diff --git a/SConstruct b/SConstruct index 7d3f1be..8147c58 100644 --- a/SConstruct +++ b/SConstruct @@ -17,7 +17,8 @@ env = Environment(CCFLAGS=[ '-fno-exceptions', '-Wall', '-Wpedantic', '-Wextra', '-Werror', '-O0', '-g3', '-Isrc', - '-DPROJECTNAME=\\\"'+project+'\\\"' + '-DPROJECTNAME=\\\"'+project+'\\\"', + '-DDEBUG' ], LINKFLAGS=[ '-lSDL2', '-lSDL2_image', '-lm', diff --git a/src/core/canvas_engine.cpp b/src/core/canvas_engine.cpp index 1bcaa58..32ba31d 100644 --- a/src/core/canvas_engine.cpp +++ b/src/core/canvas_engine.cpp @@ -29,7 +29,8 @@ CanvasEngine::CanvasEngine() { SDL_Quit(); return; } - this->window = SDL_CreateWindow(PROJECTNAME, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1000, 800, SDL_WINDOW_FULLSCREEN | SDL_WINDOW_RESIZABLE); if(this->window == nullptr) { + this->window = SDL_CreateWindow(PROJECTNAME, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1000, 800, SDL_WINDOW_RESIZABLE | SDL_WINDOW_FULLSCREEN_DESKTOP); + if(this->window == nullptr) { SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Failed to create window, SDL error: %s", SDL_GetError()); IMG_Quit(); SDL_Quit(); diff --git a/src/core/math/transform.cpp b/src/core/math/transform.cpp index 1322384..92c5e55 100644 --- a/src/core/math/transform.cpp +++ b/src/core/math/transform.cpp @@ -1,4 +1,5 @@ #include "transform.hpp" +#include namespace ce { void Transform::translate_by(Vecf const &translation) { @@ -22,17 +23,20 @@ Vecf Transform::up() const { } Transform operator *(Transform const &lhs, Transform const &rhs) { - return Transform { + Transform t{ .position = rhs.position + lhs.position.rotated(rhs.rotation), .rotation = rhs.rotation + lhs.rotation, .scale = lhs.scale.scaled(rhs.scale) }; + assert(t.scale.x != 0.f || t.scale.y != 0.f); // !!! + return t; } Transform &operator *=(Transform &lhs, Transform const &rhs) { - lhs.position += rhs.position.rotated(lhs.rotation); + lhs.position += lhs.position.rotated(rhs.rotation); lhs.rotation += rhs.rotation; lhs.scale.scale(rhs.scale); + assert(lhs.scale.x != 0.f || lhs.scale.y != 0.f); // !!! return lhs; } } diff --git a/src/core/math/transform.hpp b/src/core/math/transform.hpp index b2ca24d..049298a 100644 --- a/src/core/math/transform.hpp +++ b/src/core/math/transform.hpp @@ -5,9 +5,9 @@ namespace ce { struct Transform { - Vecf position; - double rotation; - Vecf scale; + Vecf position{0.f, 0.f}; + double rotation{0.0}; + Vecf scale{1.f, 1.f}; void translate_by(Vecf const &translation); void rotate_by(double rotation); void scale_by(Vecf const &factors); diff --git a/src/core/node.cpp b/src/core/node.cpp index 5a2b8e4..976b66b 100644 --- a/src/core/node.cpp +++ b/src/core/node.cpp @@ -5,6 +5,10 @@ #include namespace ce { +Node::Node(std::string name) { + this->name = name; +} + Node::~Node() { this->destroyed.invoke(); } @@ -111,7 +115,6 @@ void Node::propagate_post_tick() { }); for(std::pair &pair : this->children) pair.second->propagate_post_tick(); - this->_update_transform(); } void Node::propagate_removed() { @@ -121,6 +124,7 @@ void Node::propagate_removed() { } void Node::propagate_draw(SDL_Renderer *render) { + this->_update_transform(); if(this->visible) { this->_draw(render); for(std::pair &pair : this->children) diff --git a/src/core/node.hpp b/src/core/node.hpp index c9c2ae0..ae951d7 100644 --- a/src/core/node.hpp +++ b/src/core/node.hpp @@ -27,7 +27,7 @@ public: Signal child_removed{}; //!< Signal invoked when a child is removed. Signal child_added{}; //!< Signal invoked when a child is added. public: - Node() = default; + Node(std::string name); virtual ~Node(); protected: virtual void _added(Node *parent [[maybe_unused]]) {} //!< called the moment after the object is added as a child to another node @@ -38,6 +38,7 @@ protected: virtual void _update_transform() {} public: template TNode *get_child(std::string const &name); //!< get a non-owning pointer to a child + template TNode *create_child(Args... cargs); void add_child(Node::OwnedPtr &child); //!< add a child, the caller must own the pointer void set_parent(Node *new_parent); Node *get_parent() const; //!< get the parent. @@ -61,6 +62,12 @@ private: template TNode *Node::get_child(std::string const &name) { return children.contains(name) ? dynamic_cast(children.at(name).get()) : nullptr; } +template TNode *Node::create_child(Args... cargs) { + OwnedPtr owned{std::make_unique(cargs...)}; + TNode *referenced{dynamic_cast(owned.get())}; + this->add_child(owned); + return referenced; +} } #endif // !CANVAS_NODE_HPP diff --git a/src/core/node2d.cpp b/src/core/node2d.cpp index c8dc12a..d87eb14 100644 --- a/src/core/node2d.cpp +++ b/src/core/node2d.cpp @@ -1,6 +1,9 @@ #include "node2d.hpp" +#include namespace ce { +Node2D::Node2D(std::string name) : Node(name) {} + void Node2D::_added(Node *parent) { this->parent_node2d = dynamic_cast(parent); } @@ -8,14 +11,13 @@ void Node2D::_added(Node *parent) { void Node2D::_update_transform() { if(this->parent_node2d != nullptr) this->global_transform = this->transform * this->parent_node2d->get_global_transform(); + else + this->global_transform = this->transform; } void Node2D::set_transform(Transform const &transform) { this->transform = transform; -} - -Transform &Node2D::get_transform() { - return this->transform; + this->_update_transform(); } Transform const &Node2D::get_transform() const { @@ -28,12 +30,13 @@ void Node2D::set_global_transform(Transform transform) { Transform parent = this->parent_node2d->get_global_transform(); transform.position -= parent.position.rotated(-parent.rotation); transform.scale_by(parent.scale.reciprocal()); + assert(transform.scale.x != 0.f || transform.scale.y != 0.f); // !!! transform.rotation -= parent.rotation; } this->transform = transform; } -Transform Node2D::get_global_transform() const { +Transform const &Node2D::get_global_transform() const { return this->global_transform; } } diff --git a/src/core/node2d.hpp b/src/core/node2d.hpp index 8a20005..0037cc6 100644 --- a/src/core/node2d.hpp +++ b/src/core/node2d.hpp @@ -10,14 +10,14 @@ class Node2D : public Node { Transform global_transform{}; Node2D *parent_node2d{nullptr}; public: + Node2D(std::string name); virtual void _added(Node *parent) override; Node2D *get_parent_node2d() const; virtual void _update_transform() override; void set_transform(Transform const &transform); - Transform &get_transform(); Transform const &get_transform() const; void set_global_transform(Transform transform); - Transform get_global_transform() const; + Transform const &get_global_transform() const; }; } diff --git a/src/core/sprite.cpp b/src/core/sprite.cpp index 5fa3c13..9243065 100644 --- a/src/core/sprite.cpp +++ b/src/core/sprite.cpp @@ -5,23 +5,30 @@ #include namespace ce { -Sprite::Sprite(std::string const &texture) -: Node2D() { +Sprite::Sprite(std::string name, std::string texture) +: Node2D(name) { std::optional> asset = CanvasEngine::get_singleton()->get_assets().get_asset(texture); this->texture = asset.value(); } void Sprite::_draw(SDL_Renderer *render) { - if(this->texture == nullptr) + if(this->texture == nullptr) { + SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "No texture assigned"); + this->set_visible(false); return; + } int w, h; SDL_QueryTexture(this->texture->get(), NULL, NULL, &w, &h); - Transform transform{this->get_transform()}; + Transform transform{this->get_global_transform()}; + assert(transform.scale.x != 0 && transform.scale.y != 0); // !!! + float fw{w * transform.scale.x}, fh{h * transform.scale.y}; + assert(fw != 0.f && fh != 0.f); + //float fw(w), fh(h); SDL_Rect src{0, 0, w, h}; - SDL_FRect dst{transform.position.x, transform.position.y, float(w), float(h)}; + SDL_FRect dst{transform.position.x - fw/2.f, transform.position.y - fh/2.f, fw, fh}; SDL_RenderCopyExF(render, this->texture->get(), &src, &dst, - transform.rotation,NULL, + transform.rotation * 57.2958f,NULL, SDL_FLIP_NONE); } } diff --git a/src/core/sprite.hpp b/src/core/sprite.hpp index a8a287b..16d5ae1 100644 --- a/src/core/sprite.hpp +++ b/src/core/sprite.hpp @@ -8,7 +8,7 @@ namespace ce { class Sprite : public Node2D { std::shared_ptr texture{nullptr}; public: - Sprite(std::string const &texture); + Sprite(std::string name, std::string texture); virtual void _draw(SDL_Renderer *render) override; }; } diff --git a/src/level_1.cpp b/src/level_1.cpp index 28f7de8..8ad5e3a 100644 --- a/src/level_1.cpp +++ b/src/level_1.cpp @@ -1,10 +1,10 @@ #include "level_1.hpp" #include "core/node.hpp" -#include "core/sprite.hpp" +#include "test_node.hpp" void Level1::instantiate() { ce::Node::OwnedPtr &root_ptr{this->get_owned_root()}; - root_ptr.reset(new ce::Node()); - ce::Node::OwnedPtr sprite{std::make_unique("neocat")}; - root->add_child(sprite); + root_ptr.reset(new ce::Node("root")); + ce::Node::OwnedPtr node{std::make_unique()}; + root->add_child(node); } diff --git a/src/test_node.cpp b/src/test_node.cpp new file mode 100644 index 0000000..4f61595 --- /dev/null +++ b/src/test_node.cpp @@ -0,0 +1,33 @@ +#include "test_node.hpp" +#include "core/math/transform.hpp" +#include +#include +#include + +TestNode::TestNode() +: ce::Node2D("TestNode") { + this->sprite = this->create_child("neocat", "neocat"); +} + +void TestNode::_first_tick() { + ce::Transform st{this->sprite->get_global_transform()}; + st.position.x += 200; + this->sprite->set_global_transform(st); +} + +void TestNode::_tick(double const &delta) { + ce::Node2D::_tick(delta); + ce::Transform trans{this->get_transform()}; + trans.position.x = 500 + std::sin(SDL_GetTicks64() * 0.001) * 100.f; + trans.position.y = 500 + std::cos(SDL_GetTicks64() * 0.001) * 100.f; + trans.rotate_by(delta * 10.f); + this->set_transform(trans); +} + +void TestNode::_draw(SDL_Renderer *render) { + ce::Node2D::_draw(render); + ce::Transform trans{this->get_global_transform()}; + SDL_SetRenderDrawColor(render, 255, 255, 255, 255); + SDL_FRect rect{trans.position.x-101.f, trans.position.y-101.f, 202.f, 202.f}; + SDL_RenderDrawRectF(render, &rect); +} diff --git a/src/test_node.hpp b/src/test_node.hpp new file mode 100644 index 0000000..0803385 --- /dev/null +++ b/src/test_node.hpp @@ -0,0 +1,17 @@ +#ifndef TEST_NODE_HPP +#define TEST_NODE_HPP + +#include "core/node2d.hpp" +#include "core/sprite.hpp" + +class TestNode : public ce::Node2D { +private: + ce::Sprite *sprite{nullptr}; +public: + TestNode(); + virtual void _first_tick() override; + virtual void _tick(double const &delta) override; + virtual void _draw(SDL_Renderer *render) override; +}; + +#endif // !TEST_NODE_HPP