From e4e2f2d2a7b6a282b9618aa0004d9453936f43c6 Mon Sep 17 00:00:00 2001 From: Kelly Rauchenberger Date: Sun, 18 Feb 2018 15:25:52 -0500 Subject: Added player death and event scheduling Also added ability to make sprites flicker, to freeze physics for an entity, and to freeze progression of a sprite's animation loop. --- src/components/animatable.h | 33 +++++++++++++++++ src/components/playable.h | 9 +++++ src/components/ponderable.h | 22 ++++++++++++ src/components/schedulable.h | 21 +++++++++++ src/game.cpp | 2 ++ src/systems/animating.cpp | 19 ++++++++-- src/systems/controlling.cpp | 29 +++++++++++++++ src/systems/controlling.h | 5 +++ src/systems/mapping.cpp | 21 +++++++++++ src/systems/orienting.cpp | 18 ++++------ src/systems/playing.cpp | 85 +++++++++++++++++++++++++++++++++++++++++--- src/systems/playing.h | 9 ++++- src/systems/pondering.cpp | 16 +++++++++ src/systems/scheduling.cpp | 54 ++++++++++++++++++++++++++++ src/systems/scheduling.h | 22 ++++++++++++ 15 files changed, 346 insertions(+), 19 deletions(-) create mode 100644 src/components/schedulable.h create mode 100644 src/systems/scheduling.cpp create mode 100644 src/systems/scheduling.h (limited to 'src') diff --git a/src/components/animatable.h b/src/components/animatable.h index ed0133e..ec72be0 100644 --- a/src/components/animatable.h +++ b/src/components/animatable.h @@ -51,12 +51,45 @@ public: animation_ = std::move(animation); } + inline bool isFlickering() const + { + return flickering_; + } + + inline void setFlickering(bool v) + { + flickering_ = v; + } + + inline size_t getFlickerTimer() const + { + return flickerTimer_; + } + + inline void setFlickerTimer(size_t v) + { + flickerTimer_ = v; + } + + inline bool isFrozen() const + { + return frozen_; + } + + inline void setFrozen(bool v) + { + frozen_ = v; + } + private: AnimationSet animationSet_; std::string animation_; size_t frame_ = 0; size_t countdown_ = 0; + bool flickering_ = false; + size_t flickerTimer_ = 0; + bool frozen_ = false; }; #endif /* end of include guard: SPRITE_RENDERABLE_H_D3AACBBF */ diff --git a/src/components/playable.h b/src/components/playable.h index a6e71b0..86a7ee7 100644 --- a/src/components/playable.h +++ b/src/components/playable.h @@ -2,14 +2,23 @@ #define PLAYABLE_H_DDC566C3 #include "component.h" +#include class PlayableComponent : public Component { public: + using MapChangeCallback = std::function; + bool changingMap = false; int newMapId = -1; double newMapX = 0; double newMapY = 0; + MapChangeCallback newMapCallback; + + int checkpointMapId = -1; + double checkpointX = 0; + double checkpointY = 0; + }; #endif /* end of include guard: PLAYABLE_H_DDC566C3 */ diff --git a/src/components/ponderable.h b/src/components/ponderable.h index e21cbab..78af25f 100644 --- a/src/components/ponderable.h +++ b/src/components/ponderable.h @@ -70,6 +70,26 @@ public: grounded_ = v; } + inline bool isFrozen() const + { + return frozen_; + } + + inline void setFrozen(bool v) + { + frozen_ = v; + } + + inline bool isCollidable() const + { + return collidable_; + } + + inline void setCollidable(bool v) + { + collidable_ = v; + } + private: double velX_ = 0.0; @@ -78,6 +98,8 @@ private: double accelY_ = 0.0; Type type_ = Type::vacuumed; bool grounded_ = false; + bool frozen_ = false; + bool collidable_ = true; }; #endif /* end of include guard: TANGIBLE_H_746DB3EE */ diff --git a/src/components/schedulable.h b/src/components/schedulable.h new file mode 100644 index 0000000..a92bbba --- /dev/null +++ b/src/components/schedulable.h @@ -0,0 +1,21 @@ +#ifndef SCHEDULABLE_H_1DA3FA2A +#define SCHEDULABLE_H_1DA3FA2A + +#include "component.h" +#include +#include +#include +#include "entity_manager.h" + +class SchedulableComponent : public Component { +public: + + using id_type = EntityManager::id_type; + + using Callback = std::function; + using Action = std::tuple; + + std::list actions; +}; + +#endif /* end of include guard: SCHEDULABLE_H_1DA3FA2A */ diff --git a/src/game.cpp b/src/game.cpp index f245e7c..3da23a3 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -10,6 +10,7 @@ #include "systems/mapping.h" #include "systems/orienting.h" #include "systems/playing.h" +#include "systems/scheduling.h" #include "animation.h" #include "consts.h" @@ -30,6 +31,7 @@ void key_callback(GLFWwindow* window, int key, int, int action, int) Game::Game() : world_("res/maps.xml") { systemManager_.emplaceSystem(*this); + systemManager_.emplaceSystem(*this); systemManager_.emplaceSystem(*this); systemManager_.emplaceSystem(*this); systemManager_.emplaceSystem(*this); diff --git a/src/systems/animating.cpp b/src/systems/animating.cpp index 22224c9..634af67 100644 --- a/src/systems/animating.cpp +++ b/src/systems/animating.cpp @@ -13,7 +13,10 @@ void AnimatingSystem::tick(double) auto& sprite = game_.getEntityManager(). getComponent(entity); - sprite.setCountdown(sprite.getCountdown() + 1); + if (!sprite.isFrozen()) + { + sprite.setCountdown(sprite.getCountdown() + 1); + } const Animation& anim = sprite.getAnimation(); if (sprite.getCountdown() >= anim.getDelay()) @@ -26,6 +29,11 @@ void AnimatingSystem::tick(double) sprite.setFrame(anim.getFirstFrame()); } } + + if (sprite.isFlickering()) + { + sprite.setFlickerTimer((sprite.getFlickerTimer() + 1) % 6); + } } } @@ -44,6 +52,12 @@ void AnimatingSystem::render(Texture& texture) auto& transform = game_.getEntityManager(). getComponent(entity); + double alpha = 1.0; + if (sprite.isFlickering() && (sprite.getFlickerTimer() < 3)) + { + alpha = 0.0; + } + Rectangle dstrect { static_cast(transform.getX()), static_cast(transform.getY()), @@ -55,7 +69,8 @@ void AnimatingSystem::render(Texture& texture) aset.getTexture(), texture, aset.getFrameRect(sprite.getFrame()), - dstrect); + dstrect, + alpha); } } diff --git a/src/systems/controlling.cpp b/src/systems/controlling.cpp index e1609bd..e65c09a 100644 --- a/src/systems/controlling.cpp +++ b/src/systems/controlling.cpp @@ -105,3 +105,32 @@ void ControllingSystem::input(int key, int action) { actions_.push(std::make_pair(key, action)); } + +void ControllingSystem::freeze(id_type entity) +{ + auto& controllable = game_.getEntityManager(). + getComponent(entity); + + controllable.setFrozen(true); +} + +void ControllingSystem::unfreeze(id_type entity) +{ + auto& controllable = game_.getEntityManager(). + getComponent(entity); + + if (controllable.isFrozen()) + { + controllable.setFrozen(false); + + auto& orienting = game_.getSystemManager().getSystem(); + + if (controllable.isHoldingLeft()) + { + orienting.moveLeft(entity); + } else if (controllable.isHoldingRight()) + { + orienting.moveRight(entity); + } + } +} diff --git a/src/systems/controlling.h b/src/systems/controlling.h index 01ed7a0..d6f0789 100644 --- a/src/systems/controlling.h +++ b/src/systems/controlling.h @@ -12,8 +12,13 @@ public: } void tick(double dt); + void input(int key, int action); + void freeze(id_type entity); + + void unfreeze(id_type entity); + private: std::queue> actions_; diff --git a/src/systems/mapping.cpp b/src/systems/mapping.cpp index 05167c1..a3a17ec 100644 --- a/src/systems/mapping.cpp +++ b/src/systems/mapping.cpp @@ -166,12 +166,33 @@ void MappingSystem::loadMap(size_t mapId) MappableComponent::Boundary::Type::wall); } else if (tile == 42) { + addBoundary( + mappable.getRightBoundaries(), + x * TILE_WIDTH, + y * TILE_HEIGHT, + (y+1) * TILE_HEIGHT, + MappableComponent::Boundary::Type::danger); + + addBoundary( + mappable.getLeftBoundaries(), + (x+1) * TILE_WIDTH, + y * TILE_HEIGHT, + (y+1) * TILE_HEIGHT, + MappableComponent::Boundary::Type::danger); + addBoundary( mappable.getDownBoundaries(), y * TILE_HEIGHT, x * TILE_WIDTH, (x+1) * TILE_WIDTH, MappableComponent::Boundary::Type::danger); + + addBoundary( + mappable.getUpBoundaries(), + (y+1) * TILE_HEIGHT, + x * TILE_WIDTH, + (x+1) * TILE_WIDTH, + MappableComponent::Boundary::Type::danger); } } } diff --git a/src/systems/orienting.cpp b/src/systems/orienting.cpp index 187bebc..2df8f87 100644 --- a/src/systems/orienting.cpp +++ b/src/systems/orienting.cpp @@ -93,24 +93,18 @@ void OrientingSystem::moveRight(id_type entity) void OrientingSystem::stopWalking(id_type entity) { - auto& ponderable = game_.getEntityManager(). - getComponent(entity); - auto& orientable = game_.getEntityManager(). getComponent(entity); orientable.setWalkState(OrientableComponent::WalkState::still); - if (ponderable.isGrounded()) - { - auto& animating = game_.getSystemManager().getSystem(); + auto& animating = game_.getSystemManager().getSystem(); - if (orientable.isFacingRight()) - { - animating.startAnimation(entity, "stillRight"); - } else { - animating.startAnimation(entity, "stillLeft"); - } + if (orientable.isFacingRight()) + { + animating.startAnimation(entity, "stillRight"); + } else { + animating.startAnimation(entity, "stillLeft"); } } diff --git a/src/systems/playing.cpp b/src/systems/playing.cpp index 2c6a419..40d9706 100644 --- a/src/systems/playing.cpp +++ b/src/systems/playing.cpp @@ -7,13 +7,18 @@ #include "components/orientable.h" #include "systems/mapping.h" #include "systems/pondering.h" +#include "systems/orienting.h" +#include "systems/scheduling.h" +#include "systems/controlling.h" #include "animation.h" +#include "muxer.h" void PlayingSystem::tick(double) { // Check if we need to change the map auto players = game_.getEntityManager().getEntitiesWithComponents< - PlayableComponent>(); + PlayableComponent, + TransformableComponent>(); for (id_type player : players) { @@ -44,6 +49,12 @@ void PlayingSystem::tick(double) playable.changingMap = false; + if (playable.newMapCallback) + { + playable.newMapCallback(); + playable.newMapCallback = nullptr; + } + break; } } @@ -66,7 +77,10 @@ void PlayingSystem::initPlayer() game_.getEntityManager().emplaceComponent( player, - 203, 44, 10, 12); + game_.getWorld().getStartingX(), + game_.getWorld().getStartingY(), + 10, + 12); game_.getSystemManager().getSystem().initializeBody( player, @@ -74,13 +88,20 @@ void PlayingSystem::initPlayer() game_.getEntityManager().emplaceComponent(player); game_.getEntityManager().emplaceComponent(player); - game_.getEntityManager().emplaceComponent(player); + + auto& playable = game_.getEntityManager(). + emplaceComponent(player); + + playable.checkpointMapId = game_.getWorld().getStartingMapId(); + playable.checkpointX = game_.getWorld().getStartingX(); + playable.checkpointY = game_.getWorld().getStartingY(); } void PlayingSystem::changeMap( size_t mapId, double x, - double y) + double y, + PlayableComponent::MapChangeCallback callback) { auto players = game_.getEntityManager().getEntitiesWithComponents< PlayableComponent>(); @@ -94,5 +115,61 @@ void PlayingSystem::changeMap( playable.newMapId = mapId; playable.newMapX = x; playable.newMapY = y; + playable.newMapCallback = std::move(callback); + } +} + +void PlayingSystem::die() +{ + playSound("res/Hit_Hurt5.wav", 0.25); + + auto players = game_.getEntityManager().getEntitiesWithComponents< + OrientableComponent, + ControllableComponent, + AnimatableComponent, + PonderableComponent, + PlayableComponent>(); + + for (id_type player : players) + { + auto& animatable = game_.getEntityManager(). + getComponent(player); + + auto& ponderable = game_.getEntityManager(). + getComponent(player); + + auto& controlling = game_.getSystemManager().getSystem(); + controlling.freeze(player); + + animatable.setFrozen(true); + animatable.setFlickering(true); + ponderable.setFrozen(true); + ponderable.setCollidable(false); + + auto& scheduling = game_.getSystemManager().getSystem(); + + scheduling.schedule(player, 0.75, [&] (id_type player) { + auto& playable = game_.getEntityManager(). + getComponent(player); + + changeMap( + playable.checkpointMapId, + playable.checkpointX, + playable.checkpointY, + [&, player] () { + animatable.setFrozen(false); + animatable.setFlickering(false); + ponderable.setFrozen(false); + ponderable.setCollidable(true); + + // Reset the walk state, and then potentially let the + // ControllingSystem set it again. + auto& orienting = game_.getSystemManager(). + getSystem(); + orienting.stopWalking(player); + + controlling.unfreeze(player); + }); + }); } } diff --git a/src/systems/playing.h b/src/systems/playing.h index c98a464..ff16808 100644 --- a/src/systems/playing.h +++ b/src/systems/playing.h @@ -2,6 +2,7 @@ #define PLAYING_H_70A54F7D #include "system.h" +#include "components/playable.h" class PlayingSystem : public System { public: @@ -14,7 +15,13 @@ public: void initPlayer(); - void changeMap(size_t mapId, double x, double y); + void changeMap( + size_t mapId, + double x, + double y, + PlayableComponent::MapChangeCallback callback = nullptr); + + void die(); }; diff --git a/src/systems/pondering.cpp b/src/systems/pondering.cpp index 2490dc9..d3601ac 100644 --- a/src/systems/pondering.cpp +++ b/src/systems/pondering.cpp @@ -27,6 +27,11 @@ void PonderingSystem::tick(double dt) auto& ponderable = game_.getEntityManager(). getComponent(entity); + if (ponderable.isFrozen()) + { + continue; + } + // Accelerate ponderable.setVelocityX( ponderable.getVelocityX() + ponderable.getAccelX() * dt); @@ -289,6 +294,17 @@ void PonderingSystem::tick(double dt) break; } } + + break; + } + + case Collision::Type::danger: + { + game_.getSystemManager().getSystem().die(); + + stopProcessing = true; + + break; } default: diff --git a/src/systems/scheduling.cpp b/src/systems/scheduling.cpp new file mode 100644 index 0000000..220efae --- /dev/null +++ b/src/systems/scheduling.cpp @@ -0,0 +1,54 @@ +#include "scheduling.h" +#include "game.h" +#include "components/schedulable.h" +#include "util.h" + +void SchedulingSystem::tick(double dt) +{ + auto entities = game_.getEntityManager().getEntitiesWithComponents< + SchedulableComponent>(); + + for (id_type entity : entities) + { + auto& schedulable = game_.getEntityManager(). + getComponent(entity); + + for (auto& action : schedulable.actions) + { + std::get<0>(action) -= dt; + + if (std::get<0>(action) < 0) + { + std::get<1>(action)(entity); + } + } + + erase_if(schedulable.actions, + [] (const SchedulableComponent::Action& action) { + return (std::get<0>(action) < 0); + }); + + if (schedulable.actions.empty()) + { + game_.getEntityManager().removeComponent(entity); + } + } +} + +void SchedulingSystem::schedule( + id_type entity, + double length, + std::function action) +{ + if (!game_.getEntityManager().hasComponent(entity)) + { + game_.getEntityManager().emplaceComponent(entity); + } + + auto& schedulable = game_.getEntityManager(). + getComponent(entity); + + schedulable.actions.emplace_back( + length, + std::move(action)); +} diff --git a/src/systems/scheduling.h b/src/systems/scheduling.h new file mode 100644 index 0000000..7950d62 --- /dev/null +++ b/src/systems/scheduling.h @@ -0,0 +1,22 @@ +#ifndef SCHEDULING_H_7B02E3E3 +#define SCHEDULING_H_7B02E3E3 + +#include "system.h" + +class SchedulingSystem : public System { +public: + + SchedulingSystem(Game& game) : System(game) + { + } + + void tick(double dt); + + void schedule( + id_type entity, + double length, + std::function action); + +}; + +#endif /* end of include guard: SCHEDULING_H_7B02E3E3 */ -- cgit 1.4.1