Sfoglia il codice sorgente

new trait system, split Body into Body and Physics

opengl-renderer-broken
Martin Dørum 4 anni fa
parent
commit
b2fd4178df

+ 10
- 6
core.mod/src/entities/ItemStackEntity.cc Vedi File

static std::uniform_real_distribution vy(-2.3f, -1.2f); static std::uniform_real_distribution vy(-2.3f, -1.2f);


item_ = &ctx.world.getItem(item); item_ = &ctx.world.getItem(item);
body_.pos_ = pos;
body_.pos_.y += 0.5 - body_.size_.y / 2;
body_.vel_ += Swan::Vec2{ vx(ctx.world.random_), vy(ctx.world.random_) };
body_.pos = pos;
body_.pos.y += 0.5 - body_.size.y / 2;
physics_.vel += Swan::Vec2{ vx(ctx.world.random_), vy(ctx.world.random_) };
} }


ItemStackEntity::ItemStackEntity(const Swan::Context &ctx, const PackObject &obj): ItemStackEntity::ItemStackEntity(const Swan::Context &ctx, const PackObject &obj):
SDL_Texture *tex = item_->image_.texture_.get(); SDL_Texture *tex = item_->image_.texture_.get();
Swan::TexColorMod darken(tex, 220, 220, 220); Swan::TexColorMod darken(tex, 220, 220, 220);


win.showTexture(body_.pos_, tex, &rect,
win.showTexture(body_.pos, tex, &rect,
{ .hscale = 0.5, .vscale = 0.5 }); { .hscale = 0.5, .vscale = 0.5 });
} }


void ItemStackEntity::update(const Swan::Context &ctx, float dt) {
physics(ctx, dt, { .mass = MASS, .bounciness = 0.6 });
}

void ItemStackEntity::tick(const Swan::Context &ctx, float dt) { void ItemStackEntity::tick(const Swan::Context &ctx, float dt) {
despawn_timer_ -= dt; despawn_timer_ -= dt;
if (despawn_timer_ <= 0) if (despawn_timer_ <= 0)
} }


void ItemStackEntity::deserialize(const Swan::Context &ctx, const PackObject &obj) { void ItemStackEntity::deserialize(const Swan::Context &ctx, const PackObject &obj) {
body_.pos_ = obj.at("pos").as<Swan::Vec2>();
body_.pos = obj.at("pos").as<Swan::Vec2>();
item_ = &ctx.world.getItem(obj.at("item").as<std::string>()); item_ = &ctx.world.getItem(obj.at("item").as<std::string>());
} }


Swan::Entity::PackObject ItemStackEntity::serialize(const Swan::Context &ctx, msgpack::zone &zone) { Swan::Entity::PackObject ItemStackEntity::serialize(const Swan::Context &ctx, msgpack::zone &zone) {
return { return {
{ "pos", msgpack::object(body_.pos_, zone) },
{ "pos", msgpack::object(body_.pos, zone) },
{ "tile", msgpack::object(item_->name_, zone) }, { "tile", msgpack::object(item_->name_, zone) },
}; };
} }

+ 3
- 3
core.mod/src/entities/ItemStackEntity.h Vedi File

ItemStackEntity(const Swan::Context &ctx, const PackObject &obj); ItemStackEntity(const Swan::Context &ctx, const PackObject &obj);


void draw(const Swan::Context &ctx, Swan::Win &win) override; void draw(const Swan::Context &ctx, Swan::Win &win) override;
void update(const Swan::Context &ctx, float dt) override;
void tick(const Swan::Context &ctx, float dt) override; void tick(const Swan::Context &ctx, float dt) override;
void deserialize(const Swan::Context &ctx, const PackObject &obj) override; void deserialize(const Swan::Context &ctx, const PackObject &obj) override;
PackObject serialize(const Swan::Context &ctx, msgpack::zone &zone) override; PackObject serialize(const Swan::Context &ctx, msgpack::zone &zone) override;
static constexpr float MASS = 80; static constexpr float MASS = 80;
static constexpr Swan::Vec2 SIZE = Swan::Vec2(0.5, 0.5); static constexpr Swan::Vec2 SIZE = Swan::Vec2(0.5, 0.5);
static constexpr float DESPAWN_TIME = 5 * 60; static constexpr float DESPAWN_TIME = 5 * 60;
static constexpr float BOUNCINESS = 0.6;


ItemStackEntity(): PhysicsEntity(SIZE, MASS) {
PhysicsEntity::body_.bounciness_ = 0.6;
}
ItemStackEntity(): PhysicsEntity(SIZE) {}


float despawn_timer_ = DESPAWN_TIME; float despawn_timer_ = DESPAWN_TIME;
Swan::Item *item_ = NULL; Swan::Item *item_ = NULL;

+ 10
- 10
core.mod/src/entities/PlayerEntity.cc Vedi File



PlayerEntity::PlayerEntity(const Swan::Context &ctx, Swan::Vec2 pos): PlayerEntity::PlayerEntity(const Swan::Context &ctx, Swan::Vec2 pos):
PlayerEntity(ctx) { PlayerEntity(ctx) {
body_.pos_ = pos;
body_.pos = pos;
} }


PlayerEntity::PlayerEntity(const Swan::Context &ctx, const PackObject &obj): PlayerEntity::PlayerEntity(const Swan::Context &ctx, const PackObject &obj):


void PlayerEntity::draw(const Swan::Context &ctx, Swan::Win &win) { void PlayerEntity::draw(const Swan::Context &ctx, Swan::Win &win) {
body_.outline(win); body_.outline(win);
anims_[(int)state_].draw(body_.pos_ - Swan::Vec2(0.2, 0.1), win);
anims_[(int)state_].draw(body_.pos - Swan::Vec2(0.2, 0.1), win);
} }


void PlayerEntity::update(const Swan::Context &ctx, float dt) { void PlayerEntity::update(const Swan::Context &ctx, float dt) {


// Move left // Move left
if (ctx.game.isKeyPressed(SDL_SCANCODE_A) || ctx.game.isKeyPressed(SDL_SCANCODE_LEFT)) { if (ctx.game.isKeyPressed(SDL_SCANCODE_A) || ctx.game.isKeyPressed(SDL_SCANCODE_LEFT)) {
body_.force_ += Swan::Vec2(-MOVE_FORCE, 0);
physics_.force += Swan::Vec2(-MOVE_FORCE, 0);
state_ = State::RUNNING_L; state_ = State::RUNNING_L;
} }


// Move right // Move right
if (ctx.game.isKeyPressed(SDL_SCANCODE_D) || ctx.game.isKeyPressed(SDL_SCANCODE_RIGHT)) { if (ctx.game.isKeyPressed(SDL_SCANCODE_D) || ctx.game.isKeyPressed(SDL_SCANCODE_RIGHT)) {
body_.force_ += Swan::Vec2(MOVE_FORCE, 0);
physics_.force += Swan::Vec2(MOVE_FORCE, 0);
if (state_ == State::RUNNING_L) if (state_ == State::RUNNING_L)
state_ = State::IDLE; state_ = State::IDLE;
else else
bool jump_pressed = ctx.game.isKeyPressed(SDL_SCANCODE_SPACE); bool jump_pressed = ctx.game.isKeyPressed(SDL_SCANCODE_SPACE);


// Jump // Jump
if (body_.on_ground_ && jump_pressed && jump_timer_.periodic(0.5)) {
body_.vel_.y = -JUMP_VEL;
if (physics_.on_ground && jump_pressed && jump_timer_.periodic(0.5)) {
physics_.vel.y = -JUMP_VEL;
} }


// Fall down faster than we went up // Fall down faster than we went up
if (!body_.on_ground_ && (!jump_pressed || body_.vel_.y > 0))
body_.force_ += Swan::Vec2(0, DOWN_FORCE);
if (!physics_.on_ground && (!jump_pressed || physics_.vel.y > 0))
physics_.force += Swan::Vec2(0, DOWN_FORCE);


if (state_ != oldState) if (state_ != oldState)
anims_[(int)state_].reset(); anims_[(int)state_].reset();
anims_[(int)state_].tick(dt); anims_[(int)state_].tick(dt);


PhysicsEntity::update(ctx, dt);
physics(ctx, dt, { .mass = MASS });
} }


void PlayerEntity::tick(const Swan::Context &ctx, float dt) { void PlayerEntity::tick(const Swan::Context &ctx, float dt) {
for (ItemStackEntity *ent: ctx.plane.getEntsOfType<ItemStackEntity>()) { for (ItemStackEntity *ent: ctx.plane.getEntsOfType<ItemStackEntity>()) {
float squared_dist = float squared_dist =
(getBody().getBounds().bottomMid() - ent->getBody().getBounds().center())
(body_.bottomMid() - ent->get(Swan::BodyTrait::Tag{}).center())
.squareLength(); .squareLength();


if (squared_dist < 0.5 * 0.5) { if (squared_dist < 0.5 * 0.5) {

+ 1
- 1
core.mod/src/entities/PlayerEntity.h Vedi File

static constexpr Swan::Vec2 SIZE = Swan::Vec2(0.6, 1.9); static constexpr Swan::Vec2 SIZE = Swan::Vec2(0.6, 1.9);


PlayerEntity(const Swan::Context &ctx): PlayerEntity(const Swan::Context &ctx):
PhysicsEntity(SIZE, MASS), inventory_(INVENTORY_SIZE),
PhysicsEntity(SIZE), inventory_(INVENTORY_SIZE),
anims_{ anims_{
Swan::Animation(ctx.resources.getImage("core/entity/player-still"), 0.8), Swan::Animation(ctx.resources.getImage("core/entity/player-still"), 0.8),
Swan::Animation( Swan::Animation(

+ 1
- 0
libswan/CMakeLists.txt Vedi File

add_library(libswan SHARED add_library(libswan SHARED
src/traits/BodyTrait.cc src/traits/BodyTrait.cc
src/traits/PhysicsTrait.cc
src/Animation.cc src/Animation.cc
src/Chunk.cc src/Chunk.cc
src/Clock.cc src/Clock.cc

+ 13
- 8
libswan/include/swan/Entity.h Vedi File

#include "common.h" #include "common.h"
#include "log.h" #include "log.h"
#include "traits/BodyTrait.h" #include "traits/BodyTrait.h"
#include "traits/PhysicsTrait.h"


namespace Swan { namespace Swan {


size_t generation_; size_t generation_;
}; };


class PhysicsEntity: public Entity, public BodyTrait::HasBody {
class PhysicsEntity: public Entity, public BodyTrait, public PhysicsTrait {
public: public:
PhysicsEntity(Vec2 size, float mass):
body_(size, mass) {}
PhysicsEntity(Vec2 size): body_({ .size = size }) {}


virtual BodyTrait::Body &getBody() override { return body_; }
BodyTrait::Body &get(BodyTrait::Tag) override { return body_; }
PhysicsTrait::Physics &get(PhysicsTrait::Tag) override { return physics_; }


virtual void update(const Context &ctx, float dt) override {
body_.standardForces();
body_.update(ctx, dt);
void physics(
const Context &ctx, float dt,
const PhysicsTrait::PhysicsProps &props) {

physics_.standardForces(props.mass);
physics_.update(ctx, dt, body_, props);
} }


protected: protected:
BodyTrait::PhysicsBody body_;
BodyTrait::Body body_;
PhysicsTrait::Physics physics_;
}; };


} }

+ 1
- 1
libswan/include/swan/World.h Vedi File

std::unordered_map<std::string, WorldGen::Factory> worldgen_factories_; std::unordered_map<std::string, WorldGen::Factory> worldgen_factories_;
std::vector<EntityCollection::Factory> ent_coll_factories_; std::vector<EntityCollection::Factory> ent_coll_factories_;


BodyTrait::HasBody *player_;
BodyTrait::Body *player_;
Game *game_; Game *game_;


std::mt19937 random_; std::mt19937 random_;

+ 28
- 88
libswan/include/swan/traits/BodyTrait.h Vedi File

#pragma once #pragma once


#include "../common.h"
#include "../Vector2.h" #include "../Vector2.h"


namespace Swan { namespace Swan {


class WorldPlane;
class Win; class Win;


namespace BodyTrait {

class Body;
class HasBody {
public:
virtual Body &getBody() = 0;
};

struct Bounds {
Vec2 pos;
Vec2 size;

float left() { return pos.x; }
float right() { return pos.x + size.x; }
float midX() { return pos.x + size.x / 2; }
float top() { return pos.y; }
float bottom() { return pos.y + size.y; }
float midY() { return pos.y + size.y / 2; }

Vec2 topLeft() { return { left(), top() }; }
Vec2 midLeft() { return { left(), midY() }; }
Vec2 bottomLeft() { return { left(), bottom() }; }
Vec2 topMid() { return { midX(), top() }; }
Vec2 center() { return { midX(), midY() }; }
Vec2 bottomMid() { return { midX(), bottom() }; }
Vec2 topRight() { return { right(), top() }; }
Vec2 midRight() { return { right(), midY() }; }
Vec2 bottomRight() { return { right(), bottom() }; }
};

class Body {
public:
virtual ~Body() = default;

virtual Bounds getBounds() = 0;
virtual void move(Vec2 rel) = 0;
virtual void moveTo(Vec2 pos) = 0;
};

// PhysicsBody is a BodyTrait::Body which implements
// a bunch of physics stuff.
class PhysicsBody: public Body {
public:
PhysicsBody(Vec2 size, float mass, Vec2 pos = Vec2::ZERO):
size_(size), mass_(mass), pos_(pos) {};

BodyTrait::Bounds getBounds() override { return BodyTrait::Bounds{ pos_, size_ }; }
void move(Vec2 rel) override { pos_ += rel; }
void moveTo(Vec2 pos) override { pos_ = pos; }

void friction(Vec2 coef = Vec2(400, 50));
void gravity(Vec2 g = Vec2(0, 20));
void standardForces() { friction(); gravity(); }

void outline(Win &win);
void update(const Swan::Context &ctx, float dt);
void updateWithoutCollision(float dt);

Vec2 force_ = { 0, 0 };
Vec2 vel_ = { 0, 0 };
bool on_ground_ = false;
Vec2 size_;
float mass_;
Vec2 pos_;
float bounciness_ = 0;
float mushyness_ = 2;

private:
void collideX(WorldPlane &plane);
void collideY(WorldPlane &plane);
struct BodyTrait {
struct Body;
struct Tag {};
virtual Body &get(Tag) = 0;

struct Body {
Vec2 pos{};
Vec2 size{};

float left() { return pos.x; }
float right() { return pos.x + size.x; }
float midX() { return pos.x + size.x / 2; }
float top() { return pos.y; }
float bottom() { return pos.y + size.y; }
float midY() { return pos.y + size.y / 2; }

Vec2 topLeft() { return { left(), top() }; }
Vec2 midLeft() { return { left(), midY() }; }
Vec2 bottomLeft() { return { left(), bottom() }; }
Vec2 topMid() { return { midX(), top() }; }
Vec2 center() { return { midX(), midY() }; }
Vec2 bottomMid() { return { midX(), bottom() }; }
Vec2 topRight() { return { right(), top() }; }
Vec2 midRight() { return { right(), midY() }; }
Vec2 bottomRight() { return { right(), bottom() }; }

void outline(Win &win);
};
}; };


// StaticBody is a BodyTrait::Body which just has a static
// position and size.
class StaticBody: public Body {
public:
StaticBody(Vec2 size, Vec2 pos):
size_(size), pos_(pos) {}

BodyTrait::Bounds getBounds() override { return BodyTrait::Bounds{ pos_, size_ }; }
void move(Vec2 rel) override { pos_ += rel; }
void moveTo(Vec2 pos) override { pos_ = pos; }

Vec2 size_;
Vec2 pos_;
};

}
} }

+ 47
- 0
libswan/include/swan/traits/PhysicsTrait.h Vedi File

#pragma once

#include "../traits/BodyTrait.h"
#include "../Vector2.h"
#include "../common.h"

namespace Swan {

struct PhysicsTrait {
struct Physics;
struct Tag {};
virtual Physics &get(Tag) = 0;

struct PhysicsProps {
float mass;
float bounciness = 0;
float mushyness = 2;
};

struct Physics {
Vec2 vel{};
Vec2 force{};
bool on_ground = false;

void friction(Vec2 coef = Vec2(400, 50));
void gravity(float mass, Vec2 g = Vec2(0, 20));
void standardForces(float mass) { friction(); gravity(mass); }

void update(
const Swan::Context &ctx, float dt,
BodyTrait::Body &body, const PhysicsProps &props);
};
};

/*
* Physics
*/

inline void PhysicsTrait::Physics::friction(Vec2 coef) {
force += -vel * coef;
}

inline void PhysicsTrait::Physics::gravity(float mass, Vec2 g) {
force += g * mass;
}

}

+ 4
- 6
libswan/src/World.cc Vedi File

} }


void World::spawnPlayer() { void World::spawnPlayer() {
player_ = dynamic_cast<BodyTrait::HasBody *>(
planes_[current_plane_].spawnPlayer().get());
player_ = &((dynamic_cast<BodyTrait *>(
planes_[current_plane_].spawnPlayer().get()))->get(BodyTrait::Tag{}));
} }


void World::setCurrentPlane(WorldPlane &plane) { void World::setCurrentPlane(WorldPlane &plane) {


void World::draw(Win &win) { void World::draw(Win &win) {
ZoneScopedN("World draw"); ZoneScopedN("World draw");
auto bounds = player_->getBody().getBounds();
win.cam_ = bounds.pos - (win.getSize() / 2) + (bounds.size / 2);
win.cam_ = player_->pos - (win.getSize() / 2) + (player_->size / 2);
planes_[current_plane_].draw(win); planes_[current_plane_].draw(win);
} }


for (auto &plane: planes_) for (auto &plane: planes_)
plane.tick(dt); plane.tick(dt);


auto bounds = player_->getBody().getBounds();
chunk_renderer_.tick( chunk_renderer_.tick(
planes_[current_plane_], planes_[current_plane_],
ChunkPos((int)bounds.pos.x / CHUNK_WIDTH, (int)bounds.pos.y / CHUNK_HEIGHT));
ChunkPos((int)player_->pos.x / CHUNK_WIDTH, (int)player_->pos.y / CHUNK_HEIGHT));
} }


} }

+ 5
- 5
libswan/src/WorldPlane.cc Vedi File

} }


SDL_Color WorldPlane::backgroundColor() { SDL_Color WorldPlane::backgroundColor() {
return gen_->backgroundColor(world_->player_->getBody().getBounds().pos);
return gen_->backgroundColor(world_->player_->pos);
} }


void WorldPlane::draw(Win &win) { void WorldPlane::draw(Win &win) {
ZoneScopedN("WorldPlane draw"); ZoneScopedN("WorldPlane draw");
auto ctx = getContext(); auto ctx = getContext();
auto pbounds = world_->player_->getBody().getBounds();
auto &pbody = *(world_->player_);


gen_->drawBackground(ctx, win, pbounds.pos);
gen_->drawBackground(ctx, win, pbody.pos);


ChunkPos pcpos = ChunkPos( ChunkPos pcpos = ChunkPos(
(int)floor(pbounds.pos.x / CHUNK_WIDTH),
(int)floor(pbounds.pos.y / CHUNK_HEIGHT));
(int)floor(pbody.pos.x / CHUNK_WIDTH),
(int)floor(pbody.pos.y / CHUNK_HEIGHT));


// Just init one chunk per frame // Just init one chunk per frame
if (chunk_init_list_.size() > 0) { if (chunk_init_list_.size() > 0) {

+ 2
- 116
libswan/src/traits/BodyTrait.cc Vedi File

#include "traits/BodyTrait.h" #include "traits/BodyTrait.h"


#include <math.h>
#include <array>
#include <algorithm>

#include "WorldPlane.h"
#include "Win.h" #include "Win.h"


namespace Swan { namespace Swan {
namespace BodyTrait {

static float epsilon = 0.001;

void PhysicsBody::friction(Vec2 coef) {
force_ += -vel_ * coef;
}

void PhysicsBody::gravity(Vec2 g) {
force_ += g * mass_;
}

void PhysicsBody::collideX(WorldPlane &plane) {
auto bounds = getBounds();
bool collided = false;

for (int y = (int)floor(bounds.top() + epsilon); y <= (int)floor(bounds.bottom() - epsilon); ++y) {
int lx = (int)floor(bounds.left() + epsilon);
Tile &left = plane.getTile({ lx, y });
if (left.is_solid_) {
bounds.pos.x = (float)lx + 1.0;
collided = true;
break;
}

int rx = (int)floor(bounds.right() - epsilon);
Tile &right = plane.getTile({ rx, y });
if (right.is_solid_) {
bounds.pos.x = (float)rx - bounds.size.x;
collided = true;
break;
}
}

if (collided) {
pos_.x = bounds.pos.x;

vel_.x *= -bounciness_;
if (abs(vel_.x) < mushyness_)
vel_.x = 0;
}
}

void PhysicsBody::collideY(WorldPlane &plane) {
auto bounds = getBounds();
bool collided = false;
on_ground_ = false;


for (int x = (int)floor(bounds.left() + epsilon); x <= (int)floor(bounds.right() - epsilon); ++x) {
int ty = (int)floor(bounds.top() + epsilon);
Tile &top = plane.getTile({ x, ty });
if (top.is_solid_) {
bounds.pos.y = (float)ty + 1.0;
collided = true;
break;
}

int by = (int)floor(bounds.bottom() - epsilon);
Tile &bottom = plane.getTile({ x, by });
if (bottom.is_solid_) {
bounds.pos.y = (float)by - bounds.size.y;
collided = true;
on_ground_ = true;
break;
}
}

if (collided) {
pos_.y = bounds.pos.y;

vel_.y *= -bounciness_;
if (abs(vel_.y) < mushyness_)
vel_.y = 0;
}
void BodyTrait::Body::outline(Win &win) {
win.drawRect(pos, size);
} }


void PhysicsBody::outline(Win &win) {
win.drawRect(pos_, size_);
}

void PhysicsBody::update(const Swan::Context &ctx, float dt) {
vel_ += (force_ / 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)) {
pos_.x += step.x;
collideX(ctx.plane);
dist.x -= step.x;
}
pos_.x += dist.x;
collideX(ctx.plane);

// Move in increments of at most 'step', on the Y axis
while (abs(dist.y) > abs(step.y)) {
pos_.y += step.y;
collideY(ctx.plane);
dist.y -= step.y;
}
pos_.y += dist.y;
collideY(ctx.plane);
}

void PhysicsBody::updateWithoutCollision(float dt) {
vel_ += (force_ / mass_) * dt;
pos_ += vel_ * dt;
force_ = { 0, 0 };
}

}
} }

+ 101
- 0
libswan/src/traits/PhysicsTrait.cc Vedi File

#include "traits/PhysicsTrait.h"

#include "WorldPlane.h"
#include "Win.h"

namespace Swan {

static float epsilon = 0.001;

static void collideX(
PhysicsTrait::Physics &phys, BodyTrait::Body &body,
WorldPlane &plane, const PhysicsTrait::PhysicsProps &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() + epsilon);
Tile &left = plane.getTile({ lx, y });
if (left.is_solid_) {
body.pos.x = (float)lx + 1.0;
collided = true;
break;
}

int rx = (int)floor(body.right() - epsilon);
Tile &right = plane.getTile({ rx, y });
if (right.is_solid_) {
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(
PhysicsTrait::Physics &phys, BodyTrait::Body &body,
WorldPlane &plane, const PhysicsTrait::PhysicsProps &props) {
bool collided = false;
phys.on_ground = false;

for (int x = (int)floor(body.left() + epsilon); x <= (int)floor(body.right() - epsilon); ++x) {
int ty = (int)floor(body.top() + epsilon);
Tile &top = plane.getTile({ x, ty });
if (top.is_solid_) {
body.pos.y = (float)ty + 1.0;
collided = true;
break;
}

int by = (int)floor(body.bottom() - epsilon);
Tile &bottom = plane.getTile({ x, by });
if (bottom.is_solid_) {
body.pos.y = (float)by - body.size.y;
collided = true;
phys.on_ground = true;
break;
}
}

if (collided) {
phys.vel.y *= -props.bounciness;
if (abs(phys.vel.y) < props.mushyness)
phys.vel.y = 0;
}
}

void PhysicsTrait::Physics::update(
const Swan::Context &ctx, float dt,
BodyTrait::Body &body, const PhysicsProps &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);
}

}

Loading…
Annulla
Salva