From d9c201cbf2fbfe315137e141d886a9bbfa6794ba Mon Sep 17 00:00:00 2001 From: Kelly Rauchenberger Date: Wed, 20 Feb 2019 16:44:09 -0500 Subject: Started implementing schedule Scheduled entities move downward every beat, although they have a speed that is twice the bpm, so essentially they move every other beat? Broke the simulation loop such that different parts run independently -- made it horizontal rather than vertical. Encapsulated the grid cache so that more than one position field could be cached. This is used to make sure that an entity can't move into a space that something else is already moving into. Fixed issue where an entity could move perpendicularly into the space an entity was moving out of. --- src/entity.h | 3 ++ src/grid_cache.h | 59 ++++++++++++++++++++++++ src/level.h | 2 + src/main.cpp | 27 ----------- src/schedule.h | 44 ++++++++++++++++++ src/simulation.cpp | 128 +++++++++++++++++++++++++++++++++++++++++------------ src/simulation.h | 13 +++--- 7 files changed, 213 insertions(+), 63 deletions(-) create mode 100644 src/grid_cache.h create mode 100644 src/schedule.h (limited to 'src') diff --git a/src/entity.h b/src/entity.h index b606b43..a69c612 100644 --- a/src/entity.h +++ b/src/entity.h @@ -21,6 +21,7 @@ public: vec2s destPos; double movementTween = 0.0; double speed = 0.0; // Tiles per second + Direction moveDir = Direction::none; // Player bool controllable = false; @@ -32,6 +33,8 @@ public: // Temp int colorVal = 25; + bool scheduled = false; + }; #endif /* end of include guard: ENTITY_H_0D6CB29A */ diff --git a/src/grid_cache.h b/src/grid_cache.h new file mode 100644 index 0000000..e837f55 --- /dev/null +++ b/src/grid_cache.h @@ -0,0 +1,59 @@ +#ifndef GRID_CACHE_H_67BBE74D +#define GRID_CACHE_H_67BBE74D + +#include +#include +#include "level.h" + +template +class GridCache { +public: + + explicit GridCache(const Level& level) : width_(level.getSize().w()) + { + } + + void set(T value, vec2s pos) + { + if (reverse_.count(value)) + { + size_t oldPosIndex = reverse_.at(value); + lookup_[oldPosIndex].erase(value); + } + + size_t newPosIndex = getIndex(pos); + lookup_[newPosIndex].insert(value); + reverse_[value] = newPosIndex; + } + + void remove(T value) + { + if (reverse_.count(value)) + { + size_t index = reverse_.at(value); + lookup_[index].erase(value); + reverse_.erase(value); + } + } + + const std::unordered_set& at(vec2s pos) const + { + size_t index = getIndex(pos); + + return lookup_[index]; + } + +private: + + inline size_t getIndex(const vec2s& pos) const + { + return pos.x() + pos.y() * width_; + } + + size_t width_; + + mutable std::unordered_map> lookup_; + std::unordered_map reverse_; +}; + +#endif /* end of include guard: GRID_CACHE_H_67BBE74D */ diff --git a/src/level.h b/src/level.h index 6224c15..1ca4970 100644 --- a/src/level.h +++ b/src/level.h @@ -1,6 +1,8 @@ #ifndef LEVEL_H_678CFCCF #define LEVEL_H_678CFCCF +#include +#include "vector.h" #include "consts.h" #include "tileset.h" diff --git a/src/main.cpp b/src/main.cpp index c77d25b..c0ba15f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -13,33 +13,6 @@ int main(int, char**) Level level; Simulation sim(level); - Simulation::id_type player = sim.emplaceEntity(); - Entity& entity = sim.getEntity(player); - entity.size = TILE_SIZE; - entity.speed = 3.0; - entity.controllable = true; - entity.colliderType = ColliderType::player; - entity.colorVal = 180; - sim.setGridPos(player, vec2s { 1, 5 } ); - - Simulation::id_type crateId = sim.emplaceEntity(); - Entity& crate = sim.getEntity(crateId); - crate.size = TILE_SIZE; - crate.speed = 4.0; - crate.colliderType = ColliderType::crate; - crate.canBePushedBy.insert(ColliderType::player); - crate.canBePushedBy.insert(ColliderType::crate); - sim.setGridPos(crateId, vec2s { 4, 5 } ); - - Simulation::id_type crateId2 = sim.emplaceEntity(); - Entity& crate2 = sim.getEntity(crateId2); - crate2.size = TILE_SIZE; - crate2.speed = 4.0; - crate2.colliderType = ColliderType::crate; - crate2.canBePushedBy.insert(ColliderType::player); - crate2.canBePushedBy.insert(ColliderType::crate); - sim.setGridPos(crateId2, vec2s { 6, 7 } ); - bool quit = false; SDL_Event e; diff --git a/src/schedule.h b/src/schedule.h new file mode 100644 index 0000000..5d77761 --- /dev/null +++ b/src/schedule.h @@ -0,0 +1,44 @@ +#ifndef SCHEDULE_H_EF7B9D12 +#define SCHEDULE_H_EF7B9D12 + +class Schedule { +public: + + explicit Schedule( + size_t bpm) : + bpm_(bpm), + tick_(60.0 / static_cast(bpm_)) + { + } + + size_t getBPM() const + { + return bpm_; + } + + void accumulate(double dt) + { + accum_ += dt; + } + + bool step() + { + if (accum_ > tick_) + { + accum_ -= tick_; + + return true; + } else { + return false; + } + } + +private: + + size_t bpm_; + double tick_; + double accum_ = 0.0; + +}; + +#endif /* end of include guard: SCHEDULE_H_EF7B9D12 */ diff --git a/src/simulation.cpp b/src/simulation.cpp index 912f7f0..1379c34 100644 --- a/src/simulation.cpp +++ b/src/simulation.cpp @@ -3,15 +3,68 @@ #include "consts.h" #include "level.h" +Simulation::Simulation( + const Level& level) : + level_(level) +{ + id_type player = emplaceEntity(); + Entity& entity = getEntity(player); + entity.size = TILE_SIZE; + entity.speed = 3.0; + entity.controllable = true; + entity.colliderType = ColliderType::player; + entity.colorVal = 180; + entity.gridPos = vec2s { 1, 5 }; + + id_type crateId = emplaceEntity(); + Entity& crate = getEntity(crateId); + crate.size = TILE_SIZE; + crate.speed = static_cast(schedule_.getBPM()) / 30.0; + crate.colliderType = ColliderType::crate; + crate.canBePushedBy.insert(ColliderType::player); + crate.canBePushedBy.insert(ColliderType::crate); + crate.canBePushedBy.insert(ColliderType::train); + crate.gridPos = vec2s { 4, 5 }; + + id_type crateId2 = emplaceEntity(); + Entity& crate2 = getEntity(crateId2); + crate2.size = TILE_SIZE; + crate2.speed = static_cast(schedule_.getBPM()) / 30.0; + crate2.colliderType = ColliderType::crate; + crate2.canBePushedBy.insert(ColliderType::player); + crate2.canBePushedBy.insert(ColliderType::crate); + crate2.canBePushedBy.insert(ColliderType::train); + crate2.gridPos = vec2s { 6, 7 }; + + id_type trainId = emplaceEntity(); + Entity& train = getEntity(trainId); + train.size = TILE_SIZE; + train.speed = static_cast(schedule_.getBPM()) / 30.0; + train.colliderType = ColliderType::train; + train.scheduled = true; + train.colorVal = 90; + train.gridPos = vec2s { 6, 1 }; + + + + + for (id_type id : active_) + { + Entity& entity = entities_.at(id); + + posCache_.set(id, entity.gridPos); + } +} + void Simulation::tick( double dt, const Uint8* keystate) { + // Control for (id_type id : active_) { Entity& entity = entities_.at(id); - // Control if (entity.controllable && !entity.moving) { @@ -38,7 +91,7 @@ void Simulation::tick( vec2s lookPos = posInDir(entity.gridPos, lookDir); - for (id_type blockId : getGridEntities(lookPos)) + for (id_type blockId : posCache_.at(lookPos)) { Entity& block = entities_.at(blockId); @@ -79,16 +132,40 @@ void Simulation::tick( } } } + } + + // Schedule + schedule_.accumulate(dt); + + if (schedule_.step()) + { + for (id_type id : active_) + { + Entity& entity = entities_.at(id); + + if (entity.scheduled && !entity.moving) + { + moveEntityOnGrid(id, Direction::down); + } + } + } + - // Collision + // Collision - // Movement + + + // Movement + for (id_type id : active_) + { + Entity& entity = entities_.at(id); + if (entity.moving) { entity.movementTween += entity.speed * dt; @@ -96,7 +173,9 @@ void Simulation::tick( if (entity.movementTween >= 1.0) { entity.moving = false; - setGridPos(id, entity.destPos); + entity.gridPos = entity.destPos; + posCache_.set(id, entity.gridPos); + moveToCache_.remove(id); } } @@ -141,29 +220,6 @@ void Simulation::deleteEntity(id_type id) active_.erase(id); } -void Simulation::setGridPos(id_type id, vec2s pos) -{ - Entity& entity = entities_.at(id); - - size_t oldPosIndex = - entity.gridPos.x() + entity.gridPos.y() * level_.getSize().w(); - gridCache_[oldPosIndex].erase(id); - - entity.gridPos = pos; - - size_t newPosIndex = - entity.gridPos.x() + entity.gridPos.y() * level_.getSize().w(); - gridCache_[newPosIndex].insert(id); -} - -const std::unordered_set& - Simulation::getGridEntities(vec2s pos) const -{ - size_t posIndex = pos.x() + pos.y() * level_.getSize().w(); - - return gridCache_[posIndex]; -} - bool Simulation::moveEntityOnGrid( id_type id, Direction moveDir, @@ -225,7 +281,13 @@ bool Simulation::moveEntityOnGrid( return false; } - for (id_type blockId : getGridEntities(shouldMoveTo)) + // Can't move into a space that something else is already moving into. + if (!moveToCache_.at(shouldMoveTo).empty()) + { + return false; + } + + for (id_type blockId : posCache_.at(shouldMoveTo)) { Entity& block = entities_.at(blockId); @@ -240,6 +302,11 @@ bool Simulation::moveEntityOnGrid( { return false; } + } else if (block.moveDir != moveDir) + { + // Can't move perpendicularly into a space that something else is moving + // out of. + return false; } double entityTimeLeft = 1.0 / entity.speed; @@ -260,6 +327,9 @@ bool Simulation::moveEntityOnGrid( entity.moving = true; entity.destPos = shouldMoveTo; entity.movementTween = 0.0; + entity.moveDir = moveDir; + + moveToCache_.set(id, entity.destPos); } return true; diff --git a/src/simulation.h b/src/simulation.h index 4d41b49..f86d513 100644 --- a/src/simulation.h +++ b/src/simulation.h @@ -3,11 +3,11 @@ #include "entity.h" #include "renderer.h" +#include "schedule.h" +#include "grid_cache.h" #include #include #include -#include -#include class Level; @@ -17,7 +17,7 @@ public: using id_type = std::vector::size_type; // Constructor - explicit Simulation(const Level& level) : level_(level) {} + explicit Simulation(const Level& level); void tick( double dt, @@ -47,15 +47,12 @@ public: return level_; } - void setGridPos(id_type id, vec2s pos); - static vec2s posInDir(vec2s orig, Direction dir); private: - const std::unordered_set& getGridEntities(vec2s pos) const; bool moveEntityOnGrid( id_type id, @@ -63,12 +60,14 @@ private: bool validate = false); const Level& level_; + Schedule schedule_ { 120 }; std::vector entities_; std::deque available_; std::set active_; - mutable std::unordered_map> gridCache_; + mutable GridCache posCache_ { level_ }; + mutable GridCache moveToCache_ { level_ }; }; #endif /* end of include guard: SIMULATION_H_7BF6EEA4 */ -- cgit 1.4.1