in procgen/src/basic-abstract-game.cpp [270:372]
bool BasicAbstractGame::sub_step(const std::shared_ptr<Entity> &obj, float _vx, float _vy, int depth) {
if (obj->will_erase)
return false;
float ny = obj->y + _vy;
float nx = obj->x + _vx;
float margin = 0.98f;
bool is_horizontal = _vx != 0;
bool block = false;
bool reflect = false;
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
int type2 = get_obj_from_floats(nx + obj->rx * margin * (2 * i - 1), ny + obj->ry * margin * (2 * j - 1));
block = block || is_blocked(obj, type2, is_horizontal);
reflect = reflect || will_reflect(obj->type, type2);
}
}
if (reflect) {
if (is_horizontal) {
float delta;
if (_vx < 0) {
delta = ceil(nx - obj->rx) - (nx - obj->rx);
} else {
delta = floor(nx + obj->rx) - (nx + obj->rx);
}
obj->vx = -1 * obj->vx;
nx = nx + 2 * delta;
} else {
float delta;
if (_vy < 0) {
delta = ceil(ny - obj->ry) - (ny - obj->ry);
} else {
delta = floor(ny + obj->ry) - (ny + obj->ry);
}
obj->vy = -1 * obj->vy;
ny = ny + 2 * delta;
}
} else if (block) {
if (is_horizontal) {
if (grid_step) {
nx = obj->x;
} else {
nx = _vx > 0 ? (floor(nx + obj->rx) - obj->rx) : (ceil(nx - obj->rx) + obj->rx);
}
} else {
if (grid_step) {
ny = obj->y;
} else {
ny = _vy > 0 ? (floor(ny + obj->ry) - obj->ry) : (ceil(ny - obj->ry) + obj->ry);
}
}
}
obj->x = nx;
obj->y = ny;
bool block2 = false;
for (int i = (int)(entities.size()) - 1; i >= 0; i--) {
auto m = entities[i];
if (m == obj || m->will_erase) {
continue;
}
bool curr_block = false;
if (has_collision(obj, m, POS_EPS)) {
if (is_blocked_ents(obj, m, is_horizontal)) {
curr_block = true;
} else if (will_reflect(obj->type, m->type)) {
if (is_horizontal) {
float delx = m->x - obj->x;
float rsum = m->rx + obj->rx;
obj->x += _vx > 0 ? -2 * (rsum - delx) : 2 * (rsum + delx);
obj->vx = -1 * obj->vx;
} else {
float dely = m->y - obj->y;
float rsum = m->ry + obj->ry;
obj->y += _vy > 0 ? -2 * (rsum - dely) : 2 * (rsum + dely);
obj->vy = -1 * obj->vy;
}
}
if (curr_block) {
push_obj(m, obj, is_horizontal, depth);
}
}
block2 = block2 || curr_block;
}
return block || block2;
}