Jump to content
  • Advertisement
Sign in to follow this  
nes8bit

Am I on the floor please? (FPS Games)

This topic is 4814 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Does anyone have any good solutions for detecting whether the player is on the floor in a first person shooter engine? It seems to be a fairly common problem amongst FPS engines and was wondering if there was some cut 'n dry solution. As an indie developer, we're surprisingly NOT using a terrain engine...so I'm sure standard issue solutions should work. Any suggestions? Will rate for suggestions. ^_^

Share this post


Link to post
Share on other sites
Advertisement
Guest Anonymous Poster
Just cast a line straight down from the players positions and see where it hits the world... assuming you've got your collision detection code running, if not, well, it might be time to start working on that... :)

Share this post


Link to post
Share on other sites
// Object-to-object bounding-box collision detector:
short int Sprite_Collide(sprite_ptr object1, sprite_ptr object2) {

int left1, left2;
int right1, right2;
int top1, top2;
int bottom1, bottom2;

left1 = object1->x;
left2 = object2->x;
right1 = object1->x + object1->width;
right2 = object2->x + object2->width;
top1 = object1->y;
top2 = object2->y;
bottom1 = object1->y + object1->height;
bottom2 = object2->y + object2->height;

if (bottom1 < top2) return(0);
if (top1 > bottom2) return(0);

if (right1 < left2) return(0);
if (left1 > right2) return(0);

return(1);

};
object->width = <ACTUAL BITMAP WIDTH>;
object->height = <ACTUAL BITMAP HEIGHT>;

object->col_width = object->width * 0.80;
object->col_height = object->height * 0.80;

object->col_x_offset = (object->width - object->col_width) / 2;
object->col_y_offset = (object->height - object->col_height) / 2;

// Object-to-object, reduced bounding-box collision detector:
short int Sprite_Collide(sprite_ptr object1, sprite_ptr object2) {

int left1, left2;
int right1, right2;
int top1, top2;
int bottom1, bottom2;

left1 = object1->x + object1->col_x_offset;
left2 = object2->x + object2->col_x_offset;
right1 = left1 + object1->col_width;
right2 = left2 + object2->col_width;
top1 = object1->y + object1->col_y_offset;
top2 = object2->y + object1->col_y_offset;
bottom1 = top1 + object1->col_height;
bottom2 = top2 + object2->col_height;

if (bottom1 < top2) return(0);
if (top1 > bottom2) return(0);

if (right1 < left2) return(0);
if (left1 > right2) return(0);

return(1);

};


// Object-to-Point, pixel-level collision detector:
short int Sprite_Collide(sprite_ptr object, int x, int y) {

int x_offset, y_offset;
int left, right, top, bottom;


left = object->x;
right = left + object->width;
top = object->y;
bottom = top + object->height;

if (x < left) return(0);
if (x > right) return(0);

if (y < top) return(0);
if (y > bottom) return(0);

x_offset = abs(x - object->x);
y_offset = abs((y - object->y) * object->width);

if (*(object->frames[object->curr_frame] +
y_offset + x_offset) == 0) return(0);

return(1);

};

// Object-to-Point, pixel-level collision detector:
short int Sprite_Collide(sprite_ptr object, int x, int y) {

int x_offset, y_offset;
int left, right, top, bottom;


left = object->x;
right = left + object->width;
top = object->y;
bottom = top + object->height;

if (x < left) return(0);
if (x > right) return(0);

if (y < top) return(0);
if (y > bottom) return(0);

x_offset = abs(x - object->x);
y_offset = abs((y - object->y) * object->width);

if (*(object->frames[object->curr_frame] +
y_offset + x_offset) == 0) return(0);

return(1);

};
// Object-to-Point, pixel-level collision detector:
short int Sprite_Collide(sprite_ptr object, int x, int y) {

int x_offset, y_offset;
int left, right, top, bottom;


left = object->x;
right = left + object->width;
top = object->y;
bottom = top + object->height;

if (x < left) return(0);
if (x > right) return(0);

if (y < top) return(0);
if (y > bottom) return(0);

x_offset = abs(x - object->x);
y_offset = abs((y - object->y) * object->width);

if (*(object->frames[object->curr_frame] +
y_offset + x_offset) == 0) return(0);

return(1);

};

Share this post


Link to post
Share on other sites
// Full object-to-object pixel-level collision detector:
short int Sprite_Collide(sprite_ptr object1, sprite_ptr object2) {

int left1, left2, over_left;
int right1, right2, over_right;
int top1, top2, over_top;
int bottom1, bottom2, over_bottom;
int over_width, over_height;
int i, j;
unsigned char *pixel1, *pixel2;

left1 = object1->x;
left2 = object2->x;
right1 = object1->x + object1->width;
right2 = object2->x + object2->width;
top1 = object1->y;
top2 = object2->y;
bottom1 = object1->y + object1->height;
bottom2 = object2->y + object2->height;


// Trivial rejections:
if (bottom1 < top2) return(0);
if (top1 > bottom2) return(0);

if (right1 < left2) return(0);
if (left1 > right2) return(0);


// Ok, compute the rectangle of overlap:
if (bottom1 > bottom2) over_bottom = bottom2;
else over_bottom = bottom1;

if (top1 < top2) over_top = top2;
else over_top = top1;

if (right1 > right2) over_right = right2;
else over_right = right1;

if (left1 < left2) over_left = left2;
else over_left = left1;


// Now compute starting offsets into both objects' bitmaps:
i = ((over_top - object1\1->y) * object1->width) + over_left;
pixel1 = object1->frames[object1->curr_frame] + i;

j = ((over_top - object2->y) * object2->width) + over_left;
pixel2 = object2->frames[object2->curr_frame] + j;


// Now start scanning the whole rectangle of overlap,
// checking the corresponding pixel of each object's
// bitmap to see if they're both non-zero:

for (i=0; i < over_height; I++) {
for (j=0; j < over_width; j++) {
if (*pixel1 > 0) && (*pixel2 > 0) return(1);
pixel1++;
pixel2++;
}
pixel1 += (object1->width - over_width);
pixel2 += (object2->width - over_width);
}


// Worst case! We scanned through the whole darn rectangle of overlap
// and couldn't find a single colliding pixel!

return(0);

};

Share this post


Link to post
Share on other sites
Isn't that kind of a hacky solution for this? We're using newton for physics so collision code is all fine and dandy. Its just hard to keep the player on the floor and also hard to detect whether he can jump or not.

Share this post


Link to post
Share on other sites
Didn't Quake have a flag "FL_ONGROUND" that was set when an objects bounding box collided with the ground, and un-set when it stopped colliding?

http://wiki.quakesrc.org/index.php/FL_ONGROUND

Share this post


Link to post
Share on other sites
If you want to do it as proper physics (sort of) then each foot hitting the ground could exert an upwards force, so you progress in a series of small hops. It would rock if you could get it working, but I imagine it's a horrific thing to implement!
But why not assume player is on the ground unless the ground height drops suddenly below them as they move, then let them drop until their collision box re-connects with the ground?

Share this post


Link to post
Share on other sites
usually, it's just a matter of finding out if you are colliding zith a polygon with a roughly vertical normal (say, normal.y > 0.8f).

Else, all sorts of algos can be used.

Share this post


Link to post
Share on other sites
I'm using the TrueAxis physics engine in my project, but I bet the same ideas apply. For my FPS player, I loop through all of the dynamic object's collisions from the last frame, discarding any that I don't need using "continue;". For each collision, then, I check if the normal's angle is within 0.6f (radians I think), of vertical. Then I check to make sure that the collision point, is near to where the feet should be. I used an arbitrary value for this that I trialed and errored to find out, with a little epsilon of 1/32. I have a boolean variable I keep track of in all "auto" classes (short for autonomous) called "grounded". If any of the collisions meets both criteria, then the "auto" object is grounded, and is allowed to exert force to walk and to jump. Otherwise if no collision was found that meets the criteria, grounded is false, and the player can only exert 1/10 of the force for moving laterally (no jumping), because who likes an FPS where you can't bunny hop, or change direction mid-air?

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!