#include "traits/PhysicsTrait.h" #include "WorldPlane.h" namespace Swan { static float epsilon = 0.05; static void collideX( BasicPhysics &phys, BodyTrait::Body &body, WorldPlane &plane, const BasicPhysics::Props &props) { bool collided = false; for (int y = (int)floor(body.top() + epsilon); y <= (int)floor(body.bottom() - epsilon); ++y) { int lx = (int)floor(body.left()); Tile &left = plane.getTile({lx, y}); if (left.isSolid) { body.pos.x = (float)lx + 1.0; collided = true; break; } int rx = (int)floor(body.right()); Tile &right = plane.getTile({rx, y}); if (right.isSolid) { body.pos.x = (float)rx - body.size.x; collided = true; break; } } if (collided) { phys.vel.x *= -props.bounciness; if (abs(phys.vel.x) < props.mushyness) phys.vel.x = 0; } } static void collideY( BasicPhysics &phys, BodyTrait::Body &body, WorldPlane &plane, const BasicPhysics::Props &props) { bool collided = false; phys.onGround = false; for (int x = (int)floor(body.left() + epsilon); x <= (int)floor(body.right() - epsilon); ++x) { int ty = (int)floor(body.top()); Tile &top = plane.getTile({x, ty}); if (top.isSolid) { body.pos.y = (float)ty + 1.0; collided = true; break; } int by = (int)floor(body.bottom()); Tile &bottom = plane.getTile({x, by}); if (bottom.isSolid) { body.pos.y = (float)by - body.size.y; collided = true; phys.onGround = true; break; } } if (collided) { phys.vel.y *= -props.bounciness; if (abs(phys.vel.y) < props.mushyness) phys.vel.y = 0; } } void BasicPhysics::update( const Swan::Context &ctx, float dt, BodyTrait::Body &body, const BasicPhysics::Props &props) { vel += (force / props.mass) * dt; force = { 0, 0 }; Vec2 dist = vel * dt; Vec2 dir = dist.sign(); Vec2 step = dir * 0.4; // Move in increments of at most 'step', on the X axis while (abs(dist.x) > abs(step.x)) { body.pos.x += step.x; collideX(*this, body, ctx.plane, props); dist.x -= step.x; } body.pos.x += dist.x; collideX(*this, body, ctx.plane, props); // Move in increments of at most 'step', on the Y axis while (abs(dist.y) > abs(step.y)) { body.pos.y += step.y; collideY(*this, body, ctx.plane, props); dist.y -= step.y; } body.pos.y += dist.y; collideY(*this, body, ctx.plane, props); } }