Hanging and climbing

Topics: Developer Forum, User Forum
Jun 10, 2009 at 11:34 AM
Edited Jun 10, 2009 at 11:35 AM

Hi there! I need a suggestion for a solution. The thing is that I want my character to hang himself and climb on the edges of objects (think about a cliff for example). For that I need to detect when the character is near a "climbing" edge (which normally is a 90º vertice or near that angle). I'm not sure how to do this, as I have been thinking on two different solutions:

- Create a small geometry whose tag is "climbable". So if the character is near this geometry, it knows it can hang itself there when pressed the 'hang' button.

- Detect nearby vertices and their angles (no idea how to do that), and if it finds a suitable vertice for climbing it, hang itself when pressed the 'hang' button.

What do you think? Which one is better?

Another question is, for detecting nearby objects I was thinking on using a big geometry moving with the chatracter. Then with its OnCollision method I can detect what objects are close to the character. Is that the best way or is better (in terms of performance, etc) another? Any suggestions?

Cheers and thanks!

Jun 10, 2009 at 12:32 PM

I think your second option is best. Using a bigger geometry to detect nearby geoms sounds like a good idea to me, as you make use of the engine's broad phase stuff. As for detecting nearby verts, have a look at Geom.GetNearestDistance(). It works out which edge of a geometry is closest to a point so you could do something similar to that to detect the closest vert for climbing. To detect the angle between two edges, use the dot product (Vector2.Dot()). This will give you 0 for 90 degrees, -1 for 0 degrees and +1 for 180 degrees.

Jun 10, 2009 at 12:34 PM

Hi pnikosis

Im actually just modifying the Linecasting method to return the normals of the intersected points. I havent tested it yet but I should have it running tomorrow.

You could use this to detect nearby objects and their normals, although Im not sure about how the performance will fair if you do this a lot.

Id reccommend detecting nearby objects by using only their AABBs, seeing if they fall in a certain range, and then running the raycasting for those geoms only.

And for climbing, a tagged geom is probably better, itl allow you to use levels of any shape without having to come up with a fancy algorithm to see if you can hang somewhere.

Jun 10, 2009 at 2:01 PM

Thanks for your answers! I'll try to detect edges using roonda's sugestion and see how it performs... if I achieve to do it; if I do, I'll put the method here if someone is interested. Although probably the tagged geom is the easier way, but the goal is also to try and learn :)

Robert: The Linecasting method you mention is on the 2.1 version? Or is a method you are using in your project?

As for the nearby objects detection, I'm not sure if I understand (sorry, I'm a little new in all of this), is it better using an AABB instead of a full geometry, then? I'm not sure how to do this, with a geometry I can detect a nearby object with the OnCollision method, but with an AABB... the AABB.Intersect method needs to know both geometries.

Thanks again for your help.

Jun 10, 2009 at 3:11 PM

BTW: Another option to check nearby objects could be using the OnBroadPhaseCollision, right?

Jun 10, 2009 at 5:40 PM

I can elaborate a little on the AABB thing.

The fastest of all collision detections (beside checking for line intersections perhaps) is using an AABB (Axis Aligned Bounding Box). All geometries in the physics engine uses an AABB to represent the "area" that the geometry covers. The broad phase collision detector uses this AABB in an algorithm to see if those AABBs are touching each other.

One way of detecting if other geometries are near by, is to use a sensor. The good thing about sensors is that they are geometry based. This means you can have a sensor that is the shape of anything (not just a rectangle or circle). Another way is using the OnBroadPhaseCollision like you mention - The important thing using it is to return false in the method that is subscribed to the event. Otherwise the geometry will go further into the engine and physics will be applied to the geometry.

This is what you do:

1. Create a geometry with 4 vertices (only 2 is needed to create a box - upper left corner and lower right corner, but just use 4 for simplicity sake) with the size of the area that you want you check for near by geometries.
2. Add the geometry to the simulator
3. Subscribe to the OnBroadPhaseCollision event
4. Check if the geometry is the one that collided ( if (nearByGeom == geometryA) )

And that should be it.

Jun 10, 2009 at 6:21 PM

Thanks Genbox! Another question, if I may :)

When I create a Geom, it asks me for a Body amog the parameters (using the GeomFactory). Should I create a Body for the sensor too? Or can I use an existing body?

Jun 10, 2009 at 8:39 PM

Bodies are only points in space that controls impulse and forces applied to them. If you create a sensor, you might aswell give it its own body. Have in mind that creating two geometries with the same body does so that the geometries does not get checked against each other in the broad phase. In short: geometries attached to the same body does not collide.

Jun 10, 2009 at 8:49 PM

Thanks Genbox, another question (sorry for being so nosy): You mean that geometries attached to the same body doesn't collide between them, but they collide with the rest of the world's objects right? In that case, it would be perfect as I could create the "sensor" geometry attached to the body of the character (whose position will be updated with the body's position) and avoid to have an additional body attached to the character. Is that correct, or is it better to create also an additional body with low mass and attach it to the character (with a joint, updating its position manually or something else)?

Thanks again for your patience.

Jun 10, 2009 at 10:23 PM

Sorry for the slow repsonsetime, my email account was broken.

Indeed, as you see in our broad phase collders:

if (_geometryA.body == _geometryB.body)

Geometries with the same body does not get processed. As you wrote, it might be perfect in your situation to share the same body.
As for the mass and similar physics properties: It does not matter for sensors, they are basically static and have their collision response disabled. Physics properties does not matter on sensors.

Feel free to ask any questions you want. I'm busy putting the last hand on 2.1, but I'll always find the time to answer questions.

Jun 11, 2009 at 7:37 AM

Thanks genbox! It owrks great, I added an additional geometry called "sensor" to the character's body and works great. Probably I'll add another sensor for detection of closer objects.


Jun 14, 2009 at 4:16 PM

Hi there, I managed to find a better and simpler solution. I'll explain it if someone wants to know :)

I added a small fixed rectangle geom attached next to the character's body. This rectangle (which will be called hangingGeom) will return from its OnCollision method always false, but will check the normal of the contact list it collides. If the sum of the normal is between a certain angle (say, between 60 and 120 degrees), it will recognize the colliding geom as a "climbable" or "hangle" one.

Something like this (the ==== is the hangingGeom):

|      | ====

|      |