27 posts
In need of a bit of help with 2D collision.
Edited by mojobojo on Reason: Initial post
So I am attempting to write some super simple collision code. The boxes will never be rotated and are able to move in 8 directions (up, down, left, right, +the combination of each). What I am having trouble with is movement diagonally where I would be moving along the side of the box. Movement code is simple position += velocity * dt. I sort of have it, only when corners meet it has some weird side effects.

https://i.imgur.com/N4PpsAz.gifv

To make it clear I purely don't understand what should be doing. Everything I try to look up on 2D collisions just tell me how to check if 2 boxes intersect and never go further. I am trying to fully understand this problem but there appear to be a lack of information on the actual problem and more people just telling each other to use box2d -_-

Here is a snippet of how it works

  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 if (player_moved) { dv2 ent_rect_pos = { entity->position.x + entity->collision.position.x, entity->position.y + entity->collision.position.y }; dv2 player_collision_pos = { new_player_position.x + local_player->collision.position.x, new_player_position.y + local_player->collision.position.y }; f64 left_check = MAX(ent_rect_pos.x, player_collision_pos.x); f64 top_check = MAX(ent_rect_pos.y, player_collision_pos.y); f64 right_check = MIN(ent_rect_pos.x + entity->collision.dimentions.w, player_collision_pos.x + local_player->collision.dimentions.w); f64 bottom_check = MIN(ent_rect_pos.y + entity->collision.dimentions.h, player_collision_pos.y + local_player->collision.dimentions.h); f64 col_result_x = left_check - right_check; f64 col_result_y = top_check - bottom_check; b32 collided = left_check <= right_check && top_check <= bottom_check; if (collided) { dv2 final_position = new_player_position; if (abs(col_result_x) > abs(col_result_y)) { if (player_moved_up) { final_position.y = ent_rect_pos.y - local_player->collision.dimentions.h - local_player->collision.position.y; } if (player_moved_down) { final_position.y = ent_rect_pos.y + local_player->collision.dimentions.h - local_player->collision.position.y; } } else { if (player_moved_left) { final_position.x = ent_rect_pos.x + entity->collision.dimentions.w; } if (player_moved_right) { final_position.x = ent_rect_pos.x - local_player->collision.dimentions.w; } } new_player_position = final_position; } } 
Simon Anciaux
1203 posts
In need of a bit of help with 2D collision.
Shouldn't this line
 1 2 3 if (player_moved_down) { final_position.y = ent_rect_pos.y + local_player->collision.dimentions.h - local_player->collision.position.y; } 
be
 1 2 3 if (player_moved_down) { final_position.y = ent_rect_pos.y + entity->collision.dimentions.h - local_player->collision.position.y; } 
And on those lines
 1 2 3 4 5 6 if (player_moved_left) { final_position.x = ent_rect_pos.x + entity->collision.dimentions.w; } if (player_moved_right) { final_position.x = ent_rect_pos.x - local_player->collision.dimentions.w; } 
don't you need to account for a local_player->collision.position.x that isn't zero ?

I don't think this would solve the problem though.

The issue seems to be that you detect that you are overlapping col_result_x and col_result_y "units" but are resolving the collision using other values (the values in the ifs (player_moved_x) ). For example, the first glitch in your video: the player is up, and going down left near the left side of the other entity. You detect that you are colliding and that x is the smallest overlap. So you want to correct x, but instead of moving the player using col_result_x (the actual overlap), you move it to the other side (final_position.x = ent_rect_pos.x + entity->collision.dimentions.w;) because he was moving left.

A few things that could help debug this king of bug:
- have the camera fixed instead of following the character to better see what is actually happening;
- since this bug require user input and you can't really put a breakpoint to debug when it's happening, you can use a log to print values and the code path that was taken. Or having a replay input system (like in handmade hero).

A side note: when posting a question like this one, try to give more context about your code. For example, explain what the position of the player represent. Is it the bottom left corner ? Is it the bottom center ? Is it the center ? Also try to describe the problem more precisely: what is happening that isn't what you want. And if you can, provide a simple reproduction code we can compile and debug.