How To Make a Breakout Game with Corona

This is a post by Tutorial Team Member Greg Pugh, author of the Colin Turtle children’s eBook app series. You can also find him on Google+. If you like to play video games, you’ve most likely played some variant of the classic game Breakout. The goal of Breakout is to move a paddle on the […] By .

Leave a rating/review
Save for later
Share
You are currently viewing page 4 of 6 of this article. Click here to view the first page.

Working Hard or Hardly Working?

Take a moment and think about what the requirements of how the bullet will interact inside the game. The bullet needs to move around the screen, bounce off walls, and kill zombies.

Paste the following above “main();” in your main.lua file and save:

-- Bullet properties
function updatebullet()

	-- Movement
	bullet.x = bullet.x + velocityX;
	bullet.y = bullet.y + velocityY;
	
	-- If bullet hits the ceiling or left or right wall, bounce off of it
	if bullet.x < 0 or bullet.x + bullet.width > display.contentWidth then  
		velocityX = -velocityX;
	end
	
	if bullet.y < 0  then 
		velocityY = -velocityY;
	end
	
	-- If the bullet hits the bottom wall, the player has lost the game
	if bullet.y + bullet.height > player.y + player.height then 
		textBoxScreen("MY BRAINS!!", "Try Again") gameEvent = "lose";
	end
end

The local variables velocityX and velocityY will control the direction of the bullet. velocityX starts out at 3, so the bullet will move to the right; velocityY starts at -3 so it will move up the screen. Both of these velocities together means the bullet will move diagonally up and to the right.

However, the bullet shouldn’t go flying off of the screen! :] You’ll need to constrain it to the display width and height. If the bullet hits the top, left, or right sides of the screen it should ricochet. If the bullet hits the bottom of the screen, that means the player didn’t successfully bounce the ball off the paddle — and the player loses the game.

The updateBullet function looks great — now you just need to call it somewhere. But where?

Listen Up, Buster

Since the bullet needs to move around continuously (at least until the player wins or loses), you want the updateBullet function to be called over and over.

You can do this by asking Corona to call the updateBullet every time it redraws the frame. Our Zombie game runs at 60 frames per second, so Corona would call updateBullet for us automatically 60 times per second.

Paste the following code into main.lua above “main(); and save:

-- Listen for bullet and player collisions and user dragging player
function gameListeners(event)
	if event == "add" then
		Runtime:addEventListener("enterFrame", updatebullet);
		-- Bookmark A: You'll be adding some code here later
	-- Remove listeners when not needed to free up memory
	elseif event == "remove" then
		Runtime:removeEventListener("enterFrame", updatebullet);
		-- Bookmark B: You'll be adding some code here later too
	end
end

Runtime is a special top-level object in Corona. Just as you added an event listener to buttons for when the user taps on them, you can add an event listener to the runtime when a frame is about to be drawn.

Note the two spots in the code above marked “Bookmark A” and “Bookmark B”; you’ll be adding elements to the gameListeners function as you go along, so keep an eye out.

Relaunch the app in the simulator! :]

After you tap on the “Play” button, tap on the paddle, and the bullet will go bouncing around the screen. You’ve added quite a bit of complicated physics here, without adding a lot of code!

Looks like you’re fully armed — now you just need something to shoot at! :]

Where Are All The Zombies?!

You came to Atlanta looking to participate in the zombie apocalypse — but where are the zombies? What a bust!

Time to add the zombies! First, here’s a quick checklist of how the zombies should behave — besides die when you shoot them, of course! :]

  1. Add zombies to level 1.
  2. Place them on top of the background image.
  3. Place them in rows and columns to make a wall of zombies.
  4. Enable physics on them so when they are hit, they make the bullet bounce off of them.

Paste the following into main.lua above the “main();” line and save:

function gameLevel1()
	
	currentLevel = 1;

	-- Place the zombies on the top layer
	zombies:toFront();
	
	-- Number of zombies on level 1
	local numOfRows = 2;
	local numOfColumns = 2;
	
	-- Zombie position on screen
	local zombiePlacement = {x = (_W) - (zombieWidth * numOfColumns ) / 2  + 20, y = 70};
	
	-- Create zombies based on the number of columns and rows we declared
	for row = 0, numOfRows - 1 do
		for column = 0, numOfColumns - 1 do
			local zombie = display.newImage("images/zombie.png");
			zombie.name = "zombie";
			zombie.x = zombiePlacement.x + (column * zombieWidth);
			zombie.y = zombiePlacement.y + (row * zombieHeight);
			
			-- Add physics properties to zombies
			physics.addBody(zombie, "static", {density = 1, friction = 0, bounce = 0});
			zombies.insert(zombies, zombie);
		end
	end
end

Most of the code above is just positioning the zombies on the screen. After you’ve set how many rows and columns you want, there’s a loop to make each zombie appear. You don’t want the zombies overlapping each other though, so the zombieWidth and zombieHeight variables from the beginning are used to space them out.

Reload the game in the simulator, and you should see some hordes of zombies descend on Atlanta!

Hooray, there are zombies to kill! If you’d like more or fewer zombies to appear on level one, simply change the number of rows and columns from 2 to whatever you’d like.

If you’re like most people, you won’t want to stand around in the face of a zombie apocalypse — you’ll want to move around a little! :] Move on to the next section to add some player movement!

I Like to Move It, Move It

The user will control the paddle by dragging it around with touch events, so you’ll need to connect some kind of touch event handler.

Paste the following code above “main();” in main.lua and save:

-- Player movement on user's drag
function movePlayer(event)
	if event.phase == "began" then
		moveX = event.x - player.x;
	elseif event.phase == "moved" then
		player.x = event.x - moveX;
	end

	if((player.x - player.width * 0.5) < 0) then
		player.x = player.width * 0.5;
	elseif((player.x + player.width * 0.5) > display.contentWidth) then
		player.x = display.contentWidth - player.width * 0.5;
	end
end

In the code above, the paddle should only move from side to side (in the X direction), so you’ll only set the player.x variable and leave player.y alone. The paddle should also stay within the boundaries of the screen, so there are checks against going too far to the left and to the right.

Now you need to find the appropriate place to call movePlayer. That sounds like another event listener! You need to call movePlayer when the user touches and drags the paddle around, so it would make sense to call it from the gameListener function you added above to control the movement of the bullet.

Remember those bookmarks you added previously? Here’s where you’ll use them!

Paste the following line above Bookmark A in the gameListeners function:

		player:addEventListener("touch", movePlayer);

And then paste this line above Bookmark B in the gameListeners function:

		player:removeEventListener("touch", movePlayer);

Now, relaunch the app in the simulator! Start the game, and you should be able to drag the paddle around. You might notice that the bullet doesn’t bounce off the paddle yet — you won’t kill too many zombies that way! :]

Time to add some collision physics to your paddle!