summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
authorKelly Rauchenberger <fefferburbia@gmail.com>2019-02-20 16:44:09 -0500
committerKelly Rauchenberger <fefferburbia@gmail.com>2019-02-20 16:44:09 -0500
commitd9c201cbf2fbfe315137e141d886a9bbfa6794ba (patch)
tree2dfaf8db9e43e456386796d797884ea18d63befe /src
parent8996810b1356c2224d4f34423fd4211de20da238 (diff)
downloaddispatcher-d9c201cbf2fbfe315137e141d886a9bbfa6794ba.tar.gz
dispatcher-d9c201cbf2fbfe315137e141d886a9bbfa6794ba.tar.bz2
dispatcher-d9c201cbf2fbfe315137e141d886a9bbfa6794ba.zip
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.
Diffstat (limited to 'src')
-rw-r--r--src/entity.h3
-rw-r--r--src/grid_cache.h59
-rw-r--r--src/level.h2
-rw-r--r--src/main.cpp27
-rw-r--r--src/schedule.h44
-rw-r--r--src/simulation.cpp128
-rw-r--r--src/simulation.h13
7 files changed, 213 insertions, 63 deletions
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:
21 vec2s destPos; 21 vec2s destPos;
22 double movementTween = 0.0; 22 double movementTween = 0.0;
23 double speed = 0.0; // Tiles per second 23 double speed = 0.0; // Tiles per second
24 Direction moveDir = Direction::none;
24 25
25 // Player 26 // Player
26 bool controllable = false; 27 bool controllable = false;
@@ -32,6 +33,8 @@ public:
32 // Temp 33 // Temp
33 int colorVal = 25; 34 int colorVal = 25;
34 35
36 bool scheduled = false;
37
35}; 38};
36 39
37#endif /* end of include guard: ENTITY_H_0D6CB29A */ 40#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 @@
1#ifndef GRID_CACHE_H_67BBE74D
2#define GRID_CACHE_H_67BBE74D
3
4#include <unordered_map>
5#include <unordered_set>
6#include "level.h"
7
8template <typename T>
9class GridCache {
10public:
11
12 explicit GridCache(const Level& level) : width_(level.getSize().w())
13 {
14 }
15
16 void set(T value, vec2s pos)
17 {
18 if (reverse_.count(value))
19 {
20 size_t oldPosIndex = reverse_.at(value);
21 lookup_[oldPosIndex].erase(value);
22 }
23
24 size_t newPosIndex = getIndex(pos);
25 lookup_[newPosIndex].insert(value);
26 reverse_[value] = newPosIndex;
27 }
28
29 void remove(T value)
30 {
31 if (reverse_.count(value))
32 {
33 size_t index = reverse_.at(value);
34 lookup_[index].erase(value);
35 reverse_.erase(value);
36 }
37 }
38
39 const std::unordered_set<T>& at(vec2s pos) const
40 {
41 size_t index = getIndex(pos);
42
43 return lookup_[index];
44 }
45
46private:
47
48 inline size_t getIndex(const vec2s& pos) const
49 {
50 return pos.x() + pos.y() * width_;
51 }
52
53 size_t width_;
54
55 mutable std::unordered_map<size_t, std::unordered_set<T>> lookup_;
56 std::unordered_map<T, size_t> reverse_;
57};
58
59#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 @@
1#ifndef LEVEL_H_678CFCCF 1#ifndef LEVEL_H_678CFCCF
2#define LEVEL_H_678CFCCF 2#define LEVEL_H_678CFCCF
3 3
4#include <vector>
5#include "vector.h"
4#include "consts.h" 6#include "consts.h"
5#include "tileset.h" 7#include "tileset.h"
6 8
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**)
13 Level level; 13 Level level;
14 Simulation sim(level); 14 Simulation sim(level);
15 15
16 Simulation::id_type player = sim.emplaceEntity();
17 Entity& entity = sim.getEntity(player);
18 entity.size = TILE_SIZE;
19 entity.speed = 3.0;
20 entity.controllable = true;
21 entity.colliderType = ColliderType::player;
22 entity.colorVal = 180;
23 sim.setGridPos(player, vec2s { 1, 5 } );
24
25 Simulation::id_type crateId = sim.emplaceEntity();
26 Entity& crate = sim.getEntity(crateId);
27 crate.size = TILE_SIZE;
28 crate.speed = 4.0;
29 crate.colliderType = ColliderType::crate;
30 crate.canBePushedBy.insert(ColliderType::player);
31 crate.canBePushedBy.insert(ColliderType::crate);
32 sim.setGridPos(crateId, vec2s { 4, 5 } );
33
34 Simulation::id_type crateId2 = sim.emplaceEntity();
35 Entity& crate2 = sim.getEntity(crateId2);
36 crate2.size = TILE_SIZE;
37 crate2.speed = 4.0;
38 crate2.colliderType = ColliderType::crate;
39 crate2.canBePushedBy.insert(ColliderType::player);
40 crate2.canBePushedBy.insert(ColliderType::crate);
41 sim.setGridPos(crateId2, vec2s { 6, 7 } );
42
43 bool quit = false; 16 bool quit = false;
44 17
45 SDL_Event e; 18 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 @@
1#ifndef SCHEDULE_H_EF7B9D12
2#define SCHEDULE_H_EF7B9D12
3
4class Schedule {
5public:
6
7 explicit Schedule(
8 size_t bpm) :
9 bpm_(bpm),
10 tick_(60.0 / static_cast<double>(bpm_))
11 {
12 }
13
14 size_t getBPM() const
15 {
16 return bpm_;
17 }
18
19 void accumulate(double dt)
20 {
21 accum_ += dt;
22 }
23
24 bool step()
25 {
26 if (accum_ > tick_)
27 {
28 accum_ -= tick_;
29
30 return true;
31 } else {
32 return false;
33 }
34 }
35
36private:
37
38 size_t bpm_;
39 double tick_;
40 double accum_ = 0.0;
41
42};
43
44#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 @@
3#include "consts.h" 3#include "consts.h"
4#include "level.h" 4#include "level.h"
5 5
6Simulation::Simulation(
7 const Level& level) :
8 level_(level)
9{
10 id_type player = emplaceEntity();
11 Entity& entity = getEntity(player);
12 entity.size = TILE_SIZE;
13 entity.speed = 3.0;
14 entity.controllable = true;
15 entity.colliderType = ColliderType::player;
16 entity.colorVal = 180;
17 entity.gridPos = vec2s { 1, 5 };
18
19 id_type crateId = emplaceEntity();
20 Entity& crate = getEntity(crateId);
21 crate.size = TILE_SIZE;
22 crate.speed = static_cast<double>(schedule_.getBPM()) / 30.0;
23 crate.colliderType = ColliderType::crate;
24 crate.canBePushedBy.insert(ColliderType::player);
25 crate.canBePushedBy.insert(ColliderType::crate);
26 crate.canBePushedBy.insert(ColliderType::train);
27 crate.gridPos = vec2s { 4, 5 };
28
29 id_type crateId2 = emplaceEntity();
30 Entity& crate2 = getEntity(crateId2);
31 crate2.size = TILE_SIZE;
32 crate2.speed = static_cast<double>(schedule_.getBPM()) / 30.0;
33 crate2.colliderType = ColliderType::crate;
34 crate2.canBePushedBy.insert(ColliderType::player);
35 crate2.canBePushedBy.insert(ColliderType::crate);
36 crate2.canBePushedBy.insert(ColliderType::train);
37 crate2.gridPos = vec2s { 6, 7 };
38
39 id_type trainId = emplaceEntity();
40 Entity& train = getEntity(trainId);
41 train.size = TILE_SIZE;
42 train.speed = static_cast<double>(schedule_.getBPM()) / 30.0;
43 train.colliderType = ColliderType::train;
44 train.scheduled = true;
45 train.colorVal = 90;
46 train.gridPos = vec2s { 6, 1 };
47
48
49
50
51 for (id_type id : active_)
52 {
53 Entity& entity = entities_.at(id);
54
55 posCache_.set(id, entity.gridPos);
56 }
57}
58
6void Simulation::tick( 59void Simulation::tick(
7 double dt, 60 double dt,
8 const Uint8* keystate) 61 const Uint8* keystate)
9{ 62{
63 // Control
10 for (id_type id : active_) 64 for (id_type id : active_)
11 { 65 {
12 Entity& entity = entities_.at(id); 66 Entity& entity = entities_.at(id);
13 67
14 // Control
15 if (entity.controllable && 68 if (entity.controllable &&
16 !entity.moving) 69 !entity.moving)
17 { 70 {
@@ -38,7 +91,7 @@ void Simulation::tick(
38 91
39 vec2s lookPos = posInDir(entity.gridPos, lookDir); 92 vec2s lookPos = posInDir(entity.gridPos, lookDir);
40 93
41 for (id_type blockId : getGridEntities(lookPos)) 94 for (id_type blockId : posCache_.at(lookPos))
42 { 95 {
43 Entity& block = entities_.at(blockId); 96 Entity& block = entities_.at(blockId);
44 97
@@ -79,16 +132,40 @@ void Simulation::tick(
79 } 132 }
80 } 133 }
81 } 134 }
135 }
136
137 // Schedule
138 schedule_.accumulate(dt);
139
140 if (schedule_.step())
141 {
142 for (id_type id : active_)
143 {
144 Entity& entity = entities_.at(id);
145
146 if (entity.scheduled && !entity.moving)
147 {
148 moveEntityOnGrid(id, Direction::down);
149 }
150 }
151 }
152
82 153
83 154
84 155
85 156
86 // Collision
87 157
88 158
159 // Collision
89 160
90 161
91 // Movement 162
163
164 // Movement
165 for (id_type id : active_)
166 {
167 Entity& entity = entities_.at(id);
168
92 if (entity.moving) 169 if (entity.moving)
93 { 170 {
94 entity.movementTween += entity.speed * dt; 171 entity.movementTween += entity.speed * dt;
@@ -96,7 +173,9 @@ void Simulation::tick(
96 if (entity.movementTween >= 1.0) 173 if (entity.movementTween >= 1.0)
97 { 174 {
98 entity.moving = false; 175 entity.moving = false;
99 setGridPos(id, entity.destPos); 176 entity.gridPos = entity.destPos;
177 posCache_.set(id, entity.gridPos);
178 moveToCache_.remove(id);
100 } 179 }
101 } 180 }
102 181
@@ -141,29 +220,6 @@ void Simulation::deleteEntity(id_type id)
141 active_.erase(id); 220 active_.erase(id);
142} 221}
143 222
144void Simulation::setGridPos(id_type id, vec2s pos)
145{
146 Entity& entity = entities_.at(id);
147
148 size_t oldPosIndex =
149 entity.gridPos.x() + entity.gridPos.y() * level_.getSize().w();
150 gridCache_[oldPosIndex].erase(id);
151
152 entity.gridPos = pos;
153
154 size_t newPosIndex =
155 entity.gridPos.x() + entity.gridPos.y() * level_.getSize().w();
156 gridCache_[newPosIndex].insert(id);
157}
158
159const std::unordered_set<Simulation::id_type>&
160 Simulation::getGridEntities(vec2s pos) const
161{
162 size_t posIndex = pos.x() + pos.y() * level_.getSize().w();
163
164 return gridCache_[posIndex];
165}
166
167bool Simulation::moveEntityOnGrid( 223bool Simulation::moveEntityOnGrid(
168 id_type id, 224 id_type id,
169 Direction moveDir, 225 Direction moveDir,
@@ -225,7 +281,13 @@ bool Simulation::moveEntityOnGrid(
225 return false; 281 return false;
226 } 282 }
227 283
228 for (id_type blockId : getGridEntities(shouldMoveTo)) 284 // Can't move into a space that something else is already moving into.
285 if (!moveToCache_.at(shouldMoveTo).empty())
286 {
287 return false;
288 }
289
290 for (id_type blockId : posCache_.at(shouldMoveTo))
229 { 291 {
230 Entity& block = entities_.at(blockId); 292 Entity& block = entities_.at(blockId);
231 293
@@ -240,6 +302,11 @@ bool Simulation::moveEntityOnGrid(
240 { 302 {
241 return false; 303 return false;
242 } 304 }
305 } else if (block.moveDir != moveDir)
306 {
307 // Can't move perpendicularly into a space that something else is moving
308 // out of.
309 return false;
243 } 310 }
244 311
245 double entityTimeLeft = 1.0 / entity.speed; 312 double entityTimeLeft = 1.0 / entity.speed;
@@ -260,6 +327,9 @@ bool Simulation::moveEntityOnGrid(
260 entity.moving = true; 327 entity.moving = true;
261 entity.destPos = shouldMoveTo; 328 entity.destPos = shouldMoveTo;
262 entity.movementTween = 0.0; 329 entity.movementTween = 0.0;
330 entity.moveDir = moveDir;
331
332 moveToCache_.set(id, entity.destPos);
263 } 333 }
264 334
265 return true; 335 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 @@
3 3
4#include "entity.h" 4#include "entity.h"
5#include "renderer.h" 5#include "renderer.h"
6#include "schedule.h"
7#include "grid_cache.h"
6#include <vector> 8#include <vector>
7#include <deque> 9#include <deque>
8#include <set> 10#include <set>
9#include <unordered_map>
10#include <unordered_set>
11 11
12class Level; 12class Level;
13 13
@@ -17,7 +17,7 @@ public:
17 using id_type = std::vector<Entity>::size_type; 17 using id_type = std::vector<Entity>::size_type;
18 18
19 // Constructor 19 // Constructor
20 explicit Simulation(const Level& level) : level_(level) {} 20 explicit Simulation(const Level& level);
21 21
22 void tick( 22 void tick(
23 double dt, 23 double dt,
@@ -47,15 +47,12 @@ public:
47 return level_; 47 return level_;
48 } 48 }
49 49
50 void setGridPos(id_type id, vec2s pos);
51
52 static vec2s posInDir(vec2s orig, Direction dir); 50 static vec2s posInDir(vec2s orig, Direction dir);
53 51
54private: 52private:
55 53
56 54
57 55
58 const std::unordered_set<id_type>& getGridEntities(vec2s pos) const;
59 56
60 bool moveEntityOnGrid( 57 bool moveEntityOnGrid(
61 id_type id, 58 id_type id,
@@ -63,12 +60,14 @@ private:
63 bool validate = false); 60 bool validate = false);
64 61
65 const Level& level_; 62 const Level& level_;
63 Schedule schedule_ { 120 };
66 64
67 std::vector<Entity> entities_; 65 std::vector<Entity> entities_;
68 std::deque<id_type> available_; 66 std::deque<id_type> available_;
69 std::set<id_type> active_; 67 std::set<id_type> active_;
70 68
71 mutable std::unordered_map<size_t, std::unordered_set<id_type>> gridCache_; 69 mutable GridCache<id_type> posCache_ { level_ };
70 mutable GridCache<id_type> moveToCache_ { level_ };
72}; 71};
73 72
74#endif /* end of include guard: SIMULATION_H_7BF6EEA4 */ 73#endif /* end of include guard: SIMULATION_H_7BF6EEA4 */