diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f367017 --- /dev/null +++ b/.gitignore @@ -0,0 +1,43 @@ +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app + +# Visual Studio Codee +.vscode +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json + +# Project +.obj +enginetest diff --git a/README.md b/README.md index 5283904..f1f401a 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,4 @@ # AsloEngine My WiP 2D Game Engine made using SFML + +Version 0.9.0 diff --git a/asloengine/asloengine.hpp b/asloengine/asloengine.hpp new file mode 100755 index 0000000..6632a50 --- /dev/null +++ b/asloengine/asloengine.hpp @@ -0,0 +1,15 @@ +#pragma once + +#include "builtin/builtin.hpp" + +#include "headers/clickable.hpp" +#include "headers/core.hpp" +#include "headers/define.hpp" +#include "headers/gameobject.hpp" +#include "headers/helpers.hpp" +#include "headers/keyboard.hpp" +#include "headers/mouse.hpp" +#include "headers/scene.hpp" +#include "headers/scenemanager.hpp" +#include "headers/spriteobject.hpp" +#include "headers/textobject.hpp" \ No newline at end of file diff --git a/asloengine/builtin/assets/fonts/arcon_regular.otf b/asloengine/builtin/assets/fonts/arcon_regular.otf new file mode 100755 index 0000000..a4d97b7 Binary files /dev/null and b/asloengine/builtin/assets/fonts/arcon_regular.otf differ diff --git a/asloengine/builtin/assets/fonts/argentum_sans_black.otf b/asloengine/builtin/assets/fonts/argentum_sans_black.otf new file mode 100755 index 0000000..66f93a6 Binary files /dev/null and b/asloengine/builtin/assets/fonts/argentum_sans_black.otf differ diff --git a/asloengine/builtin/assets/fonts/argentum_sans_bold.otf b/asloengine/builtin/assets/fonts/argentum_sans_bold.otf new file mode 100755 index 0000000..d547cff Binary files /dev/null and b/asloengine/builtin/assets/fonts/argentum_sans_bold.otf differ diff --git a/asloengine/builtin/assets/fonts/argentum_sans_extra_bold.otf b/asloengine/builtin/assets/fonts/argentum_sans_extra_bold.otf new file mode 100755 index 0000000..03d64f2 Binary files /dev/null and b/asloengine/builtin/assets/fonts/argentum_sans_extra_bold.otf differ diff --git a/asloengine/builtin/assets/fonts/argentum_sans_extra_light.otf b/asloengine/builtin/assets/fonts/argentum_sans_extra_light.otf new file mode 100755 index 0000000..e83da76 Binary files /dev/null and b/asloengine/builtin/assets/fonts/argentum_sans_extra_light.otf differ diff --git a/asloengine/builtin/assets/fonts/argentum_sans_light.otf b/asloengine/builtin/assets/fonts/argentum_sans_light.otf new file mode 100755 index 0000000..710381e Binary files /dev/null and b/asloengine/builtin/assets/fonts/argentum_sans_light.otf differ diff --git a/asloengine/builtin/assets/fonts/argentum_sans_medium.otf b/asloengine/builtin/assets/fonts/argentum_sans_medium.otf new file mode 100755 index 0000000..5bc4bd0 Binary files /dev/null and b/asloengine/builtin/assets/fonts/argentum_sans_medium.otf differ diff --git a/asloengine/builtin/assets/fonts/argentum_sans_regular.otf b/asloengine/builtin/assets/fonts/argentum_sans_regular.otf new file mode 100755 index 0000000..d1e4b9c Binary files /dev/null and b/asloengine/builtin/assets/fonts/argentum_sans_regular.otf differ diff --git a/asloengine/builtin/assets/fonts/argentum_sans_semi_bold.otf b/asloengine/builtin/assets/fonts/argentum_sans_semi_bold.otf new file mode 100755 index 0000000..a13ffac Binary files /dev/null and b/asloengine/builtin/assets/fonts/argentum_sans_semi_bold.otf differ diff --git a/asloengine/builtin/assets/fonts/argentum_sans_thin.otf b/asloengine/builtin/assets/fonts/argentum_sans_thin.otf new file mode 100755 index 0000000..32e75f8 Binary files /dev/null and b/asloengine/builtin/assets/fonts/argentum_sans_thin.otf differ diff --git a/asloengine/builtin/assets/fonts/nasalization_regular.ttf b/asloengine/builtin/assets/fonts/nasalization_regular.ttf new file mode 100755 index 0000000..8cfa31e Binary files /dev/null and b/asloengine/builtin/assets/fonts/nasalization_regular.ttf differ diff --git a/asloengine/builtin/assets/textures/texture_default_button.png b/asloengine/builtin/assets/textures/texture_default_button.png new file mode 100755 index 0000000..17efeb5 Binary files /dev/null and b/asloengine/builtin/assets/textures/texture_default_button.png differ diff --git a/asloengine/builtin/builtin.hpp b/asloengine/builtin/builtin.hpp new file mode 100755 index 0000000..8dcb525 --- /dev/null +++ b/asloengine/builtin/builtin.hpp @@ -0,0 +1,10 @@ +#pragma once + +#include "headers/scene_default.hpp" + +#include "headers/text_only_button.hpp" +#include "headers/button.hpp" +#include "headers/text_only_input_field.hpp" +#include "headers/input_field.hpp" +#include "headers/framerate_counter.hpp" +#include "headers/scroll_view.hpp" \ No newline at end of file diff --git a/asloengine/builtin/button.cpp b/asloengine/builtin/button.cpp new file mode 100755 index 0000000..9883436 --- /dev/null +++ b/asloengine/builtin/button.cpp @@ -0,0 +1,49 @@ +#include "headers/button.hpp" + +namespace asloengine +{ + + Button::Button(sf::String _name, sf::String _text, sf::Font& _font, sf::Texture& _texture, uint _text_size) + : text_vertical_offset(3.5), TextOnlyButton(_name, _text, _font, _text_size), SpriteObject(_name, _texture), GameObject(_name) {} + + Button::~Button() {} + + void Button::draw() + { + + SpriteObject::draw(); + TextOnlyButton::draw(); + + } + + void Button::on_main_property_update() + { + + SpriteObject::on_main_property_update(); + + sf::FloatRect sprite_bounds = sprite.getLocalBounds(); + sf::FloatRect text_bounds = text->getLocalBounds(); + + sf::Vector2f offset(0, -text_bounds.height / text_vertical_offset); + sf::Vector2f position_correction = calculate_child_position_centered( + sprite_bounds, text_bounds, offset, scale, rotation + ); + + text->setPosition(position.x + position_correction.x, position.y + position_correction.y); + text->setScale(scale); + text->setOrigin(origin); + text->setRotation(rotation); + + sprite_bounds = sprite.getGlobalBounds(); + update_clickable(sprite_bounds); + + } + + void Button::on_start() + { + + set_clickable(sprite.getGlobalBounds(), render_window); + + } + +} \ No newline at end of file diff --git a/asloengine/builtin/framerate_counter.cpp b/asloengine/builtin/framerate_counter.cpp new file mode 100755 index 0000000..442cb23 --- /dev/null +++ b/asloengine/builtin/framerate_counter.cpp @@ -0,0 +1,89 @@ +#include "headers/framerate_counter.hpp" + +namespace asloengine +{ + + FramerateCounter::FramerateCounter(sf::String _name, uint _update_interval) + : GameObject(_name) + { + + set_update_interval(_update_interval); + + prefix = ""; + postfix = ""; + + } + + FramerateCounter::FramerateCounter(sf::String _name, std::shared_ptr _target_text, uint _update_interval) + : GameObject(_name), target_text(_target_text) + { + + set_update_interval(_update_interval); + + prefix = ""; + postfix = ""; + + } + + FramerateCounter::~FramerateCounter() + { + + if (values) + { + delete[] values; + } + + } + + void FramerateCounter::set_update_interval(uint _update_interval) + { + + if (_update_interval < 1) + { + _update_interval = 1; + } + + update_interval = _update_interval; + + values = new float[_update_interval]; + for (uint i; i < _update_interval; i++) + { + values[i] = 0; + } + + } + + uint FramerateCounter::get_update_interval() const + { + + return update_interval; + + } + + void FramerateCounter::on_start() + { + + counter = 0; + + } + + void FramerateCounter::on_update(float delta_time) + { + + if (counter == update_interval) + { + counter = 0; + sf::String output_string = prefix + fmt::format("{:.1f}", (calculate_average(values, update_interval))) + postfix; + if (target_text) + { + target_text->setString(output_string); + } + signal_on_counter_updated(output_string); + } + + values[counter] = (1 / delta_time); + counter++; + + } + +} \ No newline at end of file diff --git a/asloengine/builtin/grid_container.cpp b/asloengine/builtin/grid_container.cpp new file mode 100755 index 0000000..d99bd1d --- /dev/null +++ b/asloengine/builtin/grid_container.cpp @@ -0,0 +1,124 @@ +#include "headers/grid_container.hpp" + +namespace asloengine +{ + + GridContainer::GridContainer(sf::String _name, sf::Vector2u _grid_size, sf::Vector2f _cell_size) + : grid_size(_grid_size), cell_size(_cell_size), GameObject(_name) {} + + GridContainer::~GridContainer() {} + + void GridContainer::update_positions() + { + + sf::Vector2f grid_anchor_position = get_position() - (get_origin() * to_vector2f(grid_size) * cell_size); + + for (int x = 0; x < grid_size.x; x++) + { + for (int y = 0; y < grid_size.y; y++) + { + + } + } + + unsigned int x = 0; + unsigned int y = 0; + + for (GameObject *const& object : objects) + { + + if (x >= grid_size.x) + { + y++; + x = 0; + } + + if (y >= grid_size.y) + { + break; + } + + sf::Vector2f tmp_vec = grid_anchor_position + sf::Vector2f(x * cell_size.x, y * cell_size.y); + object->set_position(tmp_vec); + + x++; + + } + + } + + void GridContainer::add_object(GameObject *object) + { + + objects.emplace_back(object); + + update_positions(); + + } + + void GridContainer::remove_object(int index) + { + + objects.erase(objects.begin() + index); + + update_positions(); + + } + + void GridContainer::draw() + { + + for (GameObject *const& object : objects) + { + object->draw(); + } + + } + + void GridContainer::on_start() + { + + for (GameObject *const& object : objects) + { + object->start(render_window); + } + + } + + void GridContainer::on_update(float delta_time) + { + + for (GameObject *const& object : objects) + { + object->update(delta_time); + if (!object->alive) + { + needs_clean = true; + } + } + + } + + void GridContainer::clean() + { + + for (int i = 0; i < objects.size(); i++) + { + objects.erase(objects.begin() + i); + } + + needs_clean = false; + + } + + void GridContainer::on_destroy() + { + + for (GameObject *const& object : objects) + { + object->destroy(); + } + + } + +} \ No newline at end of file diff --git a/asloengine/builtin/headers/button.hpp b/asloengine/builtin/headers/button.hpp new file mode 100755 index 0000000..665807e --- /dev/null +++ b/asloengine/builtin/headers/button.hpp @@ -0,0 +1,24 @@ +#pragma once + +#include "text_only_button.hpp" +#include "../../headers/spriteobject.hpp" + +namespace asloengine +{ + + class Button : public TextOnlyButton, public SpriteObject + { + + public: + float text_vertical_offset; + + Button(sf::String _name, sf::String _text, sf::Font& _font, sf::Texture& _texture, uint _text_size = 30); + ~Button(); + + virtual void draw() override; + virtual void on_main_property_update() override; + virtual void on_start() override; + + }; + +} \ No newline at end of file diff --git a/asloengine/builtin/headers/framerate_counter.hpp b/asloengine/builtin/headers/framerate_counter.hpp new file mode 100755 index 0000000..bf0b97e --- /dev/null +++ b/asloengine/builtin/headers/framerate_counter.hpp @@ -0,0 +1,34 @@ +#pragma once + +#include "../../headers/gameobject.hpp" +#include "fmt/format.h" + +namespace asloengine +{ + + class FramerateCounter : public GameObject + { + + public: + std::string prefix; + std::string postfix; + std::shared_ptr target_text; + aslosignals::TypeSignal signal_on_counter_updated; + + FramerateCounter(sf::String _name, uint _update_interval = 5); + FramerateCounter(sf::String _name, std::shared_ptr _target_text, uint _update_interval = 5); + ~FramerateCounter(); + + virtual void set_update_interval(uint _update_interval); + virtual uint get_update_interval() const; + virtual void on_start() override; + virtual void on_update(float delta_time) override; + + protected: + uint counter; + uint update_interval; + float *values; + + }; + +} \ No newline at end of file diff --git a/asloengine/builtin/headers/grid_container.hpp b/asloengine/builtin/headers/grid_container.hpp new file mode 100755 index 0000000..bf5b64b --- /dev/null +++ b/asloengine/builtin/headers/grid_container.hpp @@ -0,0 +1,32 @@ +#pragma once + +#include "../../headers/gameobject.hpp" + +namespace asloengine +{ + + class GridContainer : public GameObject + { + + public: + std::vector objects; + bool needs_clean = false; + sf::Vector2u grid_size; + sf::Vector2f cell_size; + + GridContainer(sf::String _name, sf::Vector2u _grid_size = sf::Vector2u(0, 0), sf::Vector2f _cell_size = sf::Vector2f(0, 0)); + virtual ~GridContainer() override; + + virtual void update_positions(); + virtual void add_object(GameObject *object); + virtual void remove_object(int index); + + virtual void draw() override; + virtual void on_start() override; + virtual void on_update(float delta_time) override; + virtual void clean(); + virtual void on_destroy() override; + + }; + +} \ No newline at end of file diff --git a/asloengine/builtin/headers/input_field.hpp b/asloengine/builtin/headers/input_field.hpp new file mode 100755 index 0000000..4abe430 --- /dev/null +++ b/asloengine/builtin/headers/input_field.hpp @@ -0,0 +1,24 @@ +#pragma once + +#include "text_only_input_field.hpp" +#include "../../headers/spriteobject.hpp" + +namespace asloengine +{ + + class InputField : public TextOnlyInputField, public SpriteObject + { + + public: + float text_vertical_offset; + + InputField(sf::String _name, sf::Vector2f _size, sf::Font& _font, sf::Texture& _texture, uint _text_size = 30, int _max_length = 999, sf::String _default_text = ""); + ~InputField(); + + virtual void draw() override; + virtual void on_main_property_update() override; + virtual void on_start() override; + + }; + +} \ No newline at end of file diff --git a/asloengine/builtin/headers/scene_default.hpp b/asloengine/builtin/headers/scene_default.hpp new file mode 100755 index 0000000..4664a3e --- /dev/null +++ b/asloengine/builtin/headers/scene_default.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include "../../headers/scene.hpp" +#include "text_only_button.hpp" +#include "button.hpp" +#include "text_only_input_field.hpp" +#include "input_field.hpp" +#include "framerate_counter.hpp" +#include "scroll_view.hpp" +#include "grid_container.hpp" + +namespace asloengine +{ + + class SceneDefault : public Scene + { + + public: + SceneDefault(); + + sf::Texture button_texture; + sf::Font button_font; + + void on_load() override; + void on_update(float delta_time) override; + + }; + +} \ No newline at end of file diff --git a/asloengine/builtin/headers/scroll_view.hpp b/asloengine/builtin/headers/scroll_view.hpp new file mode 100755 index 0000000..bb9051a --- /dev/null +++ b/asloengine/builtin/headers/scroll_view.hpp @@ -0,0 +1,38 @@ +#pragma once + +#include +#include "../../headers/gameobject.hpp" +#include "../../headers/clickable.hpp" +#include "../../headers/mouse.hpp" + +namespace asloengine +{ + + class ScrollView : public GameObject, public virtual Clickable + { + + public: + std::vector objects; + bool needs_clean = false; + sf::Vector2f size; + float scroll_amount; + float max_scroll_amount; + float scroll_speed; + + ScrollView(sf::String _name, sf::Vector2f _size, float _max_scroll_amount, float _scroll_speed = 25); + virtual ~ScrollView() override; + + virtual void set_rotation(float _rotation); + + virtual void draw() override; + virtual void on_start() override; + virtual void on_update(float delta_time) override; + virtual void clean(); + virtual void on_destroy() override; + + protected: + virtual sf::View change_view(); + + }; + +} \ No newline at end of file diff --git a/asloengine/builtin/headers/text_only_button.hpp b/asloengine/builtin/headers/text_only_button.hpp new file mode 100755 index 0000000..afc4598 --- /dev/null +++ b/asloengine/builtin/headers/text_only_button.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include "../../headers/textobject.hpp" +#include "../../headers/clickable.hpp" + +namespace asloengine +{ + + class TextOnlyButton : public TextObject, public Clickable + { + + public: + aslosignals::Signal signal_on_clicked; + + TextOnlyButton(sf::String _name, sf::String _text, sf::Font& _font, uint _text_size = 30); + virtual ~TextOnlyButton() override; + + virtual void draw() override; + virtual void on_main_property_update() override; + virtual void on_start() override; + virtual void on_update(float delta_time) override; + + }; + +} \ No newline at end of file diff --git a/asloengine/builtin/headers/text_only_input_field.hpp b/asloengine/builtin/headers/text_only_input_field.hpp new file mode 100755 index 0000000..17245e1 --- /dev/null +++ b/asloengine/builtin/headers/text_only_input_field.hpp @@ -0,0 +1,33 @@ +#pragma once + +#include "../../headers/textobject.hpp" +#include "../../headers/clickable.hpp" +#include "../../headers/keyboard.hpp" + +namespace asloengine +{ + + class TextOnlyInputField : public TextObject, public Clickable + { + + public: + sf::Vector2f size; + int max_length; + bool crop = true; + bool editable = true; + bool editing = false; + aslosignals::TypeSignal signal_on_text_changed; + aslosignals::Signal signal_on_focus; + aslosignals::Signal signal_on_lost_focus; + + TextOnlyInputField(sf::String _name, sf::Vector2f _size, sf::Font& _font, uint _text_size = 30, int _max_length = 999, sf::String _default_text = ""); + virtual ~TextOnlyInputField() override; + + virtual void draw() override; + virtual void on_main_property_update() override; + virtual void on_start() override; + virtual void on_update(float delta_time) override; + + }; + +} \ No newline at end of file diff --git a/asloengine/builtin/input_field.cpp b/asloengine/builtin/input_field.cpp new file mode 100755 index 0000000..a32bc4c --- /dev/null +++ b/asloengine/builtin/input_field.cpp @@ -0,0 +1,52 @@ +#include "headers/input_field.hpp" + +namespace asloengine +{ + + InputField::InputField(sf::String _name, sf::Vector2f _size, sf::Font& _font, sf::Texture& _texture, uint _text_size, int _max_length, sf::String _default_text) + : text_vertical_offset(3.5), TextOnlyInputField(_name, _size, _font, _text_size, _max_length, _default_text), SpriteObject(_name, _texture), GameObject(_name) {} + + InputField::~InputField() {} + + void InputField::draw() + { + + SpriteObject::draw(); + //sf::FloatRect sprite_bounds = sprite.getLocalBounds(); + //sf::View default_view = crop ? set_crop(position.x + (sprite_bounds.width - size.x) / 2, position.y, size.x, size.y * 1.5) : render_window->getView(); + TextObject::draw(); + //render_window->setView(default_view); + + } + + void InputField::on_main_property_update() + { + + SpriteObject::on_main_property_update(); + + sf::FloatRect sprite_bounds = sprite.getLocalBounds(); + sf::FloatRect text_bounds = text->getLocalBounds(); + + sf::Vector2f offset(0, -text_bounds.height / text_vertical_offset); + sf::Vector2f position_correction = calculate_child_position_centered( + sprite_bounds, text_bounds, offset, scale, rotation + ); + + text->setPosition(position.x + position_correction.x, position.y + position_correction.y); + text->setScale(scale); + text->setOrigin(origin); + text->setRotation(rotation); + + sprite_bounds = sprite.getGlobalBounds(); + update_clickable(sprite_bounds); + + } + + void InputField::on_start() + { + + set_clickable(sprite.getGlobalBounds(), render_window); + + } + +} \ No newline at end of file diff --git a/asloengine/builtin/scene_default.cpp b/asloengine/builtin/scene_default.cpp new file mode 100755 index 0000000..e5d33e2 --- /dev/null +++ b/asloengine/builtin/scene_default.cpp @@ -0,0 +1,86 @@ +#include "headers/scene_default.hpp" + +namespace asloengine +{ + + SceneDefault::SceneDefault() + : Scene("SceneDefault") {} + + void SceneDefault::on_load() + { + + Layer base_layer; + Layer gui_layer; + + button_texture = sf::Texture(); + button_texture.loadFromFile("asloengine/builtin/assets/textures/texture_default_button.png"); + + button_font = sf::Font(); + button_font.loadFromFile("asloengine/builtin/assets/fonts/nasalization_regular.ttf"); + + Button *btn1 = new Button("Login Button", "Login", button_font, button_texture); + //btn1->set_position(100, 50); + + TextOnlyButton *tbtn1 = new TextOnlyButton("Exit Button", "Exit Game", button_font); + //tbtn1->set_position(100, 125); + + TextObject *to1 = new TextObject("Info Text", "Aslo Engine v0.9.0 by Aslan2142", button_font); + //to1->set_position(630, 0); + //to1->set_origin(1, 0); + btn1->signal_on_clicked.connect_member(to1, &TextObject::set_text, sf::String("lulz")); + + FramerateCounter *fctr1 = new FramerateCounter("fctr1", 5); + fctr1->signal_on_counter_updated.connect_member(to1, &TextObject::set_text); + fctr1->postfix = " FPS"; + + TextOnlyInputField *toif = new TextOnlyInputField("toif1", sf::Vector2f(100, 30), button_font, 30, 10, "input"); + toif->set_position(200, 300); + + InputField *if1 = new InputField("if_1", sf::Vector2f(200, 30), button_font, button_texture, 30, 20); + if1->set_position(100, 420); + if1->signal_on_focus.connect_member(to1, &TextObject::set_text, sf::String("gained focus")); + if1->signal_on_lost_focus.connect_member(to1, &TextObject::set_text, sf::String("lost focus")); + //if1->signal_on_text_changed.connect_member(this, &SceneDefault::on_test); + + ScrollView *sc1 = new ScrollView("scroll1", sf::Vector2f(160, 160), 200); + sc1->set_position(640, 480); + sc1->set_origin(1, 1); + + InputField *if2 = new InputField("if_2", sf::Vector2f(200, 30), button_font, button_texture, 30, 20); + //if2->set_position(20, 20); + if2->signal_on_focus.connect_member(to1, &TextObject::set_text, sf::String("gained focus")); + if2->signal_on_lost_focus.connect_member(to1, &TextObject::set_text, sf::String("lost focus")); + + /*sc1->objects.emplace_back(if2); + + base_layer.emplace_back(fctr1); + base_layer.emplace_back(btn1); + base_layer.emplace_back(tbtn1); + base_layer.emplace_back(to1); + base_layer.emplace_back(if1); + gui_layer.emplace_back(toif); + gui_layer.emplace_back(sc1);*/ + + GridContainer *container = new GridContainer("cont1", sf::Vector2u(2, 2), sf::Vector2f(200, 150)); + container->set_position(100, 200); + container->add_object(to1); + container->add_object(if2); + container->add_object(btn1); + container->add_object(tbtn1); + + + base_layer.emplace_back(container); + + layers.emplace_back(base_layer); + fixed_layers.emplace_back(gui_layer); + + } + + void SceneDefault::on_update(float delta_time) + { + + move_camera(sf::Vector2f(1, 2)); + + } + +} \ No newline at end of file diff --git a/asloengine/builtin/scroll_view.cpp b/asloengine/builtin/scroll_view.cpp new file mode 100755 index 0000000..db5541f --- /dev/null +++ b/asloengine/builtin/scroll_view.cpp @@ -0,0 +1,114 @@ +#include "headers/scroll_view.hpp" + +namespace asloengine +{ + + ScrollView::ScrollView(sf::String _name, sf::Vector2f _size, float _max_scroll_amount, float _scroll_speed) + : size(_size), max_scroll_amount(_max_scroll_amount), scroll_speed(_scroll_speed), GameObject(_name), Clickable(sf::Mouse::Left) {} + + ScrollView::~ScrollView() {} + + void ScrollView::set_rotation(float _rotation) {} + + void ScrollView::draw() + { + + sf::View default_view = change_view(); + + for (GameObject *const& object : objects) + { + object->draw(); + } + + render_window->setView(default_view); + + } + + void ScrollView::on_start() + { + + set_clickable(sf::FloatRect(get_position().x - origin.x * size.x, get_position().y - origin.y * size.y, size.x, size.y), render_window); + + for (GameObject *const& object : objects) + { + object->start(render_window); + } + + } + + void ScrollView::on_update(float delta_time) + { + + if (is_mouse_in()) + { + scroll_amount -= Mouse::mouse_wheel_delta * scroll_speed; + scroll_amount = clamp(scroll_amount, 0, max_scroll_amount); + } + + sf::View default_view = change_view(); + + for (GameObject *const& object : objects) + { + object->update(delta_time); + if (!object->alive) + { + needs_clean = true; + } + } + + if (needs_clean) + { + clean(); + } + + render_window->setView(default_view); + + } + + void ScrollView::clean() + { + + for (int i = 0; i < objects.size(); i++) + { + objects.erase(objects.begin() + i); + } + + needs_clean = false; + + } + + void ScrollView::on_destroy() + { + + for (GameObject *const& object : objects) + { + object->destroy(); + } + + } + + sf::View ScrollView::change_view() + { + + sf::View default_view = render_window->getView(); + sf::View view = default_view; + sf::Vector2u window_size = render_window->getSize(); + + sf::Vector2f camera_center = default_view.getCenter() - default_view.getSize() / 2; + + view.reset(sf::FloatRect(0, 0 + scroll_amount, size.x, size.y)); + + view.setViewport(sf::FloatRect( + (position.x - camera_center.x - size.x * origin.x) / window_size.x, + (position.y - camera_center.y - size.y * origin.y) / window_size.y, + size.x / window_size.x, + size.y / window_size.y + )); + + render_window->setView(view); + + return default_view; + + } + +} \ No newline at end of file diff --git a/asloengine/builtin/text_only_button.cpp b/asloengine/builtin/text_only_button.cpp new file mode 100755 index 0000000..d1d7934 --- /dev/null +++ b/asloengine/builtin/text_only_button.cpp @@ -0,0 +1,44 @@ +#include "headers/text_only_button.hpp" + +namespace asloengine +{ + + TextOnlyButton::TextOnlyButton(sf::String _name, sf::String _text, sf::Font& _font, uint _text_size) + : TextObject(_name, _text, _font, _text_size), GameObject(_name), Clickable(sf::Mouse::Left) {} + + TextOnlyButton::~TextOnlyButton() {} + + void TextOnlyButton::draw() + { + + TextObject::draw(); + + } + + void TextOnlyButton::on_main_property_update() + { + + TextObject::on_main_property_update(); + + update_clickable(text->getGlobalBounds()); + + } + + void TextOnlyButton::on_start() + { + + set_clickable(text->getGlobalBounds(), render_window); + + } + + void TextOnlyButton::on_update(float delta_time) + { + + if (clicked_press_and_release()) + { + signal_on_clicked(); + } + + } + +} \ No newline at end of file diff --git a/asloengine/builtin/text_only_input_field.cpp b/asloengine/builtin/text_only_input_field.cpp new file mode 100755 index 0000000..238f212 --- /dev/null +++ b/asloengine/builtin/text_only_input_field.cpp @@ -0,0 +1,78 @@ +#include "headers/text_only_input_field.hpp" + +namespace asloengine +{ + + TextOnlyInputField::TextOnlyInputField(sf::String _name, sf::Vector2f _size, sf::Font& _font, uint _text_size, int _max_length, sf::String _default_text) + : size(_size), max_length(_max_length), TextObject(_name, _default_text, _font, _text_size), GameObject(_name), Clickable(sf::Mouse::Left) {} + + TextOnlyInputField::~TextOnlyInputField() {} + + void TextOnlyInputField::draw() + { + + //sf::View default_view = crop ? set_crop(position.x, position.y, size.x, size.y * 1.5) : render_window->getView(); + TextObject::draw(); + //render_window->setView(default_view); + + } + + void TextOnlyInputField::on_main_property_update() + { + + TextObject::on_main_property_update(); + + update_clickable(sf::FloatRect(position, size)); + + } + + void TextOnlyInputField::on_start() + { + + set_clickable(sf::FloatRect(position, size), render_window); + + } + + void TextOnlyInputField::on_update(float delta_time) + { + + if (editable) + { + + if (get_click_action() == ClickAction::Pressed) + { + if (is_mouse_in()) + { + if (!editing) + { + signal_on_focus(); + } + editing = true; + } else { + if (editing) + { + signal_on_lost_focus(); + } + editing = false; + } + } + + if (editing && Keyboard::entered_text != 0) + { + if (Keyboard::entered_text == 8 || Keyboard::entered_text == 127) + { + sf::String tmp_text = get_text(); + set_text(tmp_text.substring(0, tmp_text.getSize() - 1)); + signal_on_text_changed(get_text(), Keyboard::entered_text); + } else if (get_text_length() < max_length) { + set_text(get_text() + sf::String(Keyboard::entered_text)); + signal_on_text_changed(get_text(), Keyboard::entered_text); + } + + } + + } + + } + +} \ No newline at end of file diff --git a/asloengine/clickable.cpp b/asloengine/clickable.cpp new file mode 100755 index 0000000..2a9bda0 --- /dev/null +++ b/asloengine/clickable.cpp @@ -0,0 +1,100 @@ +#include "headers/clickable.hpp" + +namespace asloengine +{ + + Clickable::Clickable(sf::Mouse::Button _click_button) + : click_button(_click_button) {} + + Clickable::~Clickable() {} + + void Clickable::set_clickable(sf::FloatRect rect, sf::RenderWindow *window) + { + + clickable_rect = rect; + clickable_window = window; + + } + + void Clickable::update_clickable(sf::FloatRect rect) + { + + clickable_rect = rect; + + } + + bool Clickable::is_mouse_in() const + { + + sf::Vector2i mouse_position = sf::Mouse::getPosition(*clickable_window); + + sf::Vector2f mouse_world_position = clickable_window->mapPixelToCoords(mouse_position); + + return clickable_rect.contains(mouse_world_position.x, mouse_world_position.y); + + } + + Clickable::ClickAction Clickable::get_click_action() const + { + + if (pressed) + { + if (!sf::Mouse::isButtonPressed(click_button)) + { + pressed = false; + return ClickAction::Released; + } + } else { + if (sf::Mouse::isButtonPressed(click_button)) + { + pressed = true; + return ClickAction::Pressed; + } + } + + return ClickAction::Nothing; + + } + + bool Clickable::clicked_press() const + { + + ClickAction action = get_click_action(); + + return action == ClickAction::Pressed && is_mouse_in(); + + } + + bool Clickable::clicked_release() const + { + + ClickAction action = get_click_action(); + + return action == ClickAction::Released && is_mouse_in(); + + } + + bool Clickable::clicked_press_and_release() const + { + + ClickAction action = get_click_action(); + + if (clicking) + { + if (action == ClickAction::Released) + { + clicking = false; + return is_mouse_in(); + } + } else { + if (action == ClickAction::Pressed) + { + clicking = is_mouse_in(); + } + } + + return false; + + } + +} \ No newline at end of file diff --git a/asloengine/core.cpp b/asloengine/core.cpp new file mode 100755 index 0000000..bd18adb --- /dev/null +++ b/asloengine/core.cpp @@ -0,0 +1,94 @@ +#include "headers/core.hpp" + +namespace asloengine +{ + + static sf::RenderWindow *main_window; + + void init(Scene *starting_scene) + { + + LOG("START Init"); + + main_window = new sf::RenderWindow(sf::VideoMode(RESOLUTION_X, RESOLUTION_Y, BIT_DEPTH), + PROGRAM_INFO, sf::Style::Fullscreen); + + main_window->setVerticalSyncEnabled(VSYNC_ENABLED); + main_window->setFramerateLimit(MAX_FRAMERATE); + + SceneManager::load_scene(starting_scene); + + LOG("END Init"); + + } + + void start_main_game_loop() + { + + LOG("START Main Game Loop"); + + sf::Clock clock; + bool quitting = false; + + SceneManager::scene->start(main_window); + + // Main Game Loop + while (main_window->isOpen()) + { + + Keyboard::entered_text = 0; + Mouse::mouse_wheel_delta = 0; + + // Process Events + sf::Event event; + while (main_window->pollEvent(event)) + { + switch (event.type) + { + + case sf::Event::Closed: + SceneManager::unload_scene(); + quitting = true; + main_window->close(); + break; + + case sf::Event::TextEntered: + Keyboard::entered_text = event.text.unicode; + break; + + case sf::Event::MouseWheelScrolled: + Mouse::mouse_wheel_delta = event.mouseWheelScroll.delta; + break; + + } + } + + main_window->clear(); + + // Scene Drawing + if (SceneManager::scene != NULL) + { + SceneManager::scene->update(clock.restart().asSeconds()); + SceneManager::scene->draw(); + } else if (!quitting) { + WARN("no scene loaded (pointer refering to nothing)"); + } + + main_window->display(); + + // Load Next Scene if Requested + if (SceneManager::next_scene != NULL) + { + SceneManager::load_scene(SceneManager::next_scene, main_window); + SceneManager::next_scene = NULL; + } + + } + + delete main_window; + + LOG("END Main Game Loop"); + + } + +} \ No newline at end of file diff --git a/asloengine/gameobject.cpp b/asloengine/gameobject.cpp new file mode 100755 index 0000000..7f25da6 --- /dev/null +++ b/asloengine/gameobject.cpp @@ -0,0 +1,275 @@ +#include "headers/gameobject.hpp" + +namespace asloengine +{ + + GameObject::GameObject(sf::String _name) + { + + name = _name; + + position = sf::Vector2f(0, 0); + scale = sf::Vector2f(1, 1); + origin = sf::Vector2f(0, 0); + rotation = 0; + + } + + GameObject::~GameObject() {} + + void GameObject::start(sf::RenderWindow *window) + { + + render_window = window; + + alive = true; + + LOG("GameObject '" + name + "' has been Started"); + + on_start(); + + } + + void GameObject::update(float delta_time) + { + + if (alive) + { + on_update(delta_time); + if (main_property_changed) + { + on_main_property_update(); + main_property_changed = false; + } + on_post_update(delta_time); + } + + } + + void GameObject::destroy() + { + + if (alive) + { + on_destroy(); + + alive = false; + + LOG("GameObject '" + name + "' has been Destroyed"); + + delete this; + } + + } + + sf::Vector2f GameObject::calculate_child_position(sf::Vector2f& offset, sf::Vector2f& scale, float rotation) + { + + float radians = DEG_TO_RAD * (rotation + 90); + float sinus = sin(radians); + float cosinus = cos(radians); + + sf::Vector2f position_vec + { + offset.x * scale.x * sinus + offset.y * scale.y * cosinus, + offset.x * scale.x * -cosinus + offset.y * scale.y * sinus + }; + + return position_vec; + + } + + sf::Vector2f GameObject::calculate_child_position_centered( + sf::FloatRect& parent_rect, sf::FloatRect& child_rect, sf::Vector2f& offset, sf::Vector2f& scale, float rotation + ) + { + + offset.x += parent_rect.width / 2 - child_rect.width / 2; + offset.y += parent_rect.height / 2 - child_rect.height / 2; + + return calculate_child_position(offset, scale, rotation); + + } + + sf::View GameObject::set_crop(sf::Vector2f _position, sf::Vector2f _size) + { + + return set_crop(_position.x, _position.y, _size.x, _size.y); + + } + + sf::View GameObject::set_crop(float _left, float _top, float _width, float _height) + { + + sf::Vector2u window = render_window->getSize(); + + sf::View last_view = render_window->getView(); + sf::View view = last_view; + + view.reset(sf::FloatRect(_left, _top, _width, _height)); + view.setViewport(sf::FloatRect(_left / window.x, _top / window.y, _width / window.x, _height / window.y)); + render_window->setView(view); + + return last_view; + + } + + void GameObject::set_position(sf::Vector2f& _position) + { + + position = _position; + + main_property_changed = true; + + } + + void GameObject::set_scale(sf::Vector2f& _scale) + { + + scale = _scale; + + main_property_changed = true; + + } + + void GameObject::set_origin(sf::Vector2f& _origin) + { + + origin = _origin; + + main_property_changed = true; + + } + + void GameObject::set_rotation(float _rotation) + { + + rotation = _rotation; + + main_property_changed = true; + + } + + void GameObject::set_position(float _position_x, float _position_y) + { + + position.x = _position_x; + position.y = _position_y; + + main_property_changed = true; + + } + + void GameObject::set_scale(float _scale_x, float _scale_y) + { + + scale.x = _scale_x; + scale.y = _scale_y; + + main_property_changed = true; + + } + + void GameObject::set_origin(float _origin_x, float _origin_y) + { + + origin.x = _origin_x; + origin.y = _origin_y; + + main_property_changed = true; + + } + + void GameObject::move(sf::Vector2f& _move) + { + + sf::Vector2f vec = position + _move; + set_position(vec); + + } + + void GameObject::rescale(sf::Vector2f& _rescale) + { + + sf::Vector2f vec = scale + _rescale; + set_scale(vec); + + } + + void GameObject::translate_origin(sf::Vector2f& _translate_origin) + { + + sf::Vector2f vec = origin + _translate_origin; + set_origin(vec); + + } + + void GameObject::rotate(float _rotate) + { + + set_rotation(rotation + _rotate); + + } + + void GameObject::move(float _move_x, float _move_y) + { + + set_position(position.x + _move_x, position.y + _move_y); + + } + + void GameObject::rescale(float _rescale_x, float _rescale_y) + { + + set_scale(scale.x + _rescale_x, scale.y + _rescale_y); + + } + + void GameObject::translate_origin(float _translate_origin_x, float _translate_origin_y) + { + + set_origin(origin.x + _translate_origin_x, origin.y + _translate_origin_y); + + } + + sf::Vector2f GameObject::get_position() const + { + + return position; + + } + + sf::Vector2f GameObject::get_scale() const + { + + return scale; + + } + + sf::Vector2f GameObject::get_origin() const + { + + return origin; + + } + + float GameObject::get_rotation() const + { + + return rotation; + + } + + void GameObject::draw() {} + + void GameObject::on_main_property_update() {} + + void GameObject::on_start() {} + + void GameObject::on_update(float delta_time) {} + + void GameObject::on_post_update(float delta_time) {} + + void GameObject::on_destroy() {} + +} \ No newline at end of file diff --git a/asloengine/headers/aslosignals.hpp b/asloengine/headers/aslosignals.hpp new file mode 100755 index 0000000..f58cbd9 --- /dev/null +++ b/asloengine/headers/aslosignals.hpp @@ -0,0 +1,163 @@ +//AsloSignals v1.0.0 + +#include +#include +#include + +namespace aslosignals +{ + + class SlotBase + { + + public: + virtual void emit() {} + + }; + + template + class Slot : public SlotBase + { + + public: + void emit() override + { + std::apply(slot, parameters); + } + std::function slot; + std::tuple parameters; + + }; + + class Signal + { + + public: + std::vector slots; + + // Connect Member Method + template + int connect_member(T *instance, void (T::*slot)(Args...), Args... parameters) + { + + return bind((std::function)([=](Args...) { (instance->*slot)(parameters...); })); + + } + + // Connect Const Member Method + template + int connect_member(T *instance, void (T::*slot)(Args...) const, Args... parameters) + { + + return bind((std::function)([=](Args...) { (instance->*slot)(parameters...); })); + + } + + // Connect Function + template + int connect(void (*slot)(Args...), Args... parameters) + { + + return bind((std::function)([=](Args...) { (*slot)(parameters...); })); + + } + + void disconnect(int index) + { + + slots.erase(slots.begin() + index); + + } + + void clear() + { + + slots.clear(); + + } + + void operator()() + { + + for (SlotBase *& slot : slots) + { + slot->emit(); + } + + } + + private: + template + int bind(std::function slot) + { + + Slot *_slot = new Slot(); + _slot->slot = slot; + slots.emplace_back(_slot); + return slots.size() - 1; + + } + + }; + + template + class TypeSignal + { + + public: + std::vector> slots; + + // Connect Member Method + template + int connect_member(T *instance, void (T::*slot)(Args...)) + { + + return connect([=](Args... args) { (instance->*slot)(args...); }); + + } + + // Connect Const Member Method + template + int connect_member(T *instance, void (T::*slot)(Args...) const) + { + + return connect([=](Args... args) { (instance->*slot)(args...); }); + + } + + // Connect Function + int connect(std::function slot) + { + + slots.emplace_back(slot); + return slots.size() - 1; + + } + + void disconnect(int index) + { + + slots.erase(slots.begin() + index); + + } + + void clear() + { + + slots.clear(); + + } + + void operator()(Args... args) + { + + for (std::function& slot : slots) + { + slot(args...); + } + + } + + }; + +} diff --git a/asloengine/headers/clickable.hpp b/asloengine/headers/clickable.hpp new file mode 100755 index 0000000..8f6b062 --- /dev/null +++ b/asloengine/headers/clickable.hpp @@ -0,0 +1,39 @@ +#pragma once + +#include +#include "helpers.hpp" + +namespace asloengine +{ + + class Clickable + { + + public: + enum ClickAction + { + Nothing, Pressed, Released + }; + + sf::Mouse::Button click_button; + + Clickable(sf::Mouse::Button _click_button); + virtual ~Clickable(); + + void set_clickable(sf::FloatRect rect, sf::RenderWindow *window); + void update_clickable(sf::FloatRect rect); + bool is_mouse_in() const; + ClickAction get_click_action() const; + bool clicked_press() const; + bool clicked_release() const; + bool clicked_press_and_release() const; + + private: + sf::FloatRect clickable_rect; + sf::RenderWindow *clickable_window; + mutable bool pressed = false; + mutable bool clicking = false; + + }; + +} \ No newline at end of file diff --git a/asloengine/headers/core.hpp b/asloengine/headers/core.hpp new file mode 100755 index 0000000..adeeb35 --- /dev/null +++ b/asloengine/headers/core.hpp @@ -0,0 +1,14 @@ +#pragma once + +#include +#include "scenemanager.hpp" +#include "keyboard.hpp" +#include "mouse.hpp" + +namespace asloengine +{ + + void init(Scene *starting_scene); + void start_main_game_loop(); + +} \ No newline at end of file diff --git a/asloengine/headers/define.hpp b/asloengine/headers/define.hpp new file mode 100644 index 0000000..7c1846b --- /dev/null +++ b/asloengine/headers/define.hpp @@ -0,0 +1,14 @@ +#pragma once + +#define PROGRAM_NAME "Space Strategy" +#define PROGRAM_VERSION "0.1.0" +#define PROGRAM_INFO (std::string)PROGRAM_NAME + " v" + PROGRAM_VERSION +#define PROGRAM_BUILD 0 +#define PROGRAM_CREATOR "Aslan2142" +#define COPYRIGHT "Copyright 2019" +#define RESOLUTION_X 1920 +#define RESOLUTION_Y 1080 +#define BIT_DEPTH 24 +#define MAX_FRAMERATE 60 +#define VSYNC_ENABLED true +#define DEBUG \ No newline at end of file diff --git a/asloengine/headers/gameobject.hpp b/asloengine/headers/gameobject.hpp new file mode 100755 index 0000000..e7a765b --- /dev/null +++ b/asloengine/headers/gameobject.hpp @@ -0,0 +1,76 @@ +#pragma once + +#include +#include +#include "aslosignals.hpp" +#include "helpers.hpp" + +namespace asloengine +{ + + class GameObject + { + + public: + sf::RenderWindow *render_window; + sf::String name = "nonameobject"; + bool alive = true; + + GameObject(sf::String _name); + virtual ~GameObject(); + + virtual void start(sf::RenderWindow *window); + virtual void update(float delta_time); + virtual void destroy(); + + static sf::Vector2f calculate_child_position(sf::Vector2f& offset, sf::Vector2f& scale, float rotation); + static sf::Vector2f calculate_child_position_centered( + sf::FloatRect& parent_rect, sf::FloatRect& child_rect, sf::Vector2f& offset, sf::Vector2f& scale, float rotation + ); + + virtual sf::View set_crop(sf::Vector2f _position, sf::Vector2f _size); + virtual sf::View set_crop(float _left, float _top, float _width, float _height); + + // Main Property Getters and Setters + virtual void set_position(sf::Vector2f& _position); + virtual void set_scale(sf::Vector2f& _scale); + virtual void set_origin(sf::Vector2f& _origin); + virtual void set_rotation(float _rotation); + + virtual void set_position(float _position_x, float _position_y); + virtual void set_scale(float _scale_x, float _scale_y); + virtual void set_origin(float _origin_x, float _origin_y); + + virtual sf::Vector2f get_position() const; + virtual sf::Vector2f get_scale() const; + virtual sf::Vector2f get_origin() const; + virtual float get_rotation() const; + + // Main Property Modifiers + virtual void move(sf::Vector2f& _move); + virtual void rescale(sf::Vector2f& _rescale); + virtual void translate_origin(sf::Vector2f& _translate_origin); + virtual void rotate(float _rotate); + + virtual void move(float _move_x, float _move_y); + virtual void rescale(float _rescale_x, float _rescale_y); + virtual void translate_origin(float _translate_origin_x, float _translate_origin_y); + + // Custom Derived Implementations + virtual void draw(); + virtual void on_main_property_update(); + virtual void on_start(); + virtual void on_update(float delta_time); + virtual void on_post_update(float delta_time); + virtual void on_destroy(); + + protected: + bool main_property_changed = false; + sf::Vector2f position; + sf::Vector2f scale; + sf::Vector2f origin; + float rotation; + + }; + +} \ No newline at end of file diff --git a/asloengine/headers/helpers.hpp b/asloengine/headers/helpers.hpp new file mode 100755 index 0000000..cc2ea90 --- /dev/null +++ b/asloengine/headers/helpers.hpp @@ -0,0 +1,83 @@ +#pragma once + +#include +#include +#include +#include "define.hpp" + +#ifdef DEBUG +#define LOG(message) asloengine::log((std::string)"LOG: ", message) +#define WARN(message) asloengine::log((std::string)"WARNING: ", message) +#define ERR(message) asloengine::log((std::string)"ERROR: ", message) +#else +#define LOG(message) +#define WARN(message) +#define ERR(message) +#endif + +#define DEG_TO_RAD 0.01745 + +namespace asloengine +{ + + void log(const std::string& prefix, const bool condition); + void log(const std::string& prefix, const int number); + void log(const std::string& prefix, const double number); + void log(const std::string& prefix, const char* message); + void log(const std::string& prefix, const std::string& message); + + sf::Vector2f operator+(sf::Vector2f _vec, float add); + sf::Vector2f operator-(sf::Vector2f _vec, float subtract); + sf::Vector2f operator*(sf::Vector2f _vec, float multiplier); + sf::Vector2f operator/(sf::Vector2f _vec, float divider); + + sf::Vector2f operator+(sf::Vector2f _vec_1, sf::Vector2f _vec_2); + sf::Vector2f operator-(sf::Vector2f _vec_1, sf::Vector2f _vec_2); + sf::Vector2f operator*(sf::Vector2f _vec_1, sf::Vector2f _vec_2); + sf::Vector2f operator/(sf::Vector2f _vec_1, sf::Vector2f _vec_2); + + sf::Vector2f operator+(sf::Vector2f _vec, sf::FloatRect _rect); + sf::Vector2f operator-(sf::Vector2f _vec, sf::FloatRect _rect); + sf::Vector2f operator*(sf::Vector2f _vec, sf::FloatRect _rect); + sf::Vector2f operator/(sf::Vector2f _vec, sf::FloatRect _rect); + + float clamp(float value, float min, float max); + + sf::Vector2i to_vector2i(sf::Vector2u _vec); + sf::Vector2i to_vector2i(sf::Vector2f _vec); + sf::Vector2u to_vector2u(sf::Vector2i _vec); + sf::Vector2u to_vector2u(sf::Vector2f _vec); + sf::Vector2f to_vector2f(sf::Vector2i _vec); + sf::Vector2f to_vector2f(sf::Vector2u _vec); + + template + T calculate_average(T *array, size_t size) + { + + T sum; + for (size_t i = 0; i < size; i++) + { + sum += array[i]; + } + + return (sum / (T)size); + + } + + template + int vector_contains(std::vector& vec, T element) + { + + for(int i = 0; i < vec.size(); i++) + { + if (vec[i] == element) + { + return i; + } + } + + return -1; + + } + +} \ No newline at end of file diff --git a/asloengine/headers/keyboard.hpp b/asloengine/headers/keyboard.hpp new file mode 100755 index 0000000..dfa4238 --- /dev/null +++ b/asloengine/headers/keyboard.hpp @@ -0,0 +1,16 @@ +#pragma once + +#include "helpers.hpp" + +namespace asloengine +{ + + class Keyboard + { + + public: + static sf::Uint32 entered_text; + + }; + +} \ No newline at end of file diff --git a/asloengine/headers/mouse.hpp b/asloengine/headers/mouse.hpp new file mode 100755 index 0000000..83c2454 --- /dev/null +++ b/asloengine/headers/mouse.hpp @@ -0,0 +1,16 @@ +#pragma once + +#include "helpers.hpp" + +namespace asloengine +{ + + class Mouse + { + + public: + static float mouse_wheel_delta; + + }; + +} \ No newline at end of file diff --git a/asloengine/headers/scene.hpp b/asloengine/headers/scene.hpp new file mode 100755 index 0000000..15137e9 --- /dev/null +++ b/asloengine/headers/scene.hpp @@ -0,0 +1,41 @@ +#pragma once + +#include +#include "gameobject.hpp" + +namespace asloengine +{ + + typedef std::vector Layer; + + class Scene + { + + public: + std::string name = "nonamescene"; + sf::RenderWindow *scene_window; + std::vector layers; + std::vector fixed_layers; + sf::FloatRect camera_2d_rect; + bool needs_clean = false; + + Scene(std::string _name); + + void draw(); + void load(); + void start(sf::RenderWindow *window); + void update(float delta_time); + void clean(); + void destroy(); + + void move_camera(sf::Vector2f _move); + + // Custom Derived Implementations + virtual void on_load(); + virtual void on_update(float delta_time); + virtual void on_post_update(float delta_time); + virtual void on_destroy(); + + }; + +} \ No newline at end of file diff --git a/asloengine/headers/scenemanager.hpp b/asloengine/headers/scenemanager.hpp new file mode 100755 index 0000000..4182f1b --- /dev/null +++ b/asloengine/headers/scenemanager.hpp @@ -0,0 +1,24 @@ +#pragma once + +#define SCENE_MANAGER_H + +#include "scene.hpp" + +namespace asloengine +{ + + class SceneManager + { + + public: + static Scene *scene; + static Scene *next_scene; + + static void load_scene(Scene *_scene); + static void load_scene(Scene *_scene, sf::RenderWindow *window); + static void set_scene(Scene *_scene); + static void unload_scene(); + + }; + +} \ No newline at end of file diff --git a/asloengine/headers/spriteobject.hpp b/asloengine/headers/spriteobject.hpp new file mode 100755 index 0000000..38c42e5 --- /dev/null +++ b/asloengine/headers/spriteobject.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include "gameobject.hpp" + +namespace asloengine +{ + + class SpriteObject : public virtual GameObject + { + + public: + SpriteObject(std::string _name); + SpriteObject(std::string _name, sf::Texture& _texture); + virtual ~SpriteObject() override; + + void load_texture(sf::Texture& _texture); + virtual void draw() override; + virtual void on_main_property_update() override; + + protected: + sf::Sprite sprite; + + }; + +} \ No newline at end of file diff --git a/asloengine/headers/textobject.hpp b/asloengine/headers/textobject.hpp new file mode 100755 index 0000000..cc3057e --- /dev/null +++ b/asloengine/headers/textobject.hpp @@ -0,0 +1,30 @@ +#pragma once + +#include "gameobject.hpp" + +namespace asloengine +{ + + class TextObject : public virtual GameObject + { + + public: + std::shared_ptr text; + + TextObject(std::string _name, sf::String _text, sf::Font& _font, uint _text_size = 30); + virtual ~TextObject() override; + + void load_font(sf::Font& _font); + virtual void draw() override; + virtual void on_main_property_update() override; + + // Getters and Setters + virtual void set_text(sf::String _text); + virtual void set_text_size(uint _text_size); + virtual sf::String get_text() const; + virtual uint get_text_size() const; + virtual int get_text_length() const; + + }; + +} \ No newline at end of file diff --git a/asloengine/helpers.cpp b/asloengine/helpers.cpp new file mode 100755 index 0000000..e572620 --- /dev/null +++ b/asloengine/helpers.cpp @@ -0,0 +1,209 @@ +#include "headers/helpers.hpp" + +namespace asloengine +{ + + unsigned long long log_count = 0; + + void log(const std::string& prefix, const bool condition) + { + + #ifdef DEBUG + std::string new_message = condition ? "true" : "false"; + log(prefix, new_message); + #endif + + } + + void log(const std::string& prefix, const int number) + { + + #ifdef DEBUG + std::string new_message = std::to_string(number); + log(prefix, new_message); + #endif + + } + + void log(const std::string& prefix, const double number) + { + + #ifdef DEBUG + std::string new_message = std::to_string(number); + log(prefix, new_message); + #endif + + } + + void log(const std::string& prefix, const char* message) + { + + #ifdef DEBUG + std::string new_message = std::string(message); + log(prefix, new_message); + #endif + + } + + void log(const std::string& prefix, const std::string& message) + { + + #ifdef DEBUG + std::string logged_message = std::to_string(log_count++) + " - " + prefix + message; + + // Log into Console + std::cout << logged_message << std::endl; + + // Log into File + if (log_count == 1) { remove("log.txt"); } + std::ofstream o_file("log.txt", std::ios_base::app); + o_file << logged_message << std::endl; + o_file.close(); + #endif + + } + + sf::Vector2f operator+(sf::Vector2f _vec, float add) + { + + return sf::Vector2f(_vec.x + add, _vec.y + add); + + } + + sf::Vector2f operator-(sf::Vector2f _vec, float subtract) + { + + return sf::Vector2f(_vec.x - subtract, _vec.y - subtract); + + } + + sf::Vector2f operator*(sf::Vector2f _vec, float multiplier) + { + + return sf::Vector2f(_vec.x * multiplier, _vec.y * multiplier); + + } + + sf::Vector2f operator/(sf::Vector2f _vec, float divider) + { + + return sf::Vector2f(_vec.x / divider, _vec.y / divider); + + } + + sf::Vector2f operator+(sf::Vector2f _vec_1, sf::Vector2f _vec_2) + { + + return sf::Vector2f(_vec_1.x + _vec_2.x, _vec_1.y + _vec_2.y); + + } + + sf::Vector2f operator-(sf::Vector2f _vec_1, sf::Vector2f _vec_2) + { + + return sf::Vector2f(_vec_1.x - _vec_2.x, _vec_1.y - _vec_2.y); + + } + + sf::Vector2f operator*(sf::Vector2f _vec_1, sf::Vector2f _vec_2) + { + + return sf::Vector2f(_vec_1.x * _vec_2.x, _vec_1.y * _vec_2.y); + + } + + sf::Vector2f operator/(sf::Vector2f _vec_1, sf::Vector2f _vec_2) + { + + return sf::Vector2f(_vec_1.x / _vec_2.x, _vec_1.y / _vec_2.y); + + } + + sf::Vector2f operator+(sf::Vector2f _vec, sf::FloatRect _rect) + { + + return sf::Vector2f(_vec.x + _rect.width, _vec.y + _rect.height); + + } + + sf::Vector2f operator-(sf::Vector2f _vec, sf::FloatRect _rect) + { + + return sf::Vector2f(_vec.x - _rect.width, _vec.y - _rect.height); + + } + + sf::Vector2f operator*(sf::Vector2f _vec, sf::FloatRect _rect) + { + + return sf::Vector2f(_vec.x * _rect.width, _vec.y * _rect.height); + + } + + sf::Vector2f operator/(sf::Vector2f _vec, sf::FloatRect _rect) + { + + return sf::Vector2f(_vec.x / _rect.width, _vec.y / _rect.height); + + } + + float clamp(float value, float min, float max) + { + + if (value < min) + { + value = min; + } + + if (value > max) + { + value = max; + } + + return value; + + } + + sf::Vector2i to_vector2i(sf::Vector2u _vec) + { + + return sf::Vector2i(_vec.x, _vec.y); + + } + + sf::Vector2i to_vector2i(sf::Vector2f _vec) + { + + return sf::Vector2i(_vec.x, _vec.y); + + } + + sf::Vector2u to_vector2u(sf::Vector2i _vec) + { + + return sf::Vector2u(_vec.x, _vec.y); + + } + + sf::Vector2u to_vector2u(sf::Vector2f _vec) + { + + return sf::Vector2u(_vec.x, _vec.y); + + } + + sf::Vector2f to_vector2f(sf::Vector2i _vec) + { + + return sf::Vector2f(_vec.x, _vec.y); + + } + + sf::Vector2f to_vector2f(sf::Vector2u _vec) + { + + return sf::Vector2f(_vec.x, _vec.y); + + } + +} \ No newline at end of file diff --git a/asloengine/keyboard.cpp b/asloengine/keyboard.cpp new file mode 100755 index 0000000..07e01bb --- /dev/null +++ b/asloengine/keyboard.cpp @@ -0,0 +1,8 @@ +#include "headers/keyboard.hpp" + +namespace asloengine +{ + + sf::Uint32 Keyboard::entered_text = 0; + +} \ No newline at end of file diff --git a/asloengine/libs.txt b/asloengine/libs.txt new file mode 100755 index 0000000..2902567 --- /dev/null +++ b/asloengine/libs.txt @@ -0,0 +1,15 @@ +// C Standard Libraries + + +// C++ Standard Libraries + + + + + +// My Libraries +"aslosignals.hpp" + +// 3rd Party Libraries + + \ No newline at end of file diff --git a/asloengine/mouse.cpp b/asloengine/mouse.cpp new file mode 100755 index 0000000..dfe8e13 --- /dev/null +++ b/asloengine/mouse.cpp @@ -0,0 +1,8 @@ +#include "headers/mouse.hpp" + +namespace asloengine +{ + + float Mouse::mouse_wheel_delta = 0; + +} \ No newline at end of file diff --git a/asloengine/scene.cpp b/asloengine/scene.cpp new file mode 100755 index 0000000..3aade20 --- /dev/null +++ b/asloengine/scene.cpp @@ -0,0 +1,192 @@ +#include "headers/scene.hpp" + +namespace asloengine +{ + + Scene::Scene(std::string _name) + : name(_name) {} + + void Scene::draw() + { + + sf::View default_view = scene_window->getView(); + sf::View view = default_view; + + view.reset(camera_2d_rect); + scene_window->setView(view); + + for (const Layer& objects : layers) + { + for (GameObject *const& object : objects) + { + object->draw(); + } + } + + scene_window->setView(default_view); + + for (const Layer& objects : fixed_layers) + { + for (GameObject *const& object : objects) + { + object->draw(); + } + } + + } + + void Scene::load() + { + + on_load(); + + LOG("Scene '" + name + "' has been Loaded"); + + } + + void Scene::update(float delta_time) + { + + on_update(delta_time); + + sf::View default_view = scene_window->getView(); + sf::View view = default_view; + + view.reset(sf::FloatRect(camera_2d_rect)); + scene_window->setView(view); + + for (const Layer& objects : layers) + { + for (GameObject *const& object : objects) + { + object->update(delta_time); + if (!object->alive) + { + needs_clean = true; + } + } + } + + scene_window->setView(default_view); + + for (const Layer& objects : fixed_layers) + { + for (GameObject *const& object : objects) + { + object->update(delta_time); + if (!object->alive) + { + needs_clean = true; + } + } + } + + if (needs_clean) + { + clean(); + } + + on_post_update(delta_time); + + } + + void Scene::clean() + { + + for (int i = 0; i < layers.size(); i++) + { + for (int j = 0; j < layers[i].size(); i++) + { + if (!layers[i][j]->alive) + { + layers[i].erase(layers[i].begin() + j); + j--; + } + } + } + + for (int i = 0; i < fixed_layers.size(); i++) + { + for (int j = 0; j < fixed_layers[i].size(); i++) + { + if (!fixed_layers[i][j]->alive) + { + fixed_layers[i].erase(fixed_layers[i].begin() + j); + j--; + } + } + } + + needs_clean = false; + + } + + void Scene::start(sf::RenderWindow *window) + { + + scene_window = window; + + camera_2d_rect = sf::FloatRect(0, 0, scene_window->getSize().x, scene_window->getSize().y); + + for (const Layer& objects : layers) + { + for (GameObject *const& object : objects) + { + object->start(window); + } + } + + for (const Layer& objects : fixed_layers) + { + for (GameObject *const& object : objects) + { + object->start(window); + } + } + + LOG("Scene '" + name + "' has been Started"); + + } + + void Scene::destroy() + { + + on_destroy(); + + for (const Layer& objects : layers) + { + for (GameObject *const& object : objects) + { + object->destroy(); + } + } + + for (const Layer& objects : fixed_layers) + { + for (GameObject *const& object : objects) + { + object->destroy(); + } + } + + LOG("Scene '" + name + "' has been Destroyed"); + + } + + void Scene::move_camera(sf::Vector2f _move) + { + + camera_2d_rect.left += _move.x; + camera_2d_rect.top += _move.y; + + } + + void Scene::on_load() {} + + void Scene::on_update(float delta_time) {} + + void Scene::on_post_update(float delta_time) {} + + void Scene::on_destroy() {} + +} \ No newline at end of file diff --git a/asloengine/scenemanager.cpp b/asloengine/scenemanager.cpp new file mode 100755 index 0000000..a3e4a30 --- /dev/null +++ b/asloengine/scenemanager.cpp @@ -0,0 +1,51 @@ +#include "headers/scenemanager.hpp" + +namespace asloengine +{ + + Scene *SceneManager::scene; + Scene *SceneManager::next_scene; + + void SceneManager::load_scene(Scene *_scene) + { + + unload_scene(); + + scene = _scene; + + scene->load(); + + } + + void SceneManager::load_scene(Scene *_scene, sf::RenderWindow *window) + { + + unload_scene(); + + scene = _scene; + + scene->load(); + scene->start(window); + + } + + void SceneManager::set_scene(Scene *_scene) + { + + next_scene = _scene; + + } + + void SceneManager::unload_scene() + { + LOG("UNLOAD"); + if (scene) + { + scene->destroy(); + delete scene; + scene = NULL; + } + + } + +} \ No newline at end of file diff --git a/asloengine/spriteobject.cpp b/asloengine/spriteobject.cpp new file mode 100755 index 0000000..48c5fd7 --- /dev/null +++ b/asloengine/spriteobject.cpp @@ -0,0 +1,45 @@ +#include "headers/spriteobject.hpp" + +namespace asloengine +{ + + SpriteObject::SpriteObject(std::string _name) + : GameObject(_name) {} + + SpriteObject::SpriteObject(std::string _name, sf::Texture& _texture) + : GameObject(_name) + { + + load_texture(_texture); + + } + + SpriteObject::~SpriteObject() {} + + void SpriteObject::load_texture(sf::Texture& _texture) + { + + sprite = sf::Sprite(_texture); + + on_main_property_update(); + + } + + void SpriteObject::draw() + { + + render_window->draw(sprite); + + } + + void SpriteObject::on_main_property_update() + { + + sprite.setScale(scale); + sprite.setPosition(position); + sprite.setOrigin(origin * sprite.getLocalBounds()); + sprite.setRotation(rotation); + + } + +} \ No newline at end of file diff --git a/asloengine/textobject.cpp b/asloengine/textobject.cpp new file mode 100755 index 0000000..095c609 --- /dev/null +++ b/asloengine/textobject.cpp @@ -0,0 +1,77 @@ +#include "headers/textobject.hpp" + +namespace asloengine +{ + + TextObject::TextObject(std::string _name, sf::String _text, sf::Font& _font, uint _text_size) + : GameObject(_name) + { + + text = std::make_shared(); + text->setFont(_font); + text->setCharacterSize(_text_size); + set_text(_text); + + } + + TextObject::~TextObject() {} + + void TextObject::draw() + { + + render_window->draw(*text); + + } + + void TextObject::on_main_property_update() + { + + sf::FloatRect text_bounds = text->getLocalBounds(); + + text->setOrigin(origin.x * text_bounds.width, origin.y * text_bounds.height * 2); + text->setScale(scale); + text->setPosition(position); + text->setRotation(rotation); + + } + + void TextObject::set_text(sf::String _text) + { + + text->setString(_text); + + on_main_property_update(); + + } + + void TextObject::set_text_size(uint _text_size) + { + + text->setCharacterSize(_text_size); + + on_main_property_update(); + + } + + sf::String TextObject::get_text() const + { + + return text->getString(); + + } + + uint TextObject::get_text_size() const + { + + return text->getCharacterSize(); + + } + + int TextObject::get_text_length() const + { + + return text->getString().getSize(); + + } + +} \ No newline at end of file diff --git a/log.txt b/log.txt new file mode 100644 index 0000000..5d3cb31 --- /dev/null +++ b/log.txt @@ -0,0 +1,17 @@ +0 - LOG: START Init +1 - LOG: Scene 'SceneDefault' has been Loaded +2 - LOG: END Init +3 - LOG: START Main Game Loop +4 - LOG: GameObject 'cont1' has been Started +5 - LOG: GameObject 'Info Text' has been Started +6 - LOG: GameObject 'if_2' has been Started +7 - LOG: GameObject 'Login Button' has been Started +8 - LOG: GameObject 'Exit Button' has been Started +9 - LOG: Scene 'SceneDefault' has been Started +10 - LOG: GameObject 'Info Text' has been Destroyed +11 - LOG: GameObject 'if_2' has been Destroyed +12 - LOG: GameObject 'Login Button' has been Destroyed +13 - LOG: GameObject 'Exit Button' has been Destroyed +14 - LOG: GameObject 'cont1' has been Destroyed +15 - LOG: Scene 'SceneDefault' has been Destroyed +16 - LOG: END Main Game Loop diff --git a/makefile b/makefile new file mode 100755 index 0000000..a1990ec --- /dev/null +++ b/makefile @@ -0,0 +1,50 @@ +ENGINE_PATH = asloengine +ENGINE_HEADERS_PATH = asloengine/headers + +ENGINE_BUILTIN_PATH = asloengine/builtin +ENGINE_BUILTIN_HEADERS_PATH = asloengine/builtin/headers + +COMPILER_FLAGS = -std=c++17 +LINK_LIBS = -lsfml-system -lsfml-window -lsfml-graphics -lfmt + +PROGRAM_BUILD_FILES = $(wildcard *.cpp) +ENGINE_BUILD_FILES = $(wildcard $(ENGINE_PATH)/*.cpp) +ENGINE_BUILTIN_BUILD_FILES = $(wildcard $(ENGINE_BUILTIN_PATH)/*.cpp) + +BUILD_DIR = obj +OUTPUT_FILE = enginetest + +VPATH = $(ENGINE_PATH) $(ENGINE_HEADERS_PATH) $(ENGINE_BUILTIN_PATH) $(ENGINE_BUILTIN_HEADERS_PATH) + +run: compile + ./$(OUTPUT_FILE) + +justrun: + ./$(OUTPUT_FILE) + +all: clean compile + +test: + g++ $(COMPILER_FLAGS) $(PROGRAM_BUILD_FILES) $(ENGINE_BUILD_FILES) $(ENGINE_BUILTIN_BUILD_FILES) -o $(OUTPUT_FILE) $(LINK_LIBS) + +compile: $(BUILD_DIR) $(patsubst %.cpp,$(BUILD_DIR)/%.o,$(PROGRAM_BUILD_FILES)) $(patsubst $(ENGINE_PATH)/%.cpp,$(BUILD_DIR)/%.o,$(ENGINE_BUILD_FILES)) $(patsubst $(ENGINE_BUILTIN_PATH)/%.cpp,$(BUILD_DIR)/%.o,$(ENGINE_BUILTIN_BUILD_FILES)) + g++ -g -O0 $(COMPILER_FLAGS) $(BUILD_DIR)/*.o -o $(OUTPUT_FILE) $(LINK_LIBS) + +release: clean $(BUILD_DIR) $(patsubst %.cpp,$(BUILD_DIR)/%.o,$(PROGRAM_BUILD_FILES)) $(patsubst $(ENGINE_PATH)/%.cpp,$(BUILD_DIR)/%.o,$(ENGINE_BUILD_FILES)) $(patsubst $(ENGINE_BUILTIN_PATH)/%.cpp,$(BUILD_DIR)/%.o,$(ENGINE_BUILTIN_BUILD_FILES)) + g++ -O3 $(COMPILER_FLAGS) $(BUILD_DIR)/*.o -o $(OUTPUT_FILE) $(LINK_LIBS) + +clear: clean + +clean: + rm -rf $(BUILD_DIR) + +core: removecore run + +removecore: + rm -f $(BUILD_DIR)/core.o + +$(BUILD_DIR): + mkdir $@ + +$(BUILD_DIR)/%.o: %.cpp %.hpp + g++ $(COMPILER_FLAGS) -c $< -o $@ \ No newline at end of file diff --git a/program.cpp b/program.cpp new file mode 100755 index 0000000..98c549b --- /dev/null +++ b/program.cpp @@ -0,0 +1,12 @@ +#include "program.hpp" + +int main() +{ + + asloengine::init(new asloengine::SceneDefault()); + + asloengine::start_main_game_loop(); + + return 0; + +} \ No newline at end of file diff --git a/program.hpp b/program.hpp new file mode 100755 index 0000000..310b026 --- /dev/null +++ b/program.hpp @@ -0,0 +1,5 @@ +#pragma once + +#include "asloengine/asloengine.hpp" + +int main(); \ No newline at end of file diff --git a/roadmap.txt b/roadmap.txt new file mode 100644 index 0000000..a9fafe9 --- /dev/null +++ b/roadmap.txt @@ -0,0 +1,4 @@ +Loading Scenes +Window Parameters +Color +Animations