Collision with spawnProjectile does not collide with static objects

Hi All,

I’ve been loving Corona SDK for it’s ease of use of lua and the features Corona hands out of the box.

I’ve been blocked for a while on this scene where the Projectile (ball) after it releasing an elastic band does not collide with static objects.

This is the Ball Class:
[lua]module(…, package.seeall)
– Pass state reference
state = {};
– Bullet starts off in-active
ready = false;
– Pass audio references
shot = {};
band_stretch = {};

function newProjectile()

– Import easing plugin
local easingx = require(“easing”);

– Bullet properties
local bun_bullet = {
name = “pepsiBall”, – bun
type = “bullet”,
density=0.8,
friction=0.3,
bounce=0.6,
size = 49,
rotation = 30
}

– Init bullet
local bullet = display.newImage(“images/ammo/” … bun_bullet.name … “.png”);
– Place bullet
bullet.x = 170; bullet.y = _H + 20;
– Set up physical properties
physics.addBody(bullet, “kinematic”, {density=bun_bullet.density, friction=bun_bullet.friction, bounce=bun_bullet.bounce, radius=bun_bullet.size});

bullet.linearDamping = 0.3;
bullet.angularDamping = 0.8;
bullet.isBullet = true;
bullet.isSensor = true;
– Transition the bullet into position each time it’s spawned
transition.to(bullet, {time=600, y=_H - 140, transition = easingx.easeOutElastic});

return bullet;

end[/lua]

and this is the main scene
[lua]local storyboard = require( “storyboard” )
local scene = storyboard.newScene()

local ui = require “scripts.lib.ui”
local radlib = require “scripts.lib.radlib”

local physics = require “physics”
physics.start()
physics.setGravity(9.81) – 9.81 m/s*s in the positive y direction
physics.setScale(80) – 80 pixels per meter
physics.setDrawMode(“normal”)

local _WCenter = display.contentWidth/2;
local _HCenter = display.contentHeight/2;

local _W = display.contentWidth;
local _H = display.contentHeight + 20;


– BEGINNING OF YOUR IMPLEMENTATION

function scene:createScene( event )
local screenGroup = self.view
– Create the bounds of the “arena”
local background = display.newImage( “assets/playground.png” )
background.x = _WCenter;
background.y = _HCenter;

– Screen borders
local floor = display.newRect(_W, 0, 1, _H)
local lWall = display.newRect(0, _H, _W, 1)
local rWall = display.newRect(0, -1, _W, 1)
local ceiling = display.newRect(-1, 0, 1, _H)
screenGroup:insert(background)
screenGroup:insert(floor)
screenGroup:insert(lWall)
screenGroup:insert(rWall)
screenGroup:insert(ceiling)

staticMaterial = {density=2, friction=.3, bounce=.4}
physics.addBody(floor, “static”, staticMaterial)
physics.addBody(lWall, “static”, staticMaterial)
physics.addBody(rWall, “static”, staticMaterial)
physics.addBody(ceiling, “static”, staticMaterial)
–BALL
local ball = display.newImage( “assets/pepsiBall.png”)
ball.y = 150

physics.addBody(ball, {density=.8, friction=.3, bounce=.6, radius=49})
screenGroup:insert(ball)

– SCORE
local score = display.newText(“Score: 0”, _WCenter + 60, 5)
score:setTextColor(255, 255, 255, 255)
score.size = 25
screenGroup:insert(score)
– End step 2

local speedX = 0
local speedY = 0
local prevTime = 0
local prevX = 0
local prevY = 0

– A basic function for dragging physics objects
local function drag( event )
local ball = event.target

local phase = event.phase
if “began” == phase then
display.getCurrentStage():setFocus( ball )

– Store initial position
ball.x0 = event.x - ball.x
ball.y0 = event.y - ball.y

– Make body type temporarily “kinematic” (to avoid gravitional forces)
event.target.bodyType = “kinematic”

– Stop current motion, if any
event.target:setLinearVelocity( 0, 0 )
event.target.angularVelocity = 0

else
if “moved” == phase then
ball.x = event.x - ball.x0
ball.y = event.y - ball.y0
elseif “ended” == phase or “cancelled” == phase then
display.getCurrentStage():setFocus( nil )
event.target.bodyType = “dynamic”
ball:setLinearVelocity(speedX, speedY)
end
end

– Stop further propagation of touch event!
return true
end

function trackVelocity(event)
local timePassed = event.time - prevTime
prevTime = prevTime + timePassed
speedX = (ball.x - prevX)/(timePassed/1000)
speedY = (ball.y - prevY)/(timePassed/1000)

prevX = ball.x
prevY = ball.y
end

Runtime:addEventListener(“enterFrame”, trackVelocity)
ball:addEventListener(“touch”, drag)

–Create the hoop and scoring mechanism
local rimNet = display.newRect(_WCenter - 100, 40, 190, 9)
rimNet:setFillColor(255, 255, 255)
rimNet.alpha = 0.8
screenGroup:insert(rimNet)

local leftBorder = display.newRect(_WCenter - 100,30, 9, 25)
leftBorder:setFillColor(89,58,35)
screenGroup:insert(leftBorder)

local rightBorder = display.newRect(_WCenter + 85,30, 9, 25)
rightBorder:setFillColor(89,58,35)
screenGroup:insert(rightBorder)

physics.addBody(leftBorder, “static”, staticMaterial)
physics.addBody(rightBorder, “static”, staticMaterial)

scoreCtr = 0
local lastGoalTime = 1000

function monitorScore(event)
if event.time - lastGoalTime > 500 then
if ball.x > _WCenter - 100 and ball.x < _WCenter + 85 and ball.y < 65 then
scoreCtr = scoreCtr + 1
print(score)
lastGoalTime = event.time
score.text = "Score: " … scoreCtr
if scoreCtr == 1 then
local infoMessage = display.newText(“Mabrouk, one more”, _WCenter, _HCenter)
infoMessage:setTextColor(255, 255, 255, 255)
infoMessage.size = 25
transition.to( infoMessage, { time=2000, alpha=0, x=(_WCenter-50), y=(_HCenter-50) } )
screenGroup:insert(infoMessage)
elseif scoreCtr == 2 then
Runtime:removeEventListener(“enterFrame”, trackVelocity)
Runtime:removeEventListener(“enterFrame”, monitorScore)
storyboard.gotoScene( “play2” )
end
end
end
end

Runtime:addEventListener(“enterFrame”, monitorScore)

end

function scene:enterScene( event )
print(“Play loaded…”)

storyboard.removeAll()
end

function scene:exitScene( event )
end

function scene:destroyScene( event )
end


– END OF YOUR IMPLEMENTATION


– “createScene” event is dispatched if scene’s view does not exist
scene:addEventListener( “createScene”, scene )

– “enterScene” event is dispatched whenever scene transition has finished
scene:addEventListener( “enterScene”, scene )

– “exitScene” event is dispatched before next scene’s transition begins
scene:addEventListener( “exitScene”, scene )

– “destroyScene” event is dispatched before view is unloaded, which can be
– automatically unloaded in low memory situations, or explicitly via a call to
– storyboard.purgeScene() or storyboard.removeScene().
scene:addEventListener( “destroyScene”, scene )

return scene[/lua]

If you run this code, you’ll notice once you e.phase ends, I change t.bodyType = “dynamic”; and yet it still dosen’t collide. Any thoughts, or game logic I’m missing? [import]uid: 141821 topic_id: 29622 reply_id: 329622[/import]

Ignore previous Scene, This is actually the right version for the Scene Class:
[lua]local storyboard = require( “storyboard” )
local scene = storyboard.newScene()

– Global vars set up
_W = display.contentWidth;
_H = display.contentHeight;

– Imports
local movieclip = require(“movieclip”);
local physics = require(“physics”);
physics.start();

m = {}
m.random = math.random;

local state = display.newGroup(); – States where all

– Import projectile classes
local projectile = require(“projectile”);

– Variables setup
local projectiles_container = nil; – Where the Balls are!
local force_multiplier = 4;
local velocity = m.random(50,100);

– Visible groups setup
local background = display.newGroup();
local slingshot_container = display.newGroup();

– Build the catapult
– Front strut
local slingshot_strut_front = display.newImage(“images/slingshot_strut_front.png”,true);
slingshot_strut_front.x = 210;
slingshot_strut_front.y = _H - 25;
– Back strut
local slingshot_strut_back = display.newImage(“images/slingshot_strut_back.png”,true);
slingshot_strut_back.x = 210;
slingshot_strut_back.y = _H - 25;

– Move catapult up
slingshot_container.y = -25;

local state_value = nil;

– Audio
local shot = audio.loadSound(“sounds/band-release.aif”);
local band_stretch = audio.loadSound(“sounds/stretch-1.aif”);

– Transfer variables to the projectile classes
projectile.shot = shot;
projectile.band_stretch = band_stretch;

– Background image
local bg_image = display.newImage(“assets/playground.png”,true);
background:insert(bg_image);

local rimNet = display.newRect((_W/2), 40, 90, 9)
rimNet:setFillColor(255, 255, 255)
rimNet.alpha = 0.8

local leftBorder = display.newRect((_W/2)-5, 35, 9, 25)
leftBorder:setFillColor(89,58,35)

local rightBorder = display.newRect((_W/2)+90, 35, 9, 25)
rightBorder:setFillColor(89,58,35)

physics.addBody(leftBorder, “static”, staticMaterial)
physics.addBody(rightBorder, “static”, staticMaterial)


– BEGINNING OF YOUR IMPLEMENTATION

function scene:createScene( event )
local screenGroup = self.view
screenGroup:insert(background)
screenGroup:insert(slingshot_container)
screenGroup:insert(rimNet)
screenGroup:insert(leftBorder)
screenGroup:insert(rightBorder)
end

local function projectileTouchListener(e)
– The current projectile on screen
local t = e.target;
– If the projectile is ‘ready’ to be used
if(t.ready) then
– if the touch event has started…
if(e.phase == “began”) then
– Play the band stretch
audio.play(band_stretch);
– Set the stage focus to the touched projectile
display.getCurrentStage():setFocus( t );
t.isFocus = true;
t.bodyType = “kinematic”;

– Stop current physics motion, if any
t:setLinearVelocity(0,0);
t.angularVelocity = 0;

– Init the elastic band.
local myLine = nil;
local myLineBack = nil;

– Bunny eyes animation
–bunny_eyes:stopAtFrame(2);

– If the target of the touch event is the focus…
elseif(t.isFocus) then
– If the target of the touch event moves…
if(e.phase == “moved”) then

– If the band exists… refresh the drawing of the line on the stage.
if(myLine) then
myLine.parent:remove(myLine); – erase previous line
myLineBack.parent:remove(myLineBack); – erase previous line
myLine = nil;
myLineBack = nil;
end

– If the projectile is in the top left position
if(t.x < 105 and t.y < _H - 165)then
myLineBack = display.newLine(t.x - 30, t.y, 196, _H - 165);
myLine = display.newLine(t.x - 30, t.y, 120, _H - 152);
– If the projectile is in the top right position
elseif(t.x > 105 and t.y < _H - 165)then
myLineBack = display.newLine(t.x + 10, t.y - 25, 196, _H - 165);
myLine = display.newLine(t.x + 10, t.y - 25, 120, _H - 152);
– If the projectile is in the bottom left position
elseif(t.x < 105 and t.y > _H - 165)then
myLineBack = display.newLine(t.x - 25, t.y + 20, 196, _H - 165);
myLine = display.newLine(t.x - 25, t.y + 20, 120, _H - 152);
– If the projectile is in the bottom right position
elseif(t.x > 105 and t.y > _H - 165)then
myLineBack = display.newLine(t.x - 15, t.y + 30, 196, _H - 165);
myLine = display.newLine(t.x - 15, t.y + 30, 120, _H - 152);
else
– Default position (just in case).
myLineBack = display.newLine(t.x - 25, t.y, 196, _H - 165);
myLine = display.newLine(t.x - 25, t.y, 120, _H - 152);
end

– Set the elastic band’s visual attributes
myLineBack:setColor(214,184,130);
myLineBack.width = 8;

myLine:setColor(243,207,134);
myLine.width = 10;

– Insert the components of the catapult into a group.
slingshot_container:insert(slingshot_strut_back);
slingshot_container:insert(myLineBack);
slingshot_container:insert(t);
slingshot_container:insert(myLine);
slingshot_container:insert(slingshot_strut_front);

– Boundary for the projectile when grabbed
local bounds = e.target.stageBounds;
bounds.xMax = 200;
bounds.yMax = _H - 250;

if(e.y > bounds.yMax) then
t.y = e.y;
else

end

if(e.x < bounds.xMax) then
t.x = e.x;
else
– Do nothing
end

– If the projectile touch event ends (player lets go)…
elseif(e.phase == “ended” or e.phase == “cancelled”) then

– Remove projectile touch so player can’t grab it back and re-use after firing.
projectiles_container:removeEventListener(“touch”, projectileTouchListener);
– Reset the stage focus
display.getCurrentStage():setFocus(nil);
t.isFocus = false;

– Play the release sound
audio.play(shot);

– Remove the elastic band
if(myLine) then
myLine.parent:remove(myLine); – erase previous line
myLineBack.parent:remove(myLineBack); – erase previous line
myLine = nil;
myLineBack = nil;
end

– Launch projectile
t.bodyType = “dynamic”;
t:applyForce((160 - e.x)*force_multiplier, (_H - 160 - e.y)*force_multiplier, t.x, t.y);
t:applyTorque( 100 )
t.isFixedRotation = false;

– Wait a second before the catapult is reloaded (Avoids conflicts).
t.timer = timer.performWithDelay(1000, function(e)
state:dispatchEvent({name=“change”, state=“fire”});

if(e.count == 1) then
timer.cancel(t.timer);
t.timer = nil;
end

end, 1)

end

end

end

end

–[[

SPAWN projectile FUNCTION

]]–
local function spawnProjectile()

– If there is a projectile available then…
if(projectile.ready)then

projectiles_container = projectile.newProjectile();
– Flag projectiles for removal
projectiles_container.ready = true;
projectiles_container.remove = true;

– Reset the indexing for the visual attributes of the catapult.
slingshot_container:insert(slingshot_strut_back);
slingshot_container:insert(projectiles_container);
slingshot_container:insert(slingshot_strut_front);

– Add an event listener to the projectile.
projectiles_container:addEventListener(“touch”, projectileTouchListener);

end

end
–[[

GAME STATE CHANGE FUNCTION

]]–
function state:change(e)

if(e.state == “fire”) then

– You fired…
– new projectile please
spawnProjectile();

end

end

– Tell the projectile it’s good to go!
projectile.ready = true;
– Spawn the first projectile.
spawnProjectile();
– Create listnener for state changes in the game
state:addEventListener(“change”, state);

function scene:enterScene( event )
print(“Play loaded…”)
storyboard.removeAll()
end

function scene:exitScene( event )
end

function scene:destroyScene( event )
end


– END OF YOUR IMPLEMENTATION


– “createScene” event is dispatched if scene’s view does not exist
scene:addEventListener( “createScene”, scene )

– “enterScene” event is dispatched whenever scene transition has finished
scene:addEventListener( “enterScene”, scene )

– “exitScene” event is dispatched before next scene’s transition begins
scene:addEventListener( “exitScene”, scene )

– “destroyScene” event is dispatched before view is unloaded, which can be
– automatically unloaded in low memory situations, or explicitly via a call to
– storyboard.purgeScene() or storyboard.removeScene().
scene:addEventListener( “destroyScene”, scene )

return scene[/lua] [import]uid: 141821 topic_id: 29622 reply_id: 118901[/import]