From 84728b73c6cb021bb0f2b4e06e8dae03c8816853 Mon Sep 17 00:00:00 2001 From: Joseph Walton-Rivers <joseph@walton-rivers.uk> Date: Sat, 3 Sep 2022 22:44:26 +0100 Subject: [PATCH] make player spin in grid world --- demo/demo/GameScene.cpp | 4 +- demo/demo/grid.cpp | 18 +++++- demo/demo/rollball.cpp | 6 +- demo/demo/topdown.cpp | 4 +- demo/include/GameScene.h | 2 +- demo/include/grid.hpp | 6 +- demo/include/rollball.hpp | 2 +- demo/include/topdown.hpp | 2 +- fggl/app.cpp | 8 ++- fggl/scenes/game.cpp | 4 +- fggl/scenes/menu.cpp | 2 +- include/fggl/animation/animator.hpp | 87 +++++++++++++++++++++++++++++ include/fggl/app.hpp | 2 +- include/fggl/scenes/game.hpp | 4 +- include/fggl/scenes/menu.hpp | 2 +- 15 files changed, 132 insertions(+), 21 deletions(-) create mode 100644 include/fggl/animation/animator.hpp diff --git a/demo/demo/GameScene.cpp b/demo/demo/GameScene.cpp index 165c4b9..1bb95b5 100644 --- a/demo/demo/GameScene.cpp +++ b/demo/demo/GameScene.cpp @@ -172,8 +172,8 @@ void GameScene::setup() { } } -void GameScene::update() { - Game::update(); +void GameScene::update(float dt) { + Game::update(dt); process_camera(world(), input()); } diff --git a/demo/demo/grid.cpp b/demo/demo/grid.cpp index 670bbb7..16cec01 100644 --- a/demo/demo/grid.cpp +++ b/demo/demo/grid.cpp @@ -94,13 +94,15 @@ namespace demo { } } - GridScene::GridScene(fggl::App &app) : GameBase(app), m_tiles(), m_grid(nullptr) { + GridScene::GridScene(fggl::App &app) : GameBase(app), m_tiles(), m_animator(15.0F), m_grid(nullptr) { + m_animator.add([this](){this->tickPlayer();}); } void GridScene::activate() { GameBase::activate(); fggl::debug::log(fggl::debug::Level::info, "GridScene::activate()"); + m_animator.reset(); // fake loading the tileset if ( m_tiles.m_floors.empty() ) { @@ -175,6 +177,20 @@ namespace demo { } } + void GridScene::update(float deltaTime) { + GameBase::update(deltaTime); + m_animator.update(deltaTime); + } + + void GridScene::tickPlayer() { + auto &manager = m_grid->entities(); + auto entities = manager.find<CellPos>(); + for (const auto &entity : entities) { + auto &pos = manager.get<CellPos>(entity); + pos.direction = (pos.direction + 1) % 4; + } + } + //float progress = 0.0f; void GridScene::render(fggl::gfx::Graphics &gfx) { fggl::gfx::Paint paint; diff --git a/demo/demo/rollball.cpp b/demo/demo/rollball.cpp index 3ef9ec5..75439bb 100644 --- a/demo/demo/rollball.cpp +++ b/demo/demo/rollball.cpp @@ -182,12 +182,10 @@ namespace demo { return force; } - void RollBall::update() { - Game::update(); + void RollBall::update(float deltaTime) { + Game::update(deltaTime); m_phys->step(); - const float deltaTime = 1 / 60.0F; - auto& input = this->input(); if ( state.player != fggl::entity::INVALID ) { diff --git a/demo/demo/topdown.cpp b/demo/demo/topdown.cpp index dfc9609..c94ca17 100644 --- a/demo/demo/topdown.cpp +++ b/demo/demo/topdown.cpp @@ -127,8 +127,8 @@ void TopDown::activate() { populate_sample_level(factory, world()); } -void TopDown::update() { - Game::update(); +void TopDown::update(float dt) { + Game::update(dt); process_camera(world(), input()); if ( input().mouse.pressed(fggl::input::MouseButton::LEFT) ) { diff --git a/demo/include/GameScene.h b/demo/include/GameScene.h index 84ab5e6..96232ca 100644 --- a/demo/include/GameScene.h +++ b/demo/include/GameScene.h @@ -57,7 +57,7 @@ enum camera_type { cam_free, cam_arcball }; setup(); } - void update() override; + void update(float dt) override; void render(fggl::gfx::Graphics& gfx) override; private: diff --git a/demo/include/grid.hpp b/demo/include/grid.hpp index c0fd98d..380e772 100644 --- a/demo/include/grid.hpp +++ b/demo/include/grid.hpp @@ -22,6 +22,7 @@ #include <memory> #include "fggl/scenes/game.hpp" +#include "fggl/animation/animator.hpp" #include "fggl/entity/gridworld/zone.hpp" namespace demo { @@ -47,12 +48,15 @@ namespace demo { void activate() override; void deactivate() override; - //void update() override; + void update(float dt) override; void render(fggl::gfx::Graphics& gfx) override; private: fggl::entity::grid::TileSet m_tiles; + fggl::animation::FrameAnimator m_animator; std::unique_ptr<DemoGrid> m_grid; + void tickPlayer(); + }; } diff --git a/demo/include/rollball.hpp b/demo/include/rollball.hpp index 1b39f03..fc23e5c 100644 --- a/demo/include/rollball.hpp +++ b/demo/include/rollball.hpp @@ -57,7 +57,7 @@ namespace demo { void activate() override; void deactivate() override; - void update() override; + void update(float dt) override; void render(fggl::gfx::Graphics& gfx) override; private: diff --git a/demo/include/topdown.hpp b/demo/include/topdown.hpp index af4642f..519dc90 100644 --- a/demo/include/topdown.hpp +++ b/demo/include/topdown.hpp @@ -29,7 +29,7 @@ namespace demo { explicit TopDown(fggl::App& app); void activate() override; - void update() override; + void update(float dt) override; void render(fggl::gfx::Graphics& gfx) override; private: diff --git a/fggl/app.cpp b/fggl/app.cpp index 59684c8..baaf206 100644 --- a/fggl/app.cpp +++ b/fggl/app.cpp @@ -39,7 +39,13 @@ namespace fggl { state.activate(); } + auto lastTime = glfwGetTime(); + while (m_running) { + auto currTime = glfwGetTime(); + auto delta = currTime - lastTime; + lastTime = currTime; + // trigger a state change if expected if (m_expectedScene != m_states.activeID()) { auto result = m_states.change(m_expectedScene); @@ -55,7 +61,7 @@ namespace fggl { //m_modules->onUpdate(); auto &state = m_states.active(); - state.update(); + state.update((float)delta); // window rendering to frame buffer if (m_window != nullptr) { diff --git a/fggl/scenes/game.cpp b/fggl/scenes/game.cpp index db795a3..14a2139 100644 --- a/fggl/scenes/game.cpp +++ b/fggl/scenes/game.cpp @@ -28,7 +28,7 @@ namespace fggl::scenes { m_input = app.service<input::Input>(); } - void GameBase::update() { + void GameBase::update(float dt) { // detect the user quitting if (m_input != nullptr) { bool escapePressed = m_input->keyboard.pressed(glfwGetKeyScancode(GLFW_KEY_ESCAPE)); @@ -59,7 +59,7 @@ namespace fggl::scenes { m_world.reset(); } - void Game::update() { + void Game::update(float dt) { assert(m_world && "called game update, but there was no world - was activate called?"); if (m_input != nullptr) { diff --git a/fggl/scenes/menu.cpp b/fggl/scenes/menu.cpp index de6dfc0..2c38180 100644 --- a/fggl/scenes/menu.cpp +++ b/fggl/scenes/menu.cpp @@ -26,7 +26,7 @@ namespace fggl::scenes { m_inputs = app.service<input::Input>(); } - void BasicMenu::update() { + void BasicMenu::update(float dt) { if (m_inputs != nullptr) { m_cursorPos.x = m_inputs->mouse.axis(MouseAxis::X); m_cursorPos.y = m_inputs->mouse.axis(MouseAxis::Y); diff --git a/include/fggl/animation/animator.hpp b/include/fggl/animation/animator.hpp new file mode 100644 index 0000000..2a5170d --- /dev/null +++ b/include/fggl/animation/animator.hpp @@ -0,0 +1,87 @@ +/* + * This file is part of FGGL. + * + * FGGL is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any + * later version. + * + * FGGL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along with FGGL. + * If not, see <https://www.gnu.org/licenses/>. + */ + +// +// Created by webpigeon on 03/09/22. +// + +#ifndef FGGL_ANIMATION_ANIMATOR_H +#define FGGL_ANIMATION_ANIMATOR_H + +#include <functional> +#include <map> +#include <cstdint> +#include <cassert> + +namespace fggl::animation { + + using AnimationCallback = std::function<void(void)>; + using CallbackHandle = uint32_t; + + /** + * Frame-based animation. + * + * Tries to maintain a constant framerate for things that care about that. + */ + class FrameAnimator { + public: + explicit inline FrameAnimator(float targetFPS) : m_target( 1.0F / targetFPS) { + assert( 0 <= m_target ); + } + + inline void reset() { + m_current = 0; + } + + inline void update(float dt) { + assert(0 <= dt); + m_current += dt; + while ( m_current >= m_target) { + tick(); + m_current -= m_target; + } + assert(0 <= m_current); + } + + // tick the animation system, should be handled by update + inline void tick() { + for (auto& [k,v] : m_callbacks) { + v(); + } + } + + inline CallbackHandle add(AnimationCallback callback) { + auto myHandle = m_lastCallback++; + m_callbacks[myHandle] = callback; + return myHandle; + } + + inline void remove(CallbackHandle handle) { + auto itr = m_callbacks.find(handle); + if ( itr != m_callbacks.end() ) { + m_callbacks.erase(itr); + } + } + + private: + const float m_target; + float m_current = 0.0F; + + CallbackHandle m_lastCallback = 0; + std::map<CallbackHandle, AnimationCallback> m_callbacks; + }; + +} // namespace fggl::animation + +#endif //FGGL_ANIMATION_ANIMATOR_H diff --git a/include/fggl/app.hpp b/include/fggl/app.hpp index 1301916..98eab80 100644 --- a/include/fggl/app.hpp +++ b/include/fggl/app.hpp @@ -58,7 +58,7 @@ namespace fggl { * multiple updates per render or vice-versa depending on requriements. Update is intended for * dispatching game-system related infomation. */ - virtual void update() = 0; + virtual void update(float dt) = 0; /** * Perform actions neccerary for rendering the scene. diff --git a/include/fggl/scenes/game.hpp b/include/fggl/scenes/game.hpp index d9f7155..71a129f 100644 --- a/include/fggl/scenes/game.hpp +++ b/include/fggl/scenes/game.hpp @@ -30,7 +30,7 @@ namespace fggl::scenes { public: explicit GameBase(fggl::App &app); - void update() override; + void update(float dt) override; void render(fggl::gfx::Graphics &gfx) override = 0; protected: @@ -52,7 +52,7 @@ namespace fggl::scenes { void activate() override; void deactivate() override; - void update() override; + void update(float dt) override; void render(fggl::gfx::Graphics &gfx) override; protected: diff --git a/include/fggl/scenes/menu.hpp b/include/fggl/scenes/menu.hpp index 5c6220c..70c0b15 100644 --- a/include/fggl/scenes/menu.hpp +++ b/include/fggl/scenes/menu.hpp @@ -32,7 +32,7 @@ namespace fggl::scenes { public: explicit BasicMenu(App &owner); - void update() override; + void update(float dt) override; void render(gfx::Graphics &paint) override; void activate() override; -- GitLab