From a9ba15f93b5fc4cef2c1880caf885371f7a1d84b Mon Sep 17 00:00:00 2001 From: Sara Date: Sat, 24 Jun 2023 22:42:38 +0200 Subject: [PATCH] improved handling of interpolate_move calls with a distance shorter than minimum delta --- src/corelib/physics.c | 94 ++++++++++++++++++------------------------- 1 file changed, 40 insertions(+), 54 deletions(-) diff --git a/src/corelib/physics.c b/src/corelib/physics.c index 2f6ad1c..64df3ef 100644 --- a/src/corelib/physics.c +++ b/src/corelib/physics.c @@ -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; - } - - this->sprite.x = old_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); + } } } -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 /= m; + 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); } } -- 2.34.1