feat: implemented some basic gameplay
parent
70b6dc4ab7
commit
110e72e241
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 465 B After Width: | Height: | Size: 514 B |
|
@ -29,9 +29,7 @@ void AssetDB::load(std::string asset_name) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssetDB::index_assets() {
|
void AssetDB::index_assets() {
|
||||||
SDL_Log("Indexing assets");
|
|
||||||
for(std::filesystem::directory_entry const &itr : std::filesystem::recursive_directory_iterator("resources")) {
|
for(std::filesystem::directory_entry const &itr : std::filesystem::recursive_directory_iterator("resources")) {
|
||||||
SDL_Log("Indexing %s", itr.path().c_str());
|
|
||||||
if(itr.is_directory())
|
if(itr.is_directory())
|
||||||
continue;
|
continue;
|
||||||
else if(!itr.path().has_extension())
|
else if(!itr.path().has_extension())
|
||||||
|
@ -43,7 +41,6 @@ void AssetDB::index_assets() {
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Failed to add asset %s, asset by that name is already indexed", name.c_str());
|
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Failed to add asset %s, asset by that name is already indexed", name.c_str());
|
||||||
} else {
|
} else {
|
||||||
this->assets.insert({name, std::make_shared<Texture>(itr.path())});
|
this->assets.insert({name, std::make_shared<Texture>(itr.path())});
|
||||||
SDL_Log("Indexed resource %s as texture", name.c_str());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,7 @@ void CollisionWorld::check_collisions_for(CollisionShape *shape, std::vector<Col
|
||||||
// (As the shapes *before* have already been checked, guaranteeing that each pair will only be checked once)
|
// (As the shapes *before* have already been checked, guaranteeing that each pair will only be checked once)
|
||||||
for(std::vector<CollisionShape*>::iterator iter{begin}; iter != this->shapes.end(); ++iter) {
|
for(std::vector<CollisionShape*>::iterator iter{begin}; iter != this->shapes.end(); ++iter) {
|
||||||
CollisionShape *other{*iter};
|
CollisionShape *other{*iter};
|
||||||
if(other != shape && CollisionShape::shapes_overlap(shape, other)) {
|
if(other != shape && other->get_owner() != shape->get_owner() && CollisionShape::shapes_overlap(shape, other)) {
|
||||||
if((shape->get_mask() & other->get_layers()) != 0x0u)
|
if((shape->get_mask() & other->get_layers()) != 0x0u)
|
||||||
shape->get_owner()->add_overlap(shape, other);
|
shape->get_owner()->add_overlap(shape, other);
|
||||||
if((shape->get_layers() & other->get_mask()) != 0x0u)
|
if((shape->get_layers() & other->get_mask()) != 0x0u)
|
||||||
|
|
|
@ -24,13 +24,16 @@ Shape Shape::make_box(float h_extent, float v_extent) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
CollisionShape::CollisionShape(std::string const &name, Node *owner, Shape shape)
|
CollisionShape::CollisionShape(std::string const &name, Shape shape)
|
||||||
: Node2D(name)
|
: Node2D(name)
|
||||||
, world{CanvasEngine::get_singleton()->get_collision_world()} {
|
, world{CanvasEngine::get_singleton()->get_collision_world()}
|
||||||
this->shape = shape;
|
, shape{shape} {}
|
||||||
}
|
|
||||||
|
|
||||||
void CollisionShape::_added() {
|
void CollisionShape::_added() {
|
||||||
|
this->ce::Node2D::_added();
|
||||||
|
ce::Transform transform{this->get_global_transform()};
|
||||||
|
if(!this->is_inside_tree())
|
||||||
|
return;
|
||||||
Node *parent{this->get_parent()};
|
Node *parent{this->get_parent()};
|
||||||
while(parent != nullptr) {
|
while(parent != nullptr) {
|
||||||
if(CollidableNode *as_collidable{dynamic_cast<CollidableNode*>(parent)}) {
|
if(CollidableNode *as_collidable{dynamic_cast<CollidableNode*>(parent)}) {
|
||||||
|
@ -40,16 +43,18 @@ void CollisionShape::_added() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "%s does not have a parent that is a CollidableNode to serve as the owner", this->get_name().c_str());
|
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "%s does not have a parent that is a CollidableNode to serve as the owner", this->get_name().c_str());
|
||||||
#ifdef DEBUG
|
|
||||||
abort();
|
|
||||||
#endif
|
|
||||||
if(this->is_registered)
|
if(this->is_registered)
|
||||||
this->deregister_with_world();
|
this->deregister_with_world();
|
||||||
|
#ifdef DEBUG
|
||||||
|
abort();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void CollisionShape::_removed() {
|
void CollisionShape::_removed() {
|
||||||
if(this->is_registered)
|
this->ce::Node2D::_removed();
|
||||||
|
if(this->is_registered) {
|
||||||
this->deregister_with_world();
|
this->deregister_with_world();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CollisionShape::can_collide(CollisionShape const *lhs, CollisionShape const *rhs) {
|
bool CollisionShape::can_collide(CollisionShape const *lhs, CollisionShape const *rhs) {
|
||||||
|
@ -71,9 +76,9 @@ bool CollisionShape::shapes_overlap(CollisionShape const *lhs, CollisionShape co
|
||||||
? overlap_circle_circle(lshape.circle, lhst, rshape.circle, rhst)
|
? overlap_circle_circle(lshape.circle, lhst, rshape.circle, rhst)
|
||||||
: overlap_circle_aabb(lshape.circle, lhst, rshape.box, rhst);
|
: overlap_circle_aabb(lshape.circle, lhst, rshape.box, rhst);
|
||||||
} else if(lhs->shape.shape == Shape::AABB) {
|
} else if(lhs->shape.shape == Shape::AABB) {
|
||||||
return rhs->shape.shape == Shape::CIRCLE
|
return rhs->shape.shape == Shape::AABB
|
||||||
? overlap_circle_aabb(rshape.circle, rhst, lshape.box, lhst)
|
? overlap_aabb_aabb(lshape.box, lhst, rshape.box, rhst)
|
||||||
: overlap_aabb_aabb(lshape.box, lhst, rshape.box, rhst);
|
: overlap_circle_aabb(lshape.circle, lhst, rshape.box, rhst);
|
||||||
} else {
|
} else {
|
||||||
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Attempt to compare shapes with a shape that is not of a valid shape. This should never happen.");
|
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Attempt to compare shapes with a shape that is not of a valid shape. This should never happen.");
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
@ -97,16 +102,9 @@ bool CollisionShape::overlap_circle_aabb(ShapeCircle lhs, Transform lhst, ShapeA
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CollisionShape::overlap_aabb_aabb(ShapeAABB lhs, Transform lhst, ShapeAABB rhs, Transform rhst) {
|
bool CollisionShape::overlap_aabb_aabb(ShapeAABB lhs, Transform lhst, ShapeAABB rhs, Transform rhst) {
|
||||||
// calculate size of bounding box encompassing both. If it's smaller than the size of both summed, the two are overlapping.
|
ce::Vecf const diff{lhst.position - rhst.position};
|
||||||
float const bound_x{std::max({
|
return std::abs(diff.x) <= (lhs.h_extent + rhs.h_extent)
|
||||||
std::abs((lhst.position.x - lhs.h_extent) - (rhst.position.x + rhs.h_extent)),
|
&& std::abs(diff.y) <= (lhs.v_extent + rhs.v_extent);
|
||||||
lhs.h_extent, rhs.h_extent
|
|
||||||
})};
|
|
||||||
float const bound_y{std::max({
|
|
||||||
std::abs((lhst.position.y - lhs.v_extent) - (rhst.position.y + rhs.v_extent)),
|
|
||||||
lhs.v_extent, rhs.v_extent
|
|
||||||
})};
|
|
||||||
return bound_x < (lhs.h_extent + rhs.h_extent) && bound_y < (lhs.v_extent + rhs.v_extent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CollidableNode *CollisionShape::get_owner() const {
|
CollidableNode *CollisionShape::get_owner() const {
|
||||||
|
|
|
@ -29,7 +29,7 @@ class CollisionShape : public Node2D {
|
||||||
CollisionWorld &world;
|
CollisionWorld &world;
|
||||||
bool is_registered{false};
|
bool is_registered{false};
|
||||||
public:
|
public:
|
||||||
CollisionShape(std::string const &name, Node *owner, Shape shape);
|
CollisionShape(std::string const &name, Shape shape);
|
||||||
|
|
||||||
virtual void _added() override;
|
virtual void _added() override;
|
||||||
virtual void _removed() override;
|
virtual void _removed() override;
|
||||||
|
|
|
@ -17,6 +17,7 @@ void Level::deinstantiate() {
|
||||||
|
|
||||||
void Level::propagate_tick(double const &delta_time) {
|
void Level::propagate_tick(double const &delta_time) {
|
||||||
this->root->propagate_tick(delta_time);
|
this->root->propagate_tick(delta_time);
|
||||||
|
this->root->propagate_post_tick();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Level::propagate_draw(SDL_Renderer *render) {
|
void Level::propagate_draw(SDL_Renderer *render) {
|
||||||
|
|
|
@ -71,6 +71,12 @@ bool Vecf::is_nan() const {
|
||||||
return std::isnan(this->x) || std::isnan(this->y);
|
return std::isnan(this->x) || std::isnan(this->y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Vecf Vecf::clamp_magnitude(float max) const {
|
||||||
|
float const old_magnitude{this->magnitude()};
|
||||||
|
float const new_magnitude{std::min(max, old_magnitude)};
|
||||||
|
return (old_magnitude != 0.f ? ((*this) / old_magnitude) : ce::Vecf::ZERO) * new_magnitude;
|
||||||
|
}
|
||||||
|
|
||||||
void Vecf::scale(float x, float y) {
|
void Vecf::scale(float x, float y) {
|
||||||
this->x *= x;
|
this->x *= x;
|
||||||
this->y *= y;
|
this->y *= y;
|
||||||
|
|
|
@ -37,6 +37,7 @@ struct Vecf {
|
||||||
//! returns true if either the x or y element is NaN
|
//! returns true if either the x or y element is NaN
|
||||||
bool is_nan() const;
|
bool is_nan() const;
|
||||||
|
|
||||||
|
Vecf clamp_magnitude(float max) const;
|
||||||
//! scale vector member-wise
|
//! scale vector member-wise
|
||||||
void scale(float x, float y);
|
void scale(float x, float y);
|
||||||
//! scale vector member-wise
|
//! scale vector member-wise
|
||||||
|
@ -62,20 +63,20 @@ bool operator==(Vecf const &lhs, Vecf const &rhs) {
|
||||||
|
|
||||||
static inline
|
static inline
|
||||||
Vecf operator+(Vecf const &lhs, Vecf const &rhs) {
|
Vecf operator+(Vecf const &lhs, Vecf const &rhs) {
|
||||||
return Vecf(lhs.x + rhs.x, lhs.y + rhs.y);
|
return Vecf{lhs.x + rhs.x, lhs.y + rhs.y};
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline
|
static inline
|
||||||
Vecf operator-(Vecf const &lhs, Vecf const &rhs) {
|
Vecf operator-(Vecf const &lhs, Vecf const &rhs) {
|
||||||
return Vecf(lhs.x - rhs.x, lhs.y - rhs.y);
|
return Vecf{lhs.x - rhs.x, lhs.y - rhs.y};
|
||||||
}
|
}
|
||||||
static inline
|
static inline
|
||||||
Vecf operator*(Vecf const &v, float f) {
|
Vecf operator*(Vecf const &v, float f) {
|
||||||
return Vecf(v.x * f, v.y * f);
|
return Vecf{v.x * f, v.y * f};
|
||||||
}
|
}
|
||||||
static inline
|
static inline
|
||||||
Vecf operator/(Vecf const &v, float f) {
|
Vecf operator/(Vecf const &v, float f) {
|
||||||
return Vecf(v.x / f, v.y / f);
|
return Vecf{v.x / f, v.y / f};
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline
|
static inline
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "node.hpp"
|
#include "node.hpp"
|
||||||
#include <SDL2/SDL_assert.h>
|
#include <SDL2/SDL_assert.h>
|
||||||
|
#include <SDL2/SDL.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
@ -52,8 +53,6 @@ void Node::set_name(std::string const &name) {
|
||||||
|
|
||||||
void Node::flag_for_deletion() {
|
void Node::flag_for_deletion() {
|
||||||
this->request_deletion = true;
|
this->request_deletion = true;
|
||||||
this->tick = false;
|
|
||||||
this->visible = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Node::requests_deletion() const {
|
bool Node::requests_deletion() const {
|
||||||
|
@ -84,6 +83,10 @@ bool Node::is_inside_tree() const {
|
||||||
return this->inside_tree;
|
return this->inside_tree;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Node::ChildrenVector &Node::get_children() {
|
||||||
|
return this->children;
|
||||||
|
}
|
||||||
|
|
||||||
void Node::set_level(ce::Level *level) {
|
void Node::set_level(ce::Level *level) {
|
||||||
// parent level needs to match
|
// parent level needs to match
|
||||||
assert(this->parent == nullptr || this->parent->get_level() == level);
|
assert(this->parent == nullptr || this->parent->get_level() == level);
|
||||||
|
@ -136,12 +139,12 @@ void Node::propagate_tick(double const &delta_time) {
|
||||||
|
|
||||||
void Node::propagate_post_tick() {
|
void Node::propagate_post_tick() {
|
||||||
// clean up children queued for deletion
|
// clean up children queued for deletion
|
||||||
for(size_t i{0}; i < this->children.size(); ++i) {
|
for(size_t i{0}; i < this->children.size();) {
|
||||||
ChildrenVector::value_type &value{this->children[i]};
|
ChildrenVector::value_type &value{this->children[i]};
|
||||||
if(value.second->requests_deletion()) {
|
if(value.second->requests_deletion()) {
|
||||||
value.second->propagate_removed();
|
this->remove_child(value.second.get());
|
||||||
this->child_removed.invoke(value.second.get());
|
|
||||||
} else {
|
} else {
|
||||||
|
++i;
|
||||||
value.second->propagate_post_tick();
|
value.second->propagate_post_tick();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ public:
|
||||||
public:
|
public:
|
||||||
Node(std::string name);
|
Node(std::string name);
|
||||||
virtual ~Node();
|
virtual ~Node();
|
||||||
protected:
|
public:
|
||||||
virtual void _added() {} //!< called the moment after the object is added as a child to another node
|
virtual void _added() {} //!< called the moment after the object is added as a child to another node
|
||||||
virtual void _first_tick() {} //!< called the first frame this object is active
|
virtual void _first_tick() {} //!< called the first frame this object is active
|
||||||
virtual void _tick(double const &delta_time [[maybe_unused]]) {} //!< called every frame
|
virtual void _tick(double const &delta_time [[maybe_unused]]) {} //!< called every frame
|
||||||
|
@ -57,6 +57,7 @@ public:
|
||||||
bool is_ticking() const;
|
bool is_ticking() const;
|
||||||
ce::Level *get_level() const;
|
ce::Level *get_level() const;
|
||||||
bool is_inside_tree() const;
|
bool is_inside_tree() const;
|
||||||
|
ChildrenVector &get_children();
|
||||||
private:
|
private:
|
||||||
void set_level(ce::Level *level);
|
void set_level(ce::Level *level);
|
||||||
void set_is_inside_tree(bool value);
|
void set_is_inside_tree(bool value);
|
||||||
|
|
|
@ -6,6 +6,7 @@ Node2D::Node2D(std::string name) : Node(name) {}
|
||||||
|
|
||||||
void Node2D::_added() {
|
void Node2D::_added() {
|
||||||
this->parent_node2d = dynamic_cast<Node2D*>(this->get_parent());
|
this->parent_node2d = dynamic_cast<Node2D*>(this->get_parent());
|
||||||
|
this->_update_transform();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Node2D::_update_transform() {
|
void Node2D::_update_transform() {
|
||||||
|
@ -13,6 +14,8 @@ void Node2D::_update_transform() {
|
||||||
this->global_transform = this->transform * this->parent_node2d->get_global_transform();
|
this->global_transform = this->transform * this->parent_node2d->get_global_transform();
|
||||||
else
|
else
|
||||||
this->global_transform = this->transform;
|
this->global_transform = this->transform;
|
||||||
|
for(ChildrenVector::value_type &pair : this->get_children())
|
||||||
|
pair.second->_update_transform();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Node2D::set_transform(Transform const &transform) {
|
void Node2D::set_transform(Transform const &transform) {
|
||||||
|
@ -30,10 +33,11 @@ void Node2D::set_global_transform(Transform transform) {
|
||||||
Transform parent = this->parent_node2d->get_global_transform();
|
Transform parent = this->parent_node2d->get_global_transform();
|
||||||
transform.position -= parent.position.rotated(-parent.rotation);
|
transform.position -= parent.position.rotated(-parent.rotation);
|
||||||
transform.scale_by(parent.scale.reciprocal());
|
transform.scale_by(parent.scale.reciprocal());
|
||||||
assert(transform.scale.x != 0.f || transform.scale.y != 0.f); // !!!
|
assert(transform.scale.x != 0.f || transform.scale.y != 0.f);
|
||||||
transform.rotation -= parent.rotation;
|
transform.rotation -= parent.rotation;
|
||||||
}
|
}
|
||||||
this->transform = transform;
|
this->transform = transform;
|
||||||
|
this->_update_transform();
|
||||||
}
|
}
|
||||||
|
|
||||||
Transform const &Node2D::get_global_transform() const {
|
Transform const &Node2D::get_global_transform() const {
|
||||||
|
|
|
@ -13,6 +13,6 @@ ce::Node::OwnedPtr Level1::construct() {
|
||||||
.scale = ce::Vecf::ONE
|
.scale = ce::Vecf::ONE
|
||||||
});
|
});
|
||||||
root->create_child<Player>();
|
root->create_child<Player>();
|
||||||
root->create_child<Truck>(0.f);
|
root->create_child<Truck>(true);
|
||||||
return std::move(root);
|
return std::move(root);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
#include "core/canvas_engine.hpp"
|
#include "core/canvas_engine.hpp"
|
||||||
#include "level_1.hpp"
|
#include "level_1.hpp"
|
||||||
|
#include <SDL2/SDL_log.h>
|
||||||
|
|
||||||
ce::CanvasEngine engine{};
|
ce::CanvasEngine engine{};
|
||||||
|
|
||||||
int main(int argc [[maybe_unused]], char* argv [[maybe_unused]][]) {
|
int main(int argc [[maybe_unused]], char* argv [[maybe_unused]][]) {
|
||||||
|
SDL_LogSetAllPriority(SDL_LOG_PRIORITY_VERBOSE);
|
||||||
std::unique_ptr<ce::Level> level{std::make_unique<Level1>()};
|
std::unique_ptr<ce::Level> level{std::make_unique<Level1>()};
|
||||||
engine.run(level);
|
engine.run(level);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,11 +10,15 @@
|
||||||
#include "truck.hpp"
|
#include "truck.hpp"
|
||||||
#include <SDL2/SDL_keyboard.h>
|
#include <SDL2/SDL_keyboard.h>
|
||||||
#include <SDL2/SDL_keycode.h>
|
#include <SDL2/SDL_keycode.h>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
Player::Player()
|
Player::Player()
|
||||||
: ce::CollidableNode("player", 0x1u, 0x1u)
|
: ce::CollidableNode("player", 0x1u, 0x1u)
|
||||||
, sprite{this->create_child<ce::Sprite>("bike", "bike")}
|
, sprite{this->create_child<ce::Sprite>("bike", "bike")}
|
||||||
, shape{this->create_child<ce::CollisionShape>("player_col_shape", this, ce::Shape::make_box(1.f, 2.f))} {
|
, shape{this->create_child<ce::CollisionShape>("player_col_shape", ce::Shape::make_box(.4f, 0.75f))} {
|
||||||
|
this->set_global_transform(this->get_global_transform()
|
||||||
|
.translated({0.f, 2.f})
|
||||||
|
);
|
||||||
this->sprite->set_global_transform(this->sprite->get_global_transform()
|
this->sprite->set_global_transform(this->sprite->get_global_transform()
|
||||||
.scaled({1.5f, 1.5f})
|
.scaled({1.5f, 1.5f})
|
||||||
);
|
);
|
||||||
|
@ -24,9 +28,7 @@ Player::Player()
|
||||||
new ce::KeyboardScancode(SDL_SCANCODE_A),
|
new ce::KeyboardScancode(SDL_SCANCODE_A),
|
||||||
new ce::KeyboardScancode(SDL_SCANCODE_D)
|
new ce::KeyboardScancode(SDL_SCANCODE_D)
|
||||||
)
|
)
|
||||||
})
|
}).changed.connect(ce::Callable<void, ce::InputValue>::make(
|
||||||
.changed
|
|
||||||
.connect(ce::Callable<void, ce::InputValue>::make(
|
|
||||||
this, &Player::_input_horizontal_movement)
|
this, &Player::_input_horizontal_movement)
|
||||||
);
|
);
|
||||||
map.bind_input("vertical", {
|
map.bind_input("vertical", {
|
||||||
|
@ -34,12 +36,12 @@ Player::Player()
|
||||||
new ce::KeyboardScancode(SDL_SCANCODE_W),
|
new ce::KeyboardScancode(SDL_SCANCODE_W),
|
||||||
new ce::KeyboardScancode(SDL_SCANCODE_S)
|
new ce::KeyboardScancode(SDL_SCANCODE_S)
|
||||||
)
|
)
|
||||||
})
|
}) .changed.connect(ce::Callable<void, ce::InputValue>::make(
|
||||||
.changed
|
|
||||||
.connect(ce::Callable<void, ce::InputValue>::make(
|
|
||||||
this, &Player::_input_vertical_movement)
|
this, &Player::_input_vertical_movement)
|
||||||
);
|
);
|
||||||
this->overlap_enter.connect(ce::Callable<void, ce::CollisionShape *, ce::CollidableNode *, ce::CollisionShape *>::make(this, &Player::_on_overlap_enter));
|
this->overlap_enter.connect(ce::Callable<void, ce::CollisionShape *, ce::CollidableNode *, ce::CollisionShape *>::make(
|
||||||
|
this, &Player::_on_overlap_enter
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::_tick(double const &delta) {
|
void Player::_tick(double const &delta) {
|
||||||
|
@ -49,9 +51,17 @@ void Player::_tick(double const &delta) {
|
||||||
ACCELERATION * delta
|
ACCELERATION * delta
|
||||||
);
|
);
|
||||||
ce::Transform trans{this->get_global_transform().translated(this->velocity * delta)};
|
ce::Transform trans{this->get_global_transform().translated(this->velocity * delta)};
|
||||||
trans.position.x = std::clamp(trans.position.x, -3.f, 3.f);
|
trans.position.x = std::clamp(trans.position.x, -LIMITS.x, LIMITS.x);
|
||||||
trans.position.y = std::clamp(trans.position.y, -2.f, 2.f);
|
trans.position.y = std::clamp(trans.position.y, -LIMITS.y, LIMITS.y);
|
||||||
this->set_global_transform(trans);
|
this->set_global_transform(trans);
|
||||||
|
|
||||||
|
if(this->invincibility > 0.f) {
|
||||||
|
this->invincibility -= delta;
|
||||||
|
this->sprite->set_visible(this->invincibility <= 0.f
|
||||||
|
? true
|
||||||
|
: int(std::floorf(this->invincibility / DAMAGE_FLASH_FREQ)) % 2 != 0
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::_input_horizontal_movement(ce::InputValue value) {
|
void Player::_input_horizontal_movement(ce::InputValue value) {
|
||||||
|
@ -63,9 +73,10 @@ void Player::_input_vertical_movement(ce::InputValue value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::_on_overlap_enter(ce::CollisionShape *, ce::CollidableNode *other, ce::CollisionShape *) {
|
void Player::_on_overlap_enter(ce::CollisionShape *, ce::CollidableNode *other, ce::CollisionShape *) {
|
||||||
|
if(this->invincibility > 0.f)
|
||||||
|
return;
|
||||||
if(Truck *truck{dynamic_cast<Truck*>(other)}) {
|
if(Truck *truck{dynamic_cast<Truck*>(other)}) {
|
||||||
// TODO: Implement damage
|
this->invincibility = 2.f;
|
||||||
this->flag_for_deletion();
|
this->velocity = (this->get_global_transform().position - other->get_global_transform().position).normalized() * DAMAGE_FORCE;
|
||||||
}
|
}
|
||||||
SDL_Log("overlap");
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,12 +11,16 @@ class Sprite;
|
||||||
|
|
||||||
class Player : public ce::CollidableNode {
|
class Player : public ce::CollidableNode {
|
||||||
ce::Vecf const SPEED{3.f, 2.5f};
|
ce::Vecf const SPEED{3.f, 2.5f};
|
||||||
float const ACCELERATION{20.f};
|
float const ACCELERATION{10.f};
|
||||||
|
ce::Vecf const LIMITS{3.f, 3.f};
|
||||||
|
float const DAMAGE_FLASH_FREQ{.1f};
|
||||||
|
float const DAMAGE_FORCE{6.f};
|
||||||
|
|
||||||
ce::Vecf velocity{0.f, 0.f};
|
ce::Vecf velocity{0.f, 0.f};
|
||||||
ce::Vecf input{0.f, 0.f};
|
ce::Vecf input{0.f, 0.f};
|
||||||
ce::CollisionShape *shape{nullptr};
|
ce::CollisionShape *shape{nullptr};
|
||||||
ce::Sprite *sprite{nullptr};
|
ce::Sprite *sprite{nullptr};
|
||||||
|
float invincibility{0.f};
|
||||||
public:
|
public:
|
||||||
Player();
|
Player();
|
||||||
virtual void _tick(double const &delta) override;
|
virtual void _tick(double const &delta) override;
|
||||||
|
|
|
@ -1,17 +1,29 @@
|
||||||
#include "truck.hpp"
|
#include "truck.hpp"
|
||||||
#include "core/callable.hpp"
|
|
||||||
#include "core/collision_shape.hpp"
|
#include "core/collision_shape.hpp"
|
||||||
#include "core/sprite.hpp"
|
#include "core/sprite.hpp"
|
||||||
|
#include <SDL2/SDL_log.h>
|
||||||
|
|
||||||
Truck::Truck(float x_pos)
|
Truck::Truck(bool left)
|
||||||
: ce::CollidableNode("truck", 0x1u, 0x1u)
|
: ce::CollidableNode("truck", 0x1u, 0x1u)
|
||||||
, sprite{this->create_child<ce::Sprite>("sprite", "truck")}
|
, sprite{this->create_child<ce::Sprite>("sprite", "truck")}
|
||||||
, shape{this->create_child<ce::CollisionShape>("truck_col_shape", this, ce::Shape::make_box(2.f, 2.f))} {
|
, shape{this->create_child<ce::CollisionShape>("truck_col_shape", ce::Shape::make_box(.5f, 1.f))}
|
||||||
this->sprite->set_global_transform(this->get_global_transform()
|
, spawned_left{left} {
|
||||||
.scaled({2.5f, 2.5f})
|
this->sprite->set_global_transform(this->get_global_transform() .scaled({2.5f, 2.5f}));
|
||||||
.translated({x_pos, -3.f})
|
this->set_global_transform(this->get_global_transform().translated({
|
||||||
);
|
.x=this->spawned_left ? -1.4f : 1.4f,
|
||||||
|
.y=-4.5f
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Truck::_tick(double const &delta) {
|
void Truck::_tick(double const &delta) {
|
||||||
|
wave_time += delta * FREQUENCY;
|
||||||
|
ce::Transform const transform{this->get_global_transform()
|
||||||
|
.translated(ce::Vecf{
|
||||||
|
.x=std::sin(wave_time) * AMPLITUDE * (this->spawned_left > 0.f ? 1.f : -1.f),
|
||||||
|
.y=this->RELATIVE_VERTICAL_SPEED
|
||||||
|
} * float(delta))
|
||||||
|
};
|
||||||
|
this->set_global_transform(transform);
|
||||||
|
if(transform.position.y > 4.5f)
|
||||||
|
this->flag_for_deletion();
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,10 +9,15 @@ namespace ce {
|
||||||
};
|
};
|
||||||
|
|
||||||
class Truck : public ce::CollidableNode {
|
class Truck : public ce::CollidableNode {
|
||||||
|
float const AMPLITUDE{4.f};
|
||||||
|
float const FREQUENCY{3.f};
|
||||||
|
float const RELATIVE_VERTICAL_SPEED{1.5f};
|
||||||
|
float wave_time{0.f};
|
||||||
|
bool spawned_left{false};
|
||||||
ce::Sprite *sprite{nullptr};
|
ce::Sprite *sprite{nullptr};
|
||||||
ce::CollisionShape *shape{nullptr};
|
ce::CollisionShape *shape{nullptr};
|
||||||
public:
|
public:
|
||||||
Truck(float x_pos);
|
Truck(bool left);
|
||||||
virtual void _tick(double const &delta) override;
|
virtual void _tick(double const &delta) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue