improved handling of interpolate_move calls with a distance shorter than minimum delta #10
|
@ -179,91 +179,77 @@ float get_solve_force(const object_t* a, const object_t* b, float* out_px, float
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline
|
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;
|
float dx, dy;
|
||||||
const float d = get_solve_force(this, other, &dx, &dy);
|
const float d = get_solve_force(this, other, &dx, &dy);
|
||||||
this->sprite.x += dx;
|
this->sprite.x += dx;
|
||||||
this->sprite.y += dy;
|
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;
|
static inline
|
||||||
this->sprite.y = old_y;
|
void _solve_move(object_t* this) {
|
||||||
if(!_collision_check(other, this)) {
|
// loop over all objects and check collision if applicable
|
||||||
return;
|
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
|
// 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)
|
if(dx == 0 && dy == 0)
|
||||||
return;
|
return;
|
||||||
// calculate direction x,y
|
// calculate direction x,y
|
||||||
float m = sqrtf(dx*dx + dy*dy);
|
float m = sqrtf(dx*dx + dy*dy);
|
||||||
if(dx != 0)
|
|
||||||
dx /= m;
|
dx /= m;
|
||||||
if(dy != 0)
|
|
||||||
dy /= m;
|
dy /= m;
|
||||||
dx *= max_step_size; dy *= max_step_size;
|
dx *= max_step_size; dy *= max_step_size;
|
||||||
int step_count = max_step_size / m;
|
int step_count = max_step_size / m;
|
||||||
|
|
||||||
// ensure this object would ever collide
|
// ensure this object would ever collide
|
||||||
// if it wouldn't collide anyway, just set position
|
// if it wouldn't collide anyway, just set position
|
||||||
if(!can_collide(object)) {
|
if(!can_collide(this)) {
|
||||||
object->sprite.x = target_x;
|
this->sprite.x = target_x;
|
||||||
object->sprite.y = target_y;
|
this->sprite.y = target_y;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(step_count == 0) {
|
||||||
|
this->sprite.x = target_x;
|
||||||
|
this->sprite.y = target_y;
|
||||||
|
_solve_move(this);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 1. move towards target
|
* 1. move towards target
|
||||||
* 2. check collision with every other object
|
* 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
|
// 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;
|
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;
|
const float sqdist = distx*distx + disty*disty;
|
||||||
if(sqdist > max_step_size) {
|
if(sqdist > max_step_size*max_step_size) {
|
||||||
object->sprite.x += dx;
|
this->sprite.x += dx;
|
||||||
object->sprite.y += dy;
|
this->sprite.y += dy;
|
||||||
new_x = object->sprite.x;
|
new_x = this->sprite.x;
|
||||||
new_y = object->sprite.y;
|
new_y = this->sprite.y;
|
||||||
} else {
|
} else {
|
||||||
new_x = object->sprite.x = target_x;
|
this->sprite.x = target_x;
|
||||||
new_y = object->sprite.y = target_y;
|
this->sprite.y = target_y;
|
||||||
|
new_x = target_x;
|
||||||
|
new_y = target_y;
|
||||||
}
|
}
|
||||||
|
|
||||||
// loop over all objects and check collision if applicable
|
_solve_move(this);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue