Jump to content

  • Log In with Google      Sign In   
  • Create Account

FREE SOFTWARE GIVEAWAY

We have 4 x Pro Licences (valued at $59 each) for 2d modular animation software Spriter to give away in this Thursday's GDNet Direct email newsletter.


Read more in this forum topic or make sure you're signed up (from the right-hand sidebar on the homepage) and read Thursday's newsletter to get in the running!


Platform game collision detection


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
4 replies to this topic

#1 Yohanu   Members   -  Reputation: 100

Like
0Likes
Like

Posted 04 April 2010 - 10:52 PM

Hello, i am currently writing a pseudo-3d* super mario bros 1 clone using lwjgl (Java), but i'm facing trouble with collision detection. I need to somehow check what direction an obstacle was hit from (jumping on enemies, destroy blocks etc), but i'm not sure how i can achieve this. I currently use the AABB-technique for all obstacles in the game world (i do 3d intersection checks for some game-features planned later on), but i'm uncertain what "logic" or design-pattern to apply for something like this. I have searched these forums, but i couldn't find anything specifically like this. Should more info be required, do reply and i will answer as quickly as i can. Any help would be appreciated, thanks. * 2d platformer but in a 3d world, all sprites being flat entities while the world is 3d blocks. Fixed camera in a "sidescrolling"-mode.

Sponsor:

#2 0BZEN   Crossbones+   -  Reputation: 2025

Like
0Likes
Like

Posted 05 April 2010 - 12:21 AM

for 3D boxes, you have 6 faces, so 6 potentential hit direction.

If your boxes intersect, the direction of the hit will be where the intersection along the X, Y, or Z axis are minimum.

something like that...

Quote:

bool AABBIntersect(const Vector& mina, // min vector of boxa
const Vector& maxa, // max vector of boxa
const Vector& minb, // min vector of boxb
const Vector& maxb, // max vector of boxb
Vector& ncoll, // normal of collision.
float& dcoll, // depth of intersection.
int& fcoll) // face intersected.
{
// the normal of each face.
static const Vector faces[6] =
{
Vector(-1, 0, 0), // 'left' face normal (-x direction)
Vector( 1, 0, 0), // 'right' face normal (+x direction)
Vector( 0, -1, 0), // 'bottom' face normal (-y direction)
Vector( 0, 1, 0), // 'top' face normal (+y direction)
Vector( 0, 0, -1), // 'far' face normal (-z direction)
Vector( 0, 0, 1), // 'near' face normal (+x direction)
};

// distance of collided box to the face.
float distances[6] =
{
(maxb.x - mina.x), // distance of box 'b' to face on 'left' side of 'a'.
(maxa.x - minb.x), // distance of box 'b' to face on 'right' side of 'a'.
(maxb.y - mina.y), // distance of box 'b' to face on 'bottom' side of 'a'.
(maxa.y - minb.y), // distance of box 'b' to face on 'top' side of 'a'.
(maxb.z - mina.z), // distance of box 'b' to face on 'far' side of 'a'.
} (maxa.z - minb.z), // distance of box 'b' to face on 'near' side of 'a'.
;

// scan each face, make sure the box intersects,
// and take the face with least amount of intersection
// as the collided face.
for(int i = 0; i < 6; i ++)
{
// box does not intersect face. So boxes don't intersect at all.
if(distances[i] < 0.0f)
return false;

// face of least intersection depth. That's our candidate.
if((i == 0) || (distances[i] < dcoll))
{
fcoll = i;
ncoll = faces[i];
dcoll = distances[i];
}
}
return true;
}

Everything is better with Metal.


#3 0BZEN   Crossbones+   -  Reputation: 2025

Like
0Likes
Like

Posted 05 April 2010 - 12:31 AM

and also, to improve response, you can flag to ignore faces that are 'blocked' by other blocks.

Quote:

bool AABBIntersect(const Vector& mina, // min vector of boxa
const Vector& maxa, // max vector of boxa
const Vector& minb, // min vector of boxb
const Vector& maxb, // max vector of boxb
int ignore_faces, // bitfield of face indices flagged to be ignored for collision
Vector& ncoll, // normal of collision.
float& dcoll, // depth of intersection.
int& fcoll) // face intersected.
{
// the normal of each face.
static const Vector faces[6] =
{
Vector(-1, 0, 0), // 'left' face normal (-x direction)
Vector( 1, 0, 0), // 'right' face normal (+x direction)
Vector( 0, -1, 0), // 'bottom' face normal (-y direction)
Vector( 0, 1, 0), // 'top' face normal (+y direction)
Vector( 0, 0, -1), // 'far' face normal (-z direction)
Vector( 0, 0, 1), // 'near' face normal (+x direction)
};

// distance of collided box to the face.
float distances[6] =
{
(maxb.x - mina.x), // distance of box 'b' to face on 'left' side of 'a'.
(maxa.x - minb.x), // distance of box 'b' to face on 'right' side of 'a'.
(maxb.y - mina.y), // distance of box 'b' to face on 'bottom' side of 'a'.
(maxa.y - minb.y), // distance of box 'b' to face on 'top' side of 'a'.
(maxb.z - mina.z), // distance of box 'b' to face on 'far' side of 'a'.
} (maxa.z - minb.z), // distance of box 'b' to face on 'near' side of 'a'.
;

// scan each face, make sure the box intersects,
// and take the face with least amount of intersection
// as the collided face.
for(int i = 0; i < 6; i ++)
{
// box does not intersect face. So boxes don't intersect at all.
if(distances[i] < 0.0f)
return false;

// face cannot be used for collision response as it is 'blocked'.
if(ignore_faces & (1 << i))
continue;

// face of least intersection depth. That's our candidate.
if((i == 0) || (distances[i] < dcoll))
{
fcoll = i;
ncoll = faces[i];
dcoll = distances[i];
}
}
return true;
}


If you don't do something like that, your objects will hit bumps when sliding on the floor.

Everything is better with Metal.


#4 Lightness1024   Members   -  Reputation: 739

Like
0Likes
Like

Posted 05 April 2010 - 01:08 AM

for a simple example of collision response, you always have the code of carnage engine demo:
https://sourceforge.net/projects/carnage-engine/files/
:)
its not very advanced, my system uses a "free directions" discoverer, that only works with axis +x,-x,+y,-y directions. it happens to be enough in my case.
in a general case, the good way would be that the collision manager should return contact points, and normal of contacts. then you can response with that intel.
(box2d must be doing this)


#5 Yohanu   Members   -  Reputation: 100

Like
0Likes
Like

Posted 05 April 2010 - 02:48 AM

Thanks for the replies, i ported oliii's code to Java and it works fantastic! This is much appreciated :)




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS