diff --git a/CMakeLists.txt b/CMakeLists.txt index d042943..111d535 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,6 +28,8 @@ add_executable(game src/components/mover.h src/components/mover.cpp src/masks.h + src/factory.h + src/factory.cpp ) # Reference blah diff --git a/src/components/mover.cpp b/src/components/mover.cpp index 7768c4b..a0bebb8 100644 --- a/src/components/mover.cpp +++ b/src/components/mover.cpp @@ -71,8 +71,20 @@ void Mover::stop() m_remainder.y = 0; } +bool Mover::on_ground(int dist) const +{ + if (!collider) + return false; + + return collider->check(Mask::solid, Point(0, dist)); +} + void Mover::update() { + // apply gravity + if (gravity != 0 && (!collider || !collider->check(Mask::solid, Point(0, 1)))) + speed.y += gravity * Time::delta; + // get the amount we should move, including remainder from the previous frame Vec2 total = m_remainder + speed * Time::delta; diff --git a/src/components/mover.h b/src/components/mover.h index 9c22964..c231c3f 100644 --- a/src/components/mover.h +++ b/src/components/mover.h @@ -13,8 +13,9 @@ namespace TL Vec2 m_remainder; public: - Collider* collider; + Collider* collider = nullptr; Vec2 speed; + float gravity = 0; bool move_x(int amount); bool move_y(int amount); @@ -23,6 +24,8 @@ namespace TL void stop_y(); void stop(); + bool on_ground(int dist = 1) const; + void update() override; }; } \ No newline at end of file diff --git a/src/components/player.cpp b/src/components/player.cpp index e69de29..3cac268 100644 --- a/src/components/player.cpp +++ b/src/components/player.cpp @@ -0,0 +1,86 @@ +#include "player.h" +#include "mover.h" + +using namespace TL; + +namespace +{ + constexpr float max_ground_speed = 60; + constexpr float max_air_speed = 70; + constexpr float ground_accel = 500; + constexpr float air_accel = 20; + constexpr float friction = 800; + constexpr float gravity = 450; + constexpr float jump_force = -105; + constexpr float jump_time = 0.18f; +} + +Player::Player() +{ + input_move = VirtualStick() + .add_keys(Key::Left, Key::Right, Key::Up, Key::Down) + .add_buttons(0, Button::Left, Button::Right, Button::Up, Button::Down) + .add_axes(0, Axis::LeftX, Axis::LeftY, 0.2f); + + input_jump = VirtualButton() + .press_buffer(0.15f) + .add_key(Key::X) + .add_button(0, Button::A); +} + +void Player::update() +{ + input_move.update(); + input_jump.update(); + + auto mover = get(); + auto on_ground = mover->on_ground(); + int input = input_move.value_i().x; + + // Horizontal Movement + { + + // Acceleration + mover->speed.x += input * (on_ground ? ground_accel : air_accel) * Time::delta; + + // Maxspeed + auto maxspd = (on_ground ? max_ground_speed : max_air_speed); + if (Calc::abs(mover->speed.x) > maxspd) + { + mover->speed.x = Calc::approach( + mover->speed.x, + Calc::sign(mover->speed.x) * maxspd, + 2000 * Time::delta); + } + + if (input == 0 && on_ground) + mover->speed.x = Calc::approach(mover->speed.x, 0, friction * Time::delta); + } + + // Gravity + if (!on_ground) + { + float grav = gravity; + if (Calc::abs(mover->speed.y) < 20 && input_jump.down()) + grav *= 0.4f; + + mover->speed.y += grav * Time::delta; + } + + // Jumping + { + if (input_jump.pressed() && mover->on_ground()) + { + mover->speed.x = input * max_air_speed; + m_jump_timer = jump_time; + } + + if (m_jump_timer > 0) + { + mover->speed.y = -100; + m_jump_timer -= Time::delta; + if (!input_jump.down()) + m_jump_timer = 0; + } + } +} diff --git a/src/components/player.h b/src/components/player.h index a84c172..e707308 100644 --- a/src/components/player.h +++ b/src/components/player.h @@ -9,6 +9,13 @@ namespace TL class Player : public Component { public: + VirtualStick input_move; + VirtualButton input_jump; + + Player(); void update() override; + + private: + float m_jump_timer = 0; }; } \ No newline at end of file diff --git a/src/factory.cpp b/src/factory.cpp new file mode 100644 index 0000000..1678fdc --- /dev/null +++ b/src/factory.cpp @@ -0,0 +1,23 @@ +#include "factory.h" +#include "components/animator.h" +#include "components/collider.h" +#include "components/mover.h" +#include "components/player.h" + +using namespace TL; + +Entity* Factory::player(World* world, Point position) +{ + auto en = world->add_entity(position); + + auto an = en->add(Animator("player")); + an->play("idle"); + + auto hitbox = en->add(Collider::make_rect(RectI(-4, -8, 8, 8))); + + auto mover = en->add(Mover()); + mover->collider = hitbox; + + en->add(Player()); + return en; +} diff --git a/src/factory.h b/src/factory.h new file mode 100644 index 0000000..3236eb1 --- /dev/null +++ b/src/factory.h @@ -0,0 +1,13 @@ +#pragma once +#include +#include "world.h" + +using namespace Blah; + +namespace TL +{ + namespace Factory + { + Entity* player(World* world, Point position); + } +} \ No newline at end of file diff --git a/src/game.cpp b/src/game.cpp index d375bb7..5cef3d1 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -1,9 +1,8 @@ #include "game.h" #include "content.h" #include "masks.h" -#include "components/animator.h" #include "components/collider.h" -#include "components/mover.h" +#include "factory.h" using namespace TL; @@ -18,21 +17,21 @@ void Game::startup() // set batcher to use Nearest Filter batch.default_sampler = TextureSampler(TextureFilter::Nearest); - // add a test entity - auto en = world.add_entity(Point(100, 60)); - auto an = en->add(Animator("player")); - auto col = en->add(Collider::make_rect(RectI(-4, -8, 8, 8))); - auto mover = en->add(Mover()); - - mover->collider = col; - mover->speed = Vec2(5, 20); - an->play("idle"); - - auto floor = world.add_entity(Point(50, 100)); - auto c2 = floor->add(Collider::make_rect(RectI(0, 0, 100, 16))); - c2->mask = Mask::solid; - m_draw_colliders = true; + + load_map(); +} + +void Game::load_map() +{ + world.clear(); + + // add a test player + Factory::player(&world, Point(50, 50)); + + auto floor = world.add_entity(Point(0, 100)); + auto c2 = floor->add(Collider::make_rect(RectI(0, 0, 320, 16))); + c2->mask = Mask::solid; } void Game::shutdown() @@ -44,6 +43,8 @@ void Game::update() { if (Input::pressed(Key::F1)) m_draw_colliders = !m_draw_colliders; + if (Input::pressed(Key::F2)) + load_map(); world.update(); } diff --git a/src/game.h b/src/game.h index 326e91e..58c4269 100644 --- a/src/game.h +++ b/src/game.h @@ -13,6 +13,7 @@ namespace TL FrameBufferRef buffer; Batch batch; + void load_map(); void startup(); void shutdown(); void update(); diff --git a/src/world.cpp b/src/world.cpp index e39e487..f6b4854 100644 --- a/src/world.cpp +++ b/src/world.cpp @@ -219,6 +219,17 @@ void World::destroy(Component* component) } } +void World::clear() +{ + Entity* entity = first_entity(); + while (entity) + { + auto next = entity->next(); + destroy_entity(entity); + entity = next; + } +} + void World::update() { for (int i = 0; i < Component::Types::count(); i++) diff --git a/src/world.h b/src/world.h index caa71d3..2252a1e 100644 --- a/src/world.h +++ b/src/world.h @@ -143,6 +143,7 @@ namespace TL const T* last() const; void destroy(Component* component); + void clear(); void update(); @@ -170,14 +171,14 @@ namespace TL T* Component::get() { BLAH_ASSERT(m_entity, "Component must be assigned to an Entity"); - return entity->get(); + return m_entity->get(); } template const T* Component::get() const { BLAH_ASSERT(m_entity, "Component must be assigned to an Entity"); - return entity->get(); + return m_entity->get(); } template