Create a Brick Breaker Game with the Corona SDK: Game Controls

Create a Brick Breaker Game with the Corona SDK: Game Controls

Tutorial Details
  • Technology: Corona SDK
  • Difficulty: Intermediate
  • Estimated Completion Time: 45 Minutes
This entry is part 2 of 3 in the series Create a Brick Breaker Game with the Corona SDK

In this tutorial series, we’ll be building a Brick Breaker game from scratch using the Corona SDK. The goal of this game is to control a pong-like paddle to knock a ball against a stack of bricks until they all break.


Where We Left Off. . .

If you haven’t already done so, please be sure to read part 1 of this series to fully understand the code in this tutorial.

Step 16: Function Declarations

Having declared a multi-dimensional table to hold our levels in Step 15, now declare all the functions that will be used in this app:

local addMenuScreen = {}
local tweenMS = {}
local hideAbout = {}
local rmvAbout = {}
local addGameScreen = {}
local buildLevel = {}
local movePaddle = {}
local gameListeners = {}
local startGame = {}
local update = {}
local bounce = {}
local removeBrick = {}
local alert = {}
local restart = {}
local changeLevel = {}

Step 17: Constructor Code

Now create Main(), the first function that will be called when our game starts:

local function Main()
    addMenuScreen()
end

Step 18: Add Menu Screen

The next code snippet adds the menu screen graphics to the stage and stores them in the menuScreen group:

function addMenuScreen()
    menuScreen = display.newGroup()
    mScreen = display.newImage('mScreen.png')
    startB = display.newImage('startB.png')
    startB.name = 'startB'
    aboutB = display.newImage('aboutB.png')
    aboutB.name = 'aboutB'
    menuScreen:insert(mScreen)
    startB.x = 160
    startB.y = 260
    menuScreen:insert(startB)
    aboutB.x = 160
    aboutB.y = 310
    menuScreen:insert(aboutB)

Step 19: Button Listeners

Listeners are added to the buttons to perform the tweenMS function when tapped:

	startB:addEventListener('tap', tweenMS)
	aboutB:addEventListener('tap', tweenMS)
end

Step 20: Call About Screen

This function checks which button was tapped and displays the corresponding view:

function tweenMS:tap(e)
    if(e.target.name == 'startB') then
        -- Start Game
        transition.to(menuScreen, {time = 300, y = -menuScreen.height, transition = easing.outExpo, onComplete = addGameScreen})
    else
        -- Call AboutScreen
        aboutScreen = display.newImage('aboutScreen.png')
        transition.from(aboutScreen, {time = 300, x = menuScreen.contentWidth, transition = easing.outExpo})
        aboutScreen:addEventListener('tap', hideAbout)

Step 21: Hide Menu Buttons

These lines, the conclusion of the tweenMS function from above, hide the menu screen buttons to avoid unwanted taps:

    startB.isVisible = false;
    aboutB.isVisible = false;
    end
end

Step 23: Remove About Screen

The next function tweens the about screen offstage and removes it:

function hideAbout:tap(e)
    transition.to(aboutScreen, {time = 300, x = aboutScreen.width*2, transition = easing.outExpo, onComplete = rmvAbout})
end
function rmvAbout()
    aboutScreen:removeSelf()
    -- Enable Menu Buttons
    startB.isVisible = true;
    aboutB.isVisible = true;
end

Step 24: Destroy Menu Screen

When the user taps the start button we begin the game screen creation. The first thing to do is destroy the Menu Screen:

function addGameScreen()
    -- Destroy Menu Screen
    menuScreen:removeSelf()
    menuScreen = nil

Step 25: Add Game Screen

Next we add the paddle and ball graphics:

    -- Add Game Screen
    paddle = display.newImage('paddle.png')
    ball = display.newImage('ball.png')
    paddle.x = 160
    paddle.y = 460
    ball.x = 160
    ball.y = 446
    paddle.name = 'paddle'
    ball.name = 'ball'

Step 26: Call Build Level Function

Then we build the level. This function is fully explained later in the tut:

buildLevel(levels[1])

Step 27: Scores & Levels Text

The last graphics to add are for the score and levels text:

scoreText = display.newText('Score:', 5, 2, 'akashi', 14)
scoreText:setTextColor(254, 203, 50)
scoreNum = display.newText('0', 54, 2, 'akashi', 14)
scoreNum:setTextColor(254,203,50)
levelText = display.newText('Level:', 260, 2, 'akashi', 14)
levelText:setTextColor(254, 203, 50)
levelNum = display.newText('1', 307, 2, 'akashi', 14)
levelNum:setTextColor(254,203,50)

Step 28: Start Listener

A listener is added to the background. This listener will start the game when the background is tapped:

    background:addEventListener('tap', startGame)
end

Step 29: Move Paddle

The paddle will be controlled using the device accelerometer. The data will be obtained using e.xGravity and passed to the x property of the paddle.

function movePaddle:accelerometer(e)
	-- Accelerometer Movement
	paddle.x = display.contentCenterX + (display.contentCenterX * (e.xGravity*3))

Step 30: Paddle Border Collision

To stop the paddle from leaving the stage, we create invisible borders on the sides of the screen:

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

Step 31: Build Level Function

The levels will be built by this function.

It uses a parameter to obtain the level to build, calculates its size, and runs a double for loop, one for the height and one for the width. Next, it creates a new Brick instance that is placed according to its width, height, and the number correspondig to i and j. The brick is declared as static in the physics engine as it will not be detecting the collision, that will be handle by the ball which is the only dynamic physics type.

Lastly, the brick is added to the bricks group to access it outside this function.

function buildLevel(level)
    -- Level length, height
    local len = table.maxn(level)
    bricks:toFront()
    for i = 1, len do
        for j = 1, W_LEN do
            if(level[i][j] == 1) then
                local brick = display.newImage('brick.png')
                brick.name = 'brick'
                brick.x = BRICK_W * j - OFFSET
                brick.y = BRICK_H * i
                physics.addBody(brick, {density = 1, friction = 0, bounce = 0})
                brick.bodyType = 'static'
                bricks.insert(bricks, brick)
            end
        end
    end
end

Step 32: Game Listeners

This function adds or removes the listeners. It uses a parameter to determine if the listeners should be added or removed. Note that some lines are commented as the functions to handle them have not yet been created.

function gameListeners(action)
  if(action == 'add') then
  Runtime:addEventListener('accelerometer', movePaddle)
  --Runtime:addEventListener('enterFrame', update)
  paddle:addEventListener('collision', bounce)
  --ball:addEventListener('collision', removeBrick)
  else
  Runtime:removeEventListener('accelerometer', movePaddle)
  --Runtime:removeEventListener('enterFrame', update)
  paddle:removeEventListener('collision', bounce)
  --ball:removeEventListener('collision', removeBrick)
  end
end

Step 33: Start Game

In this function we call the gameListeners function that will start the movement and game controls:

function startGame:tap(e)
    background:removeEventListener('tap', startGame)
    gameListeners('add')
    -- Physics
    physics.addBody(paddle, {density = 1, friction = 0, bounce = 0})
    physics.addBody(ball, {density = 1, friction = 0, bounce = 0})
    paddle.bodyType = 'static'
end

Step 34: Paddle-Ball Collisions

When the ball hits the paddle, the ySpeed is set to negative to make the ball go up. We also check in which side of the paddle the ball has hit to choose the side where it will move next. The collision is detected by the collision event listener added in the gameListeners function:

function bounce(e)
    ySpeed = -5
    -- Paddle Collision, check the which side of the paddle the ball hits, left, right
    if((ball.x + ball.width * 0.5) < paddle.x) then
        xSpeed = -5
    elseif((ball.x + ball.width * 0.5) >= paddle.x) then
        xSpeed = 5
    end
end
-- Run the Code
Main()

Next in the Series

In the next and final part of the series, we’ll be handling brick and wall collisions, scores, levels and the final steps to take prior to release like app testing, creating a start screen, adding an icon and, finally, building the app. Stay tuned for the final part!

Series Navigation«Create a Brick Breaker Game with the Corona SDK: Application SetupCreate a Brick Breaker Game with the Corona SDK: Collision Detection»

Note: Want to add some source code? Type <pre><code> before it and </code></pre> after it. Find out more
  • http://www.graphiics.com Graphiics

    Step 31 is too hard but i’ll try

  • http://habanerostudio.mx Dario

    Great Carlos, actually I start to develop my first game based on this good framework. I’ll be waiting the next part. Congratulations.

    Regards from Cancun Mexico

  • http://androidsmartphonenews.blogspot.com AndroidLover

    Wow… the Corona language seems like AS3, like this :)

  • MA

    Thanks,

    Can’t wait for the next part

  • Jammy

    When I build this game for iOS and try to install it on my phone, I get the following error. This is the only application I’ve ever seen generate this error: “The Info.plist for application at <> specifies a CFBundleExecutable of ${EXECUTABLE_NAME}, which does not exist”

    Any suggestions?

  • dl1606

    Hi Carlos,

    great tutorial.
    I rebuild it and it works very good. Now i started to change some things and had added different Bricks.
    But i have small problems with the code. I added other Bricks with higher density. But if i try the game , they are destroyed after one hit. The density variables are set higher but it won’t work. I have set the new Bricks to the same brick function as the other bricks. Is it necessary to set this bricks to a new function (for example brick2) or should they have a whole new group like (bricks 2).

    Thanks in advance
    Daniel

  • Anuj Khandelwal

    Hey do you know how to add keyboard button in corona SDK. I want when I press a button from keyboard it will do same function as it was doing when i directly press it with mouse.