This project is read-only.

Calculating shape slope

Jan 4, 2010 at 9:46 AM

Hi Im trying to make a 2d demo where a car travels along a custom shape that is used as a terrain

Im able to make the center of the car collide with the terrain at a pixel level but I need to know the current slope angle so I can rotate my object to match the terrain and give the impression that it is actually traveling on it

 

Is this possible to do with your library?

 

Thank you so much for your contribution to the XNA community

Jan 4, 2010 at 2:30 PM
Edited Jan 5, 2010 at 9:19 AM

Hi EvilNando,

this is a feature I have on my TODO-List ;)

but there is a workaround to get an almost accurate result.

you need the following methods of the geometry you are colliding with:

 

GetNearestPointOnEdge()
GetEdgePathValueFromPoint()
GetPositionFromEdgePath()

 

the first method gives you a point on the outline of the shape which is the closest point to the passed position (for example the bottom of a wheel of your car).

pass the result to the second method. that method will give you a relative distance from the start of the shape.

Now add a very bit to the result and pass it to the third method. It will return another Vector2.

The difference between the result of the first method and the result of the last method is the tangent vector. to get the normal, you just need to turn the vector: (x, y) => (-y, x)

 

Vector2 GetNormal(Drawing geo, Vector2 testPoint)
{
    const float STEP = 0.001f;

    Vector2 closePoint = geo.GetNearestPointOnEdge(testPoint);
    float pathPosition = geo.GetEdgePathValueFromPoint(closePoint);
    Vector2 nextPoint = geo.GetPositionFromEdgePath(pathPosition + STEP);

    Vector2 tangent = nextPoint - closePoint;

    return new Vector2(-tangent.Y, tangent.X);
}

 

 

I hope this is what you need.

If you have two wheels you may calculate the tangent by subtracting the NearestPointOnEdge of the one wheel from the other...

 

please note: all this doesn't work with Splines yet.

Jan 5, 2010 at 5:24 AM

Omg thank you so much!

Im gonna try this and post my results

 

I was about to drop this project until I found about this ! this is soo cool thanks again!

 

 

Jan 5, 2010 at 9:28 AM
thank you too for your feedback.

I hope my library can do all the things you expect and need for your project :)

 

BTW: I forgot something... a normal should be normalized... in the code above it is not normalized. So you need to do this before returning the vector:

// I think (not sure) you have to write this:
tangent = Vector2.Normalize(tangent);
Jan 6, 2010 at 7:15 AM
Edited Jan 6, 2010 at 10:51 AM

Could you clear up the way Im supposed to handle collisions?

As far as I know I have to add shapes to a collisiondetector which throws up an event whenever shapes collide

the things is that Im not sure what to do next after I get a call to the delegate function

 

can u explain a lil bit about the composition of collisioneventargs?

whats the deal of active and passive geometry types?

 

thanks

 

edit: Ive been toying with GetNearestPointOnEdge() and it turned out to be extremely slow

 

Im using an 800x600 spritemask as a terrain for collision check the plan is to have masks at least 2000xp wide

 

:S

Jan 7, 2010 at 9:32 AM

yes, the collisiondetector manages the collisions. you can use it for this purpose ;)

when you add a geometry to the detector, you have to define if it is active or passive geometry. All active geometry is tested against all passive geometry on each Update. In common the object the player is controlling is active geometry and the world and stuff in the world is passive.

so the geometry you need the normal from should be the Passive geometry which is a property of the CollisionEventArgs.

 

about the lack of performance:

there are several options to tune the performance.

For collision detection: try to use shapes which have not much empty space. If you use SpriteShapes, trim away the transparent parts around (or make use of the SourceRectangle).

For GetNearestPointOnEdge(): this should be relatively fast for all geometry with lines (Line, LineStrip, Rect, Triangle, Polygon). But not for SpriteShapes. The border of the Shape must be computed at first and then every border-pixel must be compared. this means: the bigger the texture, the slower the performance. If you can, you should use a polygon instead of the SpriteShape.

 

BTW: on weekend i will add GetTangent() and GetNormal().

Jan 10, 2010 at 9:37 PM

sorry. I tried to implement GetTangent() and GetNormal() but there are strange bugs i don't understand... so I can not upload it this weekend...

Dec 7, 2010 at 10:28 PM

Finally!

after almost a year i finally fixed the bug.

I am very sorry for my absence... i had a stressful year ;)

but now it works. I hope you or anybody else will need this feature...