Tuesday, February 8, 2011

Corona game continued: collision detection

Corona's docs on collision detection can be found here.

For this simple case we can easily use a "local collision listener" on the ball to both detect the collision and run some function to destroy the brick. Every collision is either in the "began" phase which occurs at the moment of collision or in the "ended" phase which occurs just as the objects stop colliding.

Build the collision system in three steps.

  1. Write a function that contains what you want to occur on collision.
     -- Collision behavior for the ball
    local function ballCollided(self, event)
    body = event.other
    --Allow the ball to rebound before we destroy any objects
    if(event.phase == "ended") then
    -- Destroy any bricks that we collide with
    if body.type == "brick" then -- The field "type" was added to the brick. See full source.
    body:removeSelf()
    end
    end
    end

  2. Tell your display object to use this function for collisions:
     ball.collision = ballCollided

  3. Let your display object know that it should listen for its own collision events:
     ball:addEventListener("collision", ball)
Now the brick vanishes just as the ball hits it and rebounds. Next creating a scene full of bricks...

Get the full source here.

Corona game continued: Circular Bodies


My first point of reference is obviously the corona docs on circular bodies. All I have to do is define a radius when creating the body.














So with just one line of code:
 physics.addBody(ball, { bounce = 1, radius = (ball.contentHeight /2) - 2})

the physics engine will treat the ball as a circle with a radius that's half the height of its image. I subtracted an extra 2 pixels from the radius to have closer interaction when colliding with other bodies.

Turning on the hybrid physics draw mode we can see that the ball is a circular body and the brick remains a rectangular body.

Next I want to register a collision between the ball and the brick followed by destroying the brick...


A simple corona game


So far I have created some very simple graphics and added them to my corona project.



The final result in the corona simulator looks like this:


I started off my learning using a tutorial by Hetal on the corona blog. I modified the code until I arrived here:
 --Setting up physics
local physics = require("physics")
physics.start()
physics.setGravity(0, 0)

--Setting up extras
local gameUI = require("gameUI")
local dragBody = gameUI.dragBody

--Add the ball
local ball = display.newImage("orange_circle.png")
ball.x = display.contentWidth/2
ball.y = display.contentHeight - ball.contentHeight
physics.addBody(ball, { bounce = 1 })


--Add a block
local block = display.newImage("orange_block.png")
block.x = display.contentWidth/2
physics.addBody(block, "static")

--Contain the ball within the scene
local leftWall = display.newRect(0,0, 1, display.contentHeight)
local topWall = display.newRect(0,0, display.contentWidth, 1)
local rightWall = display.newRect(display.contentWidth -1, 0, 1, display.contentHeight)
local bottomWall = display.newRect(0, display.contentHeight -1, display.contentWidth, 1)
physics.addBody(leftWall, "static",{bounce=0})
physics.addBody(topWall, "static", {bounce = 0})
physics.addBody(rightWall, "static", {bounce = 0})
physics.addBody(bottomWall, "static", {bounce = 0})


-- Setting up event listeners
ball:addEventListener("touch", dragBody)


The two bodies in the scene are physical bodies (using the box2d physics interface provided by corona.) By default however these bodies have a square collision box. So next I want the ball to have a circular collision body.

You can get the entire project files here.