summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKelly Rauchenberger <fefferburbia@gmail.com>2019-02-22 17:25:59 -0500
committerKelly Rauchenberger <fefferburbia@gmail.com>2019-02-22 17:25:59 -0500
commit26fbd8c1edaf94513d9750681edbe449b699efe4 (patch)
tree3356e61d3eca5eda067169a2c584616a49d8e5a5
parentd9c201cbf2fbfe315137e141d886a9bbfa6794ba (diff)
downloaddispatcher-26fbd8c1edaf94513d9750681edbe449b699efe4.tar.gz
dispatcher-26fbd8c1edaf94513d9750681edbe449b699efe4.tar.bz2
dispatcher-26fbd8c1edaf94513d9750681edbe449b699efe4.zip
Trains move on tracks to the beat
Small implementation changes in various places, biggest thing is now we're using ranges, which is experimental and will be included for real in C++20.
-rw-r--r--CMakeLists.txt1
-rw-r--r--src/direction.cpp25
-rw-r--r--src/direction.h18
-rw-r--r--src/entity.h7
-rw-r--r--src/enums.h9
-rw-r--r--src/schedule.h22
-rw-r--r--src/simulation.cpp114
-rw-r--r--src/simulation.h4
8 files changed, 160 insertions, 40 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 8800db7..6fabbf3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt
@@ -23,6 +23,7 @@ add_executable(dispatcher
23 src/main.cpp 23 src/main.cpp
24 src/renderer.cpp 24 src/renderer.cpp
25 src/simulation.cpp 25 src/simulation.cpp
26 src/direction.cpp
26) 27)
27 28
28set_property(TARGET dispatcher PROPERTY CXX_STANDARD 17) 29set_property(TARGET dispatcher PROPERTY CXX_STANDARD 17)
diff --git a/src/direction.cpp b/src/direction.cpp new file mode 100644 index 0000000..cf6409e --- /dev/null +++ b/src/direction.cpp
@@ -0,0 +1,25 @@
1#include "direction.h"
2
3vec2s posInDir(vec2s orig, Direction dir)
4{
5 switch (dir)
6 {
7 case Direction::left: return orig - vec2s { 1, 0 };
8 case Direction::right: return orig + vec2s { 1, 0 };
9 case Direction::up: return orig - vec2s { 0, 1 };
10 case Direction::down: return orig + vec2s { 0, 1 };
11 case Direction::none: return orig;
12 }
13}
14
15Direction oppositeDir(Direction dir)
16{
17 switch (dir)
18 {
19 case Direction::left: return Direction::right;
20 case Direction::right: return Direction::left;
21 case Direction::up: return Direction::down;
22 case Direction::down: return Direction::up;
23 case Direction::none: return Direction::none;
24 }
25}
diff --git a/src/direction.h b/src/direction.h new file mode 100644 index 0000000..8108505 --- /dev/null +++ b/src/direction.h
@@ -0,0 +1,18 @@
1#ifndef DIRECTION_H_2B40D968
2#define DIRECTION_H_2B40D968
3
4#include "vector.h"
5
6enum class Direction {
7 none,
8 left,
9 right,
10 up,
11 down
12};
13
14vec2s posInDir(vec2s orig, Direction dir);
15
16Direction oppositeDir(Direction dir);
17
18#endif /* end of include guard: DIRECTION_H_2B40D968 */
diff --git a/src/entity.h b/src/entity.h index a69c612..c47f1e7 100644 --- a/src/entity.h +++ b/src/entity.h
@@ -4,6 +4,7 @@
4#include <set> 4#include <set>
5#include "vector.h" 5#include "vector.h"
6#include "enums.h" 6#include "enums.h"
7#include "direction.h"
7 8
8class Entity { 9class Entity {
9public: 10public:
@@ -14,6 +15,7 @@ public:
14 15
15 // Grid placement 16 // Grid placement
16 vec2s gridPos; 17 vec2s gridPos;
18 Layer layer = Layer::object;
17 19
18 // Movement 20 // Movement
19 Direction shouldMoveTo = Direction::none; 21 Direction shouldMoveTo = Direction::none;
@@ -35,6 +37,11 @@ public:
35 37
36 bool scheduled = false; 38 bool scheduled = false;
37 39
40 // Track
41 bool isTrack = false;
42 Direction trackDir1 = Direction::none;
43 Direction trackDir2 = Direction::none;
44
38}; 45};
39 46
40#endif /* end of include guard: ENTITY_H_0D6CB29A */ 47#endif /* end of include guard: ENTITY_H_0D6CB29A */
diff --git a/src/enums.h b/src/enums.h index 9821da1..e2056f5 100644 --- a/src/enums.h +++ b/src/enums.h
@@ -8,12 +8,9 @@ enum class ColliderType {
8 other 8 other
9}; 9};
10 10
11enum class Direction { 11enum class Layer {
12 none, 12 track,
13 left, 13 object
14 right,
15 up,
16 down
17}; 14};
18 15
19#endif /* end of include guard: ENUMS_H_CD0A75E4 */ 16#endif /* end of include guard: ENUMS_H_CD0A75E4 */
diff --git a/src/schedule.h b/src/schedule.h index 5d77761..f7c5543 100644 --- a/src/schedule.h +++ b/src/schedule.h
@@ -5,17 +5,23 @@ class Schedule {
5public: 5public:
6 6
7 explicit Schedule( 7 explicit Schedule(
8 size_t bpm) : 8 double bpm) :
9 bpm_(bpm), 9 bpm_(bpm),
10 tick_(60.0 / static_cast<double>(bpm_)) 10 bps_(bpm_ / 60.0),
11 tick_(1.0 / bps_)
11 { 12 {
12 } 13 }
13 14
14 size_t getBPM() const 15 double getBPM() const
15 { 16 {
16 return bpm_; 17 return bpm_;
17 } 18 }
18 19
20 double getBPS() const
21 {
22 return bps_;
23 }
24
19 void accumulate(double dt) 25 void accumulate(double dt)
20 { 26 {
21 accum_ += dt; 27 accum_ += dt;
@@ -26,6 +32,7 @@ public:
26 if (accum_ > tick_) 32 if (accum_ > tick_)
27 { 33 {
28 accum_ -= tick_; 34 accum_ -= tick_;
35 beats_++;
29 36
30 return true; 37 return true;
31 } else { 38 } else {
@@ -33,11 +40,18 @@ public:
33 } 40 }
34 } 41 }
35 42
43 size_t getBeat() const
44 {
45 return beats_;
46 }
47
36private: 48private:
37 49
38 size_t bpm_; 50 double bpm_;
51 double bps_;
39 double tick_; 52 double tick_;
40 double accum_ = 0.0; 53 double accum_ = 0.0;
54 size_t beats_ = 0;
41 55
42}; 56};
43 57
diff --git a/src/simulation.cpp b/src/simulation.cpp index 1379c34..77a9a3e 100644 --- a/src/simulation.cpp +++ b/src/simulation.cpp
@@ -1,5 +1,6 @@
1#include "simulation.h" 1#include "simulation.h"
2 2
3#include <range/v3/all.hpp>
3#include "consts.h" 4#include "consts.h"
4#include "level.h" 5#include "level.h"
5 6
@@ -7,6 +8,59 @@ Simulation::Simulation(
7 const Level& level) : 8 const Level& level) :
8 level_(level) 9 level_(level)
9{ 10{
11
12
13 id_type trackId = emplaceEntity();
14 Entity& track = getEntity(trackId);
15 track.size = TILE_SIZE;
16 track.layer = Layer::track;
17 track.isTrack = true;
18 track.trackDir1 = Direction::right;
19 track.trackDir2 = Direction::down;
20 track.colorVal = 130;
21 track.gridPos = vec2s { 6, 1 };
22
23 id_type trackId2 = emplaceEntity();
24 Entity& track2 = getEntity(trackId2);
25 track2.size = TILE_SIZE;
26 track2.layer = Layer::track;
27 track2.isTrack = true;
28 track2.trackDir1 = Direction::right;
29 track2.trackDir2 = Direction::up;
30 track2.colorVal = 130;
31 track2.gridPos = vec2s { 6, 2 };
32
33 id_type trackId3 = emplaceEntity();
34 Entity& track3 = getEntity(trackId3);
35 track3.size = TILE_SIZE;
36 track3.layer = Layer::track;
37 track3.isTrack = true;
38 track3.trackDir1 = Direction::up;
39 track3.trackDir2 = Direction::left;
40 track3.colorVal = 130;
41 track3.gridPos = vec2s { 7, 2 };
42
43 id_type trackId4 = emplaceEntity();
44 Entity& track4 = getEntity(trackId4);
45 track4.size = TILE_SIZE;
46 track4.layer = Layer::track;
47 track4.isTrack = true;
48 track4.trackDir1 = Direction::left;
49 track4.trackDir2 = Direction::down;
50 track4.colorVal = 130;
51 track4.gridPos = vec2s { 7, 1 };
52
53
54 id_type trainId = emplaceEntity();
55 Entity& train = getEntity(trainId);
56 train.size = TILE_SIZE;
57 train.speed = schedule_.getBPS() * 2.0;
58 train.colliderType = ColliderType::train;
59 train.scheduled = true;
60 train.colorVal = 90;
61 train.gridPos = vec2s { 6, 1 };
62 train.moveDir = Direction::left;
63
10 id_type player = emplaceEntity(); 64 id_type player = emplaceEntity();
11 Entity& entity = getEntity(player); 65 Entity& entity = getEntity(player);
12 entity.size = TILE_SIZE; 66 entity.size = TILE_SIZE;
@@ -19,7 +73,7 @@ Simulation::Simulation(
19 id_type crateId = emplaceEntity(); 73 id_type crateId = emplaceEntity();
20 Entity& crate = getEntity(crateId); 74 Entity& crate = getEntity(crateId);
21 crate.size = TILE_SIZE; 75 crate.size = TILE_SIZE;
22 crate.speed = static_cast<double>(schedule_.getBPM()) / 30.0; 76 crate.speed = schedule_.getBPS() * 2.0;
23 crate.colliderType = ColliderType::crate; 77 crate.colliderType = ColliderType::crate;
24 crate.canBePushedBy.insert(ColliderType::player); 78 crate.canBePushedBy.insert(ColliderType::player);
25 crate.canBePushedBy.insert(ColliderType::crate); 79 crate.canBePushedBy.insert(ColliderType::crate);
@@ -29,24 +83,13 @@ Simulation::Simulation(
29 id_type crateId2 = emplaceEntity(); 83 id_type crateId2 = emplaceEntity();
30 Entity& crate2 = getEntity(crateId2); 84 Entity& crate2 = getEntity(crateId2);
31 crate2.size = TILE_SIZE; 85 crate2.size = TILE_SIZE;
32 crate2.speed = static_cast<double>(schedule_.getBPM()) / 30.0; 86 crate2.speed = schedule_.getBPS() * 2.0;
33 crate2.colliderType = ColliderType::crate; 87 crate2.colliderType = ColliderType::crate;
34 crate2.canBePushedBy.insert(ColliderType::player); 88 crate2.canBePushedBy.insert(ColliderType::player);
35 crate2.canBePushedBy.insert(ColliderType::crate); 89 crate2.canBePushedBy.insert(ColliderType::crate);
36 crate2.canBePushedBy.insert(ColliderType::train); 90 crate2.canBePushedBy.insert(ColliderType::train);
37 crate2.gridPos = vec2s { 6, 7 }; 91 crate2.gridPos = vec2s { 6, 7 };
38 92
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 93
51 for (id_type id : active_) 94 for (id_type id : active_)
52 { 95 {
@@ -145,7 +188,28 @@ void Simulation::tick(
145 188
146 if (entity.scheduled && !entity.moving) 189 if (entity.scheduled && !entity.moving)
147 { 190 {
148 moveEntityOnGrid(id, Direction::down); 191 auto tracks =
192 posCache_.at(entity.gridPos) |
193 ranges::view::transform([&] (id_type id) -> Entity& { return entities_.at(id); }) |
194 ranges::view::filter([&] (Entity& other) { return other.isTrack; });
195
196 if (!ranges::empty(tracks))
197 {
198 Entity& track = ranges::front(tracks);
199
200 Direction dir = Direction::none;
201 Direction from = oppositeDir(entity.moveDir);
202
203 if (from == track.trackDir1)
204 {
205 dir = track.trackDir2;
206 } else if (from == track.trackDir2)
207 {
208 dir = track.trackDir1;
209 }
210
211 moveEntityOnGrid(id, dir);
212 }
149 } 213 }
150 } 214 }
151 } 215 }
@@ -282,7 +346,10 @@ bool Simulation::moveEntityOnGrid(
282 } 346 }
283 347
284 // Can't move into a space that something else is already moving into. 348 // Can't move into a space that something else is already moving into.
285 if (!moveToCache_.at(shouldMoveTo).empty()) 349 if (!ranges::empty(
350 moveToCache_.at(shouldMoveTo) |
351 ranges::view::transform([&] (id_type id) -> Entity& { return entities_.at(id); }) |
352 ranges::view::filter([&] (Entity& other) { return other.layer == entity.layer; })))
286 { 353 {
287 return false; 354 return false;
288 } 355 }
@@ -291,6 +358,11 @@ bool Simulation::moveEntityOnGrid(
291 { 358 {
292 Entity& block = entities_.at(blockId); 359 Entity& block = entities_.at(blockId);
293 360
361 if (block.layer != entity.layer)
362 {
363 continue;
364 }
365
294 if (!block.moving) 366 if (!block.moving)
295 { 367 {
296 if (!block.canBePushedBy.count(entity.colliderType)) 368 if (!block.canBePushedBy.count(entity.colliderType))
@@ -334,15 +406,3 @@ bool Simulation::moveEntityOnGrid(
334 406
335 return true; 407 return true;
336} 408}
337
338vec2s Simulation::posInDir(vec2s orig, Direction dir)
339{
340 switch (dir)
341 {
342 case Direction::left: return orig - vec2s { 1, 0 };
343 case Direction::right: return orig + vec2s { 1, 0 };
344 case Direction::up: return orig - vec2s { 0, 1 };
345 case Direction::down: return orig + vec2s { 0, 1 };
346 case Direction::none: return orig;
347 }
348}
diff --git a/src/simulation.h b/src/simulation.h index f86d513..fbe0a43 100644 --- a/src/simulation.h +++ b/src/simulation.h
@@ -47,8 +47,6 @@ public:
47 return level_; 47 return level_;
48 } 48 }
49 49
50 static vec2s posInDir(vec2s orig, Direction dir);
51
52private: 50private:
53 51
54 52
@@ -60,7 +58,7 @@ private:
60 bool validate = false); 58 bool validate = false);
61 59
62 const Level& level_; 60 const Level& level_;
63 Schedule schedule_ { 120 }; 61 Schedule schedule_ { 90 };
64 62
65 std::vector<Entity> entities_; 63 std::vector<Entity> entities_;
66 std::deque<id_type> available_; 64 std::deque<id_type> available_;