improved handling of interpolate_move calls with a distance shorter than minimum delta
parent
b8c856bf56
commit
a9ba15f93b
|
@ -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;
|
||||
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 = 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;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue