Page 1 of 1

Do stuff on end touch

Posted: Mon Mar 30, 2009 1:18 pm
by Matkins
I have a shape that is set to be a sensor, I need to do something when the sensor object is no longer touching/intersecting any other object. Does anyone know how I can achieve this? Thank you.

Re: Do stuff on end touch

Posted: Mon Mar 30, 2009 3:21 pm
by Robin
The first way I'd think of would be:

Code: Select all

function onsensor()
	--do stuff
end

sensorhit = true
function update(dt)
	if not intersect(sensor, otherthing) and sensorhit then
		onsensor()
		sensorhit = false
	end
end
How intersect(a, b) would be implemented depends on the rest of your game.

Re: Do stuff on end touch

Posted: Mon Mar 30, 2009 5:13 pm
by machee
The following assumes you're using love.physics and the collision/contact callback function.

Box2D (the physics library love uses) has callbacks for when a contact starts (Add), when a contact is still happening (Persist), and when a contact stops (Remove).

Currently, love has only implemented the callback for when a contact starts. As far as I understand, the next version of love will have the other 2 callbacks implemented so we can tell when a contact persists and stops, and that sounds like what you're looking for.

I've been trying to do something similar in my game. I want to know when a sensor on the bottom of my character is no longer colliding, so I can know when my character shouldn't be able to jump. I have not yet found a good solution for this.

Re: Do stuff on end touch

Posted: Tue Mar 31, 2009 4:40 am
by solsword
One possible hackaroud: re-generate the sensor (i.e. destroy the old sensor and create a new one) every single time you call update() on the world. This way, it will either collide with something or not collide at all, and you'll be able to tell whether a sensor that had stayed there would still be touching something. Unfortunately, this may not work properly given my post in the support forum about the bug where sensor objects retain some physics properties (probably as a side-effect of being created before becoming a sensor, but I'm not sure...

Re: Do stuff on end touch

Posted: Tue Mar 31, 2009 8:38 am
by Matkins
machee wrote:I've been trying to do something similar in my game. I want to know when a sensor on the bottom of my character is no longer colliding, so I can know when my character shouldn't be able to jump. I have not yet found a good solution for this.
This is how i sorted out jumping in my game...

Code: Select all

function update(dt)
	if(prevJumpButton == false and love.joystick.isDown(useJoy, 12) == true)then
		jumpInit = true
	end
	if(prevJumpButton == true)then
		jumpInit = false
	end
	if(onFloor == true)then
		local x, y = body:getVelocity()
		body:applyImpulse(forwardVelocity, -10000)
		onFloor = false
	end
	prevJumpButton = love.joystick.isDown(useJoy, 12)
end

function collision(shapedata1, shapedata2, contObj)
	if(jumpInit == true and (shapedata1 == "Feet" or shapedata2 == "Feet"))then
		onFloor = true
		forwardVelocity = speed*450
	end
end
The shapedata "Feet" belongs to the sensor at the bottom of my character. The "speed" variable I'm using here to create the "forwardVelocity" of the jump is coming from a joystick slider that i've not showed the code for, hopefully I've included enough for it to make sense.

My problem however is not with jumping. It's with crouching, and making sure the player can't stand up again if they are underneath something obstructing them to do so. I'm quite stuck with it at the moment, would be easy if I had the Remove collision callback machee mentioned.

Re: Do stuff on end touch

Posted: Wed Apr 01, 2009 3:31 am
by machee
Thanks for the code snippet.

The recreating the sensor work around solsword mentioned seems like it may work for your crouching problem. The only thing that comes to mind is a problem someone else had with sensors actually affecting other objects if you create the sensor inside them. ( http://love2d.org/forum/viewtopic.php?f=4&t=620 ) But it's something I'll try out myself with jumping.

[Edit]

Reread your code. I only seem to get a collision when my sensor first touches another object. So it seems like your code would only jump if I hit the jump key right before landing. Maybe I have a problem with my callback. Will check it out and play with your way some. Thanks again.

Re: Do stuff on end touch

Posted: Wed Apr 01, 2009 3:55 am
by osgeld
i have to note, you could quite half heartily do the same with 4 function math and xy cords in a table

Re: Do stuff on end touch

Posted: Thu Apr 02, 2009 5:06 am
by solsword
@Matkins: I think I see a problem with your approach: what if you are on a platform, and then walk off the edge without jumping. From what I can tell, you'd be able to jump in midair, because the code assumes that the only way to get airborne is to jump.

osgeld's idea of just doing the math has merit, but if the objects are curved or sloping, the math can get a bit messy. A trick that might work: store the most recent collision, and whenever you jump, check that you're on that object. To check that you're "on" something, you can use love.physics.PolygonShape.testPoint: call that method on the object that you most recently collided with, and test a point just below the character. For jumping off of slopes, I'd test two points, below the character at either extreme, and maybe a third in the middle for skinny platforms, and allow jumping if any of the tests succeeded. You might run into problems where you can't jump when you're touching a wall (or after you've touched a wall), but those could be solved by labeling all "jumpable" surfaces using setData and only storing the last "jumpable" surface collided with.

Re: Do stuff on end touch

Posted: Thu Apr 02, 2009 9:46 pm
by Alex
solsword wrote:osgeld's idea of just doing the math has merit, but if the objects are curved or sloping, the math can get a bit messy. A trick that might work: store the most recent collision, and whenever you jump, check that you're on that object. To check that you're "on" something, you can use love.physics.PolygonShape.testPoint: call that method on the object that you most recently collided with, and test a point just below the character. For jumping off of slopes, I'd test two points, below the character at either extreme, and maybe a third in the middle for skinny platforms, and allow jumping if any of the tests succeeded. You might run into problems where you can't jump when you're touching a wall (or after you've touched a wall), but those could be solved by labeling all "jumpable" surfaces using setData and only storing the last "jumpable" surface collided with.
I have an implementation of roughly the situation you're describing, but you really don't have to do anything different for sloped surfaces. All you need to do is test if the part of your object in question (however you choose to define it, there are a number of ways) is touching a surface based on the method you described, but use a point based on the rotation of the object and the normal of the collision. The math isn't too hard. Just one function to figure out your x test point and one to figure out the y point.

Code: Select all

xTest = x + (math.abs(math.cos(rot))*w + math.abs(math.sin(rot))*h)* nx
yTest = y + (math.abs(math.sin(rot))*w + math.abs(math.cos(rot))*h)* ny
Where x and y are the coordinates of your object, rot is the rotation of your object in radians, w and h are the width and height of your object measured from the centre point plus an arbitrary amount based on how far you want to sense the touch, and nx and ny are the x and y values of the normal of the collision.

This is of course not only limited to sensing things in the down direction, and is based on the need to have curved and sloped surfaces.