improved handling of interpolate_move calls with a distance shorter than minimum delta #10

Merged
Sara merged 2 commits from improve-short-moves into main 2023-06-24 20:44:50 +00:00
1 changed files with 40 additions and 54 deletions

View File

@ -179,91 +179,77 @@ float get_solve_force(const object_t* a, const object_t* b, float* out_px, float
}
static inline
void _solve_collision_slide(object_t* this, object_t* other, float old_x, float old_y, float new_x, float new_y) {
void _solve_collision_slide(object_t* this, object_t* other) {
float dx, dy;
const float d = get_solve_force(this, other, &dx, &dy);
this->sprite.x += dx;
this->sprite.y += dy;
return;
this->sprite.x = old_x;
this->sprite.y = new_y;
if(!_collision_check(other, this)) {
return;
}
this->sprite.x = new_x;
this->sprite.y = old_y;
if(!_collision_check(other, this)) {
return;
static inline
void _solve_move(object_t* this) {
// loop over all objects and check collision if applicable
for(int i = 0; i < WORLD_NUM_OBJECTS; ++i) {
// get pointer to other object
object_t* other = g_objects + i;
// check collision, return if found
if(can_collide(other) && this != other && _collision_check(other, this)) {
object_broadcast_collision(other, this);
object_broadcast_collision(this, other);
_solve_collision_slide(this, other);
}
this->sprite.x = old_x;
this->sprite.y = old_y;
if(!_collision_check(other, this)) {
return;
}
}
void interpolate_move(object_t* object, const float target_x, const float target_y, const float max_step_size, const int slide) {
void interpolate_move(object_t* this, const float target_x, const float target_y, const float max_step_size, const int slide) {
// calculate step delta
float dx = target_x - object->sprite.x, dy = target_y - object->sprite.y;
float dx = target_x - this->sprite.x, dy = target_y - this->sprite.y;
if(dx == 0 && dy == 0)
return;
// calculate direction x,y
float m = sqrtf(dx*dx + dy*dy);
if(dx != 0)
dx /= m;
if(dy != 0)
dy /= m;
dx *= max_step_size; dy *= max_step_size;
int step_count = max_step_size / m;
// ensure this object would ever collide
// if it wouldn't collide anyway, just set position
if(!can_collide(object)) {
object->sprite.x = target_x;
object->sprite.y = target_y;
if(!can_collide(this)) {
this->sprite.x = target_x;
this->sprite.y = target_y;
return;
}
if(step_count == 0) {
this->sprite.x = target_x;
this->sprite.y = target_y;
_solve_move(this);
}
/*
* 1. move towards target
* 2. check collision with every other object
*/
for(int steps = 0; steps < step_count && (object->sprite.x != target_x || object->sprite.y != target_y); ++steps) {
for(int steps = 0; steps <= step_count && (this->sprite.x != target_x || this->sprite.y != target_y); ++steps) {
// move towards target, snap to target if distance is too low
const float old_x = object->sprite.x, old_y = object->sprite.y;
const float old_x = this->sprite.x, old_y = this->sprite.y;
float new_x, new_y;
const float distx = fabsf(object->sprite.x - target_x), disty = fabsf(object->sprite.y - target_y);
const float distx = fabsf(this->sprite.x - target_x), disty = fabsf(this->sprite.y - target_y);
const float sqdist = distx*distx + disty*disty;
if(sqdist > max_step_size) {
object->sprite.x += dx;
object->sprite.y += dy;
new_x = object->sprite.x;
new_y = object->sprite.y;
if(sqdist > max_step_size*max_step_size) {
this->sprite.x += dx;
this->sprite.y += dy;
new_x = this->sprite.x;
new_y = this->sprite.y;
} else {
new_x = object->sprite.x = target_x;
new_y = object->sprite.y = target_y;
this->sprite.x = target_x;
this->sprite.y = target_y;
new_x = target_x;
new_y = target_y;
}
// loop over all objects and check collision if applicable
for(int i = 0; i < WORLD_NUM_OBJECTS; ++i) {
// get pointer to other object
object_t* other = g_objects + i;
// check collision, return if found
if(can_collide(other) && object != other && _collision_check(other, object)) {
object_broadcast_collision(other, object);
object_broadcast_collision(object, other);
if(slide) {
_solve_collision_slide(object, other, old_x, old_y, new_x, new_y);
} else {
object->sprite.x = old_x;
object->sprite.y = old_y;
return;
}
}
}
_solve_move(this);
}
}