Jumping on moving platforms - lua

I've just started using Corona SDK, and I'm having some problems applying physics on moving platforms.
Basically I have a platforms moving right to left, and when a object lands on the platform there is no friction, the object fails to move with the platform, so once the platform has moved from underneath the object, the object falls to the bottom of the screen. Has anybody else had this problem? I guess maybe a physics object loses some of its attributes but i don't know which one.
I want that the object can move with the platform, same direction and velocity.
Here's a code sample:
.....
elements = display.newGroup()
elements.anchorChildren = true
elements.anchorX = 0
elements.anchorY = 1
elements.x = 0
elements.y = 0
screenGroup:insert(elements)
player = display.newImageRect("player.png",30,50)
player.anchorX = 50
player.anchorY = 50
player.x = 80
player.y = display.viewableContentHeight - 80
physics.addBody(player, "static", {density=.1, bounce=0.1, friction=1.0})
player:setLinearVelocity( 100, -600 )
screenGroup:insert(player)
.....
....
local gameStarted = false
function jumptoplatform(event)
if event.phase == "began" then
if gameStarted == false then
player.bodyType = "dynamic"
addplatformsTimer = timer.performWithDelay(1000, addplatforms, -1)
moveplatformsTimer = timer.performWithDelay(2, moveplatforms, -1)
gameStarted = true
player:setLinearVelocity( 100, -600 )
else
player:setLinearVelocity( 100, -600 )
end
end
end
function moveplatforms()
for a = elements.numChildren,1,-1 do
if(elements[a].x > -150) then
elements[a].x = elements[a].x - 6
else
elements:remove(elements[a])
end
end
end
function addplatforms()
platform1 = display.newImageRect("platform.png",200,80)
platform1.anchorX = 0
platform1.anchorY = 1
platform1.x = 450
platform1.y = yPosition()
physics.addBody(platform1, "static", {density=1, bounce=0.1, friction=1.0})
elements:insert(platform1)
end
.....
Maybe I have to add an onCollision function, to handle it?, or use joints? Any idea will be appreciated..

When you create a physics body, "static" body type means that bodies does not move under simulation and they behave as if they have infinite mass. Static bodies can be moved manually by the user, but they do not accept the application of velocity. Static bodies collide only with dynamic bodies, not with other static bodies or kinematic bodies.
(More details here: http://docs.coronalabs.com/api/type/Body/bodyType.html)
Try like this:
physics.addBody(player, "dynamic", {density=.1, bounce=0.1, friction=1.0})

Related

Avoid collision - Corona

I have initialized the object named jet to collide when it interacts with other objects, But when i move the jet and touch the ceiling or floor they are also exploding. How to avoid getting collision function with ceiling & Floor? Here is the code.
Ceiling Object
ceiling = display.newImage("invisibleTile.png")
ceiling:setReferencePoint(display.BottomLeftReferencePoint)
ceiling.x = 0
ceiling.y = 0
physics.addBody(ceiling, "static", {density=.1, bounce=0.1, friction=.2})
screenGroup:insert(ceiling)
local groundShape = { -280,-20, 280,-20, 280,20, -280,20 }
Floor Object
theFloor = display.newImage("invisibleTile.png")
theFloor:setReferencePoint(display.BottomLeftReferencePoint)
theFloor.x = 0
theFloor.y = 300
physics.addBody(theFloor, "static", {density=.1, bounce=0.1, friction=.2, shape=groundShape })
screenGroup:insert(theFloor)
Jet Object
jetSpriteSheet = sprite.newSpriteSheet("greenman.png", 128, 128)
jetSprites = sprite.newSpriteSet(jetSpriteSheet, 1, 4)
sprite.add(jetSprites, "jets", 1, 15, 500, 0)
jet = sprite.newSprite(jetSprites)
jet.x = 180
jet.y = 280
jet:prepare("jets")
jet:play()
**jet.collided = false**
physics.addBody(jet, {density=0.1, bounce=0.5, friction=1, radius=12})
explosive method
function explode()
explosion.x = jet.x
explosion.y = jet.y
explosion.isVisible = true
explosion:play()
jet.isVisible = false
timer.performWithDelay(3000, gameOver, 1)
end
Collision method
function onCollision(event)
if event.phase == "began" then
if jet.collided == false then
jet.collided = true
jet.bodyType = "static"
explode()
storyboard.gotoScene("restart", "fade", 400)
end
end
end
Where exactly need to specify the condition to avoid colloids objects ?please help me to resolve this issue
Note, if you want to not detect collisions all by themselves, you should filter collisions. This link. contains a helpful table and tutorial to help you determine the maskbits and categorybits. Another alternative is group indexing, which you can read more on the first link. at the end of the document.
But, from what i see on your code, your ceiling and floor might be exploding as well. is happening is that your collision function onCollision is treating all objects the same. You would need to assign a name to your jet object jet.name = "jet", then, on your collision function check if the object really is the jet:
function onCollision(event)
if event.phase == "began" and "jet" == event.object1.name then
if jet.collided == false then
jet.collided = true
jet.bodyType = "static"
explode()
storyboard.gotoScene("restart", "fade", 400)
end
end
end
Note that you should also assign a name to all other physics objects, in case you would like to do something special with each body, and don't forget to reset jet.collided once you restart your game, if it implements it.
Read more about collision detection on the Corona Docs.

Corona SDK : How to identify the collision object?

I'm a beginner in Corona developping and i've to problem to identify the collision between 3 objects. In fact, this is my code :
The first object is my player :
player = display.newImageRect("ballon.png", 150,170 )
player.anchorX = 0.5
player.anchorY = 0.5
player.x = display.contentCenterX - 450
player.y = display.contentCenterY+250
physics.addBody(player, "static", {density=0.1, bounce=0.1, friction=0.1,})
player.myName="player"
screenGroup:insert(player)
The second object is created within a function :
function addWindSlow(self,event)
height = math.random(display.contentCenterY - 200, display.contentCenterY + 200)
windslow = display.newImage( "wind-neg.png")
windslow.x = display.contentWidth
windslow.y = height
windslow.speed = 4
windslow.myName="windslow"
physics.addBody(windslow, "static", {density = 0.1, bounce = 0, isSensor = false})
elements:insert(windslow) end
function addWindFast(self,event)
height = math.random(display.contentCenterY - 200, display.contentCenterY + 200)
windfast = display.newImage( "wind-pos.png")
windfast.x = display.contentWidth
windfast.y = height
windfast.speed = 4
windfast.myName="windfast"
physics.addBody(windfast, "static", {density = 0.1, bounce = 0, isSensor = false})
elements:insert(windfast) end
And finally, the thirth object is the same but called "addWindFast() with a different image"
So i would like to know once my player is on collision with the windslow, i need to do an action... and if it's the object windfast, another action. That's my code :
function onCollision( event )
if ( event.phase == "began" ) then
if event.other.windslow and event.other.isVisible==true then
print("windslow has been touch !")
end
end
end
I found something about the pre-collision, I'll use it once i got the information how to "identify" the object...I'll need to prevent the collision and avoid it if the player is going to touch the windfast or windslow.
We thank you for all dude !
It looks like windslow and windfast are defined outside of onCollision event handler so you should compare to those:
function onCollision( event )
if ( event.phase == "began" ) then
if event.other == windslow and event.other.isVisible==true then
print("windslow has been touch !")
end
if event.other == windfast and event.other.isVisible==true then
print("windfast has been touch !")
end
end
end -- (missing from your post but probably in your code)
The above assumes that you have registered for collision events on your player. You could also register a different collision handler on each wind:
windslow:addEventListener("collision", onCollisionSlow)
windfast:addEventListener("collision", onCollisionFast)
In that case the two collision handlers could just check if event.other == player. The advantage of that is you are separating the code for each one. You could of course do the same with your player handler:
function onCollisionSlow(other)
print('collided with slow')
end
function onCollisionFast(other)
print('collided with fast')
end
collisionHandlers = {
[windslow] = onCollisionSlow,
[windfast] = onCollisionFast,
}
function onCollision( event )
if ( event.phase == "began" ) then
collisionFunc = collisionHandlers[event.other]
if collisionFunc ~= nil and event.other.isVisible then
collisionFunc(event.other)
end
end
end
You could identify the other object with the myName property you've specified.
For example:
function onCollision( event )
if ( event.phase == "began" ) then
if (event.other.myName == "windslow" and event.other.isVisible==true) then
print("windslow has been touched!")
elseif (event.other.myName = "windfast" and event.other.isVisible==true) then
print("windfast has been touched!")
end
end

remove all spawned coins

What is the best way to remove all spawned coins when the game is over?
Here is the code that spawns the coins:
screenGroup = self.view
coin = {}
coinspawn = function()
i = display.newSprite( imageSheet1, sequenceData1 )
i.x = display.contentWidth
i.y = math.random(0, display.contentHeight-50)
i:play()
i.collided = true
i.name = "coin"
physics.addBody(i, "dynamic",
{density=.1, bounce=0.1, friction=.2, shape= shape2 ,filter=playerCollisionFilter }
)
--player.gravityScale = 0.5
coinIntro = transition.to(i,{time=2500, x=display.contentWidth - display.contentWidth -500 ,onComplete=jetReady , transition=easing.OutExpo } ) --
coin[#coin+1] = i
end
tmrcoin = timer.performWithDelay( 1000, coinspawn, 0 )
First you would remove all coins from the display. Then you would clear the coin table:
for i=1,#coin do
coin[i]:removeSelf()
end
coin = {} -- forget all coins
Assuming coin table is the only other place you store your coins, this will do it.
Note that you can't use coin[i]=nil in the loop after removeSelf: as soon as table has holes, the # operator is basically unusable. You can't use table.remove either, because i gets incremented every time, so you'll miss items (try, you'll see). Same issue with pairs: you can't edit a table while iterating through it. You could however do this:
local numCoins = #coin
for i=1,numCoins do
coin[i]:removeSelf()
coin[i]=nil
end
-- now coin is {}
The only reason I can think of to nil N items instead of letting the gc take care of it with one table = {} statement is if you have more than one reference to your coin table (which I would rename to coins, BTW, for clarity).

Cannot translate an object before collision is resolved

When I compile this is showing
error: Cannot translate an object before collision is resolved
and when I'm building app for android it shows me an error#5 (null).
Here's my code:
function onLocalCollision(meteor, event)
if event.phase == "began" then
if event.object1.myName == "meteor" and
event.object2.myName == "rocket" then
score = score - 1
scoreNumber.text = score
restart.isVisible = true
meteor.x = 500
meteor.y = 300
meteor2.x = 500
meteor2.y = 200
meteor3.x = 500
meteor3.y = 100
event.object2.alpha = 0.2
rocket:applyForce(-150,0,rocket.x,rocket.y)
lives = lives -1
livesNumber.text = lives
if lives < 1 then
lives = 3
score = 0
scoreNumber.isVisible = false
livesText.isVisible = false
livesNumber.isVisible=false
hearticon.isVisible = false
scoreText.isVisible = false
gameover.isVisible = true
restart.x = 100000
end
end
end
end
meteor.collision = onLocalCollision
Runtime:addEventListener("collision", meteor)
The problem with your code is that you cannot translate during a collision (function) so if you just say:timer.performWithDelay(100, function() rocket:applyForce(-150,0,rocket.x,rocket.y) end, 1) it should resolve your problem and/or just create a callback function.
"Modifying Objects
The objects involved in the collision should not be removed or any of it's properties altered during a collision event. You should use timer.performWithDelay() if they want to modify object position values or other properties within the collision events.
Removing the object or modifying the properties in the collision event could cause the simulator to crash."
http://docs.coronalabs.com/api/event/collision/index.html

spawning objects not removing after leaving scene

Hi my objects are not removing after leaving the scene, i have tried to purging and removing the scene, but the objects will just keep on spawning in a other scene?
local badclout1 = {}
local bad1Group = display.newGroup()
local function spawnBC1()
local badclouts1 = display.newImage("BCloud1.png")
badclouts1.x = math.random(0, _W)
physics.addBody( badclouts1, "dynamic", { density=.1, bounce=.1, friction=.2, radius=45 } )
badclouts1.name = "BCloud1"
badclouts1.bodyType = "kinematic"
badclouts1.isSensor = true
badclouts1.y = math.random(-100, -50)
badclouts1.index = #badclout1 + 1
bad1Group:insert(badclouts1)
badclouts1.rotation = math.random(-10,10) -- Rotate the object
badclouts1:setLinearVelocity(0, math.random(speeda1, speedb1)) -- Drop down
badclout1[badclouts1.index] = badclouts1
tmrSpawn1 = timer.performWithDelay(math.random(spawna, spawnb), spawnBC1)
return badclouts1
end
tmrSpawn1 = timer.performWithDelay(math.random(1000, 10000), spawnBC1)
local function removeBomb()
for i, v in pairs(badclout1) do
if badclout1[i].y >1000 then
badclout1[i]:removeSelf()
badclout1[i] = nil
end
end
end
Runtime:addEventListener("enterFrame", removeBomb)
is there something in my code that keeps it on the screen ?
You need to cancel your performWithDelay function using timer.cancel(tmrSpawn1). Because you're calling it recursively, it will just keep going until you cancel it.

Resources