My lava only hurts once :) How to check if object still in contact?

Im making a platformer type game. I have a block of lava on the floor and when I run over it I trigger a collision and my player takes damage (that parts all good).

However if I stand my man on the lava he takes the initial damage but then is perfectly safe just standing there on burning hot lava! How do I check if he’s moved off the lava and repeatedly damage him if he hasn’t?

Are you using the physics engine to detect collisions?

Yes Im using the physics engine. I use a collision event listener…

Hi @joel73,

OK, well the concept of one object being “inside” another (like a character inside a pool of water or similar) is outlined in " Part II" of this tutorial:

https://coronalabs.com/blog/2013/01/08/working-with-multi-element-physics-bodies/

The general idea is that you need to detect when the character enters the bounds of the other object in the “began” phase, and then detect the “ended” phase for the character leaving the bounds of the other object.

Hope this helps,

Brent

Thanks! I wasn’t aware of the “began” and “ended” phases. I think they should do the trick.

At the beginning phase Ill infinitely performWithDelay my damage function, then Ill cancel the timer on the ended phase… 

Ill try it out tomorrow and report back. Thanks!  :slight_smile:

 Hi,

 @Brent: you shouldn’t use too complicated things. He just wanna detect if player’s leaving the lava or not, so using collision phase as you said is enough ( the multi-element isn’t needed here )

 @joel73: maybe my code can help :slight_smile:

local function listener(event) --check if your player collide with Lava if isCollideWithLava then local phase = event.phase if "began" == phase then player.timerDamByLava = timer.performWithDelay(100,function() player:damByLava() end,0) elseif "ended" == phase then if player.timerDamByLava then timer.cancel(player.timerDamByLava) player.timerDamByLava = nil end end end end player:addEventListener("collision",listener)

Hello, This is a sample project i made to help you understand how to do what you want… 

NOTE: GO TO CORONA SIMULATOR AND MAKE A NEW PROJECT AND OPEN MAIN.LUA THEN ADD THIS CODE INTO IT AND SAVE AND DRAG THE WHITE BOX IT THE RED BOX AND LET GO AND LOOK AT THE COSOLE AND SEE WHAT HAPPENS… THEN DRAG THE WHITE BOX OUT OF THE RED BOX AND THEN YOULL SEE THAT THE CONSOLE STOPS PRINTING “-1 Health”

local physics = require("physics") physics.start() local healthTimer local lava = display.newRect( display.contentCenterX, 250, 70, 70 ) physics.addBody( lava, "static", { bounce = 0 }) lava:setFillColor( 1, 0, 0 ) local player = display.newRect( display.contentCenterX, 100, 50, 50 ) physics.addBody( player, "dynamic", { bounce = 0 }) player.gravityScale = 0 local function dragPlayer(event) local player = event.target if event.phase == "began" then player.moving = true player.parent:insert(player) display.getCurrentStage():setFocus( player ) player.x0 = event.x - player.x player.y0 = event.y - player.y elseif event.phase == "moved" then if player.moving == false then return false end player.x = event.x - player.x0 player.y = event.y - player.y0 elseif event.phase == "ended" or event.phase == "cancelled" then player.moving = false display.getCurrentStage():setFocus( nil ) end end player:addEventListener( "touch", dragPlayer ) local function duringLava() print("-1 Health") end local function onCollision(event) if event.phase == "began" then healthTimer = timer.performWithDelay( 1000, duringLava, -1) elseif event.phase == "ended" then timer.cancel(healthTimer) end end player:addEventListener( "collision", onCollision )

So this sample code works like this… so when the player is collided with the lava then the healthTimer starts and when the health timer starts it calls the duringLava function one timer every

second infinite times and when the collision ended the timer gets cacelled… So in the duringLava function you could add your health remover function or whatever you might have. 

Good Luck!

Hi all,

One major point to be aware of is the physics engine potentially triggering multiple collisions when the player hits the lava. This could happen if there is any amount of bounce/restitution on either body. Sometimes these events are so miniscule, you can’t even see them visibly occur, but the engine is seeing them.

Now, in the case of starting a timer on the “began” phase and cancelling the timer on the “ended” phase, that probably wouldn’t matter. Even if 7 actual collisions occurred (internally if not visibly), the code would just start and cancel the first 6 timers before the object settled down into a stable position, then the 7th timer would begin and the player would start taking damage.

This is why, ultimately, I recommend using the “foot sensor” method, assuming the player is like a typical plaftormer character that stands upright. Making a small, separate foot sensor body element (as a “sensor” type) will help ensure that the player only triggers the “began” phase when initially contacting the lava, and the “ended” phase when fully off the lava. And that is why I pointed the OP to the multi-element collision tutorial, because making a foot sensor involves a 2-element physics body and collision detection solely on the foot sensor for surfaces that the “feet” will touch, like lava. Yes it’s more complicated, but it will save hassle/confusion down the road and provide for a better game groundwork.

@joel73, if you’re interested in reading about the “foot sensor” method, see this tutorial:

https://coronalabs.com/blog/2013/02/19/more-physics-tricks-explained/

Take care,

Brent

Well maybe if he needs bounce he could also on began and ended phase remove bounce and then add it again… Its LUA there’s a million ways to do one thing  :smiley:

Yes, of course there are mulitple solutions to this. :slight_smile:

Of course, you can’t change the bounce or friction values on an object after the body is created, unless you use the PhysicsContact object… and that’s a very advanced topic which I wouldn’t present to a new developer.

Brent

Thanks for everyone’s input on this! Its given me a lot of food for thought. I think I will implement that “foot sensor” idea into my game for sure, I think it will help in a couple areas.

As far as my lava problem goes: With the help of the posted code I was able to use the BEGAN and ENDED phases of a collision to properly stop him getting hurt when he moves off the lava. Ive now run into another problem though :frowning:

Besides the lava I also have a flame thrower that shoots out from the wall. For now the “flamethrower” is just a rectangle that has the same properties of my lava, except the rectangle is triggered to appear and then disappear 5 seconds later, as if its firing. Its set as a sensor so I can stand inside the “flames”. 

It works great if I walk into the flame and then back out. However if I’m standing in the rectangle/flame and then the rectangle gets removed with display.remove, I still keep taking damage. The ended phase never gets called. I also tried transition.to to move the rectangle away from the player, ended phase doesn’t seem to be called here either. 

Ive been trying lots of ways to solve this problem, but they all seem to get too complex (and dont work). Is there something simple I’m missing?

You could write a function to see if the rectangle is there and is its not then the damage stops and if it is then the damage continues… And add that function on an enterFrame listener…

It turns out that if I make the “flame” a dynamic body instead of static, and then transition it away from the player it ends the collision phase.

Maybe “static” bodies don’t register collisions when you move them with transition.to? Whatever the case, I think I can make it work now :) 

Is your flame thrower a static body also? Cause static doesn’t collide with static…

It was static, but my dynamic player was able to detect a collision with it. Now I’m making them both dynamic… although Ive put the gravityscale of the flamethrower to zero so it doesnt fall.

Well if it works then it works :slight_smile: I’d recommend you mark this forum as answered and if you have anymore questions then make a new post! Thanks and Good Luck with your game!

I think it works…  :unsure: Still ironing it out. I’m on the right track though. Thanks so much for everyone’s help!!! Ill go ahead and mark it as solved.

Are you using the physics engine to detect collisions?

Yes Im using the physics engine. I use a collision event listener…

Hi @joel73,

OK, well the concept of one object being “inside” another (like a character inside a pool of water or similar) is outlined in " Part II" of this tutorial:

https://coronalabs.com/blog/2013/01/08/working-with-multi-element-physics-bodies/

The general idea is that you need to detect when the character enters the bounds of the other object in the “began” phase, and then detect the “ended” phase for the character leaving the bounds of the other object.

Hope this helps,

Brent