summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/entity.h11
-rw-r--r--src/renderer.cpp4
-rw-r--r--src/simulation.cpp231
-rw-r--r--src/simulation.h19
-rw-r--r--src/views.h62
5 files changed, 200 insertions, 127 deletions
diff --git a/src/entity.h b/src/entity.h index c47f1e7..3387219 100644 --- a/src/entity.h +++ b/src/entity.h
@@ -2,13 +2,24 @@
2#define ENTITY_H_0D6CB29A 2#define ENTITY_H_0D6CB29A
3 3
4#include <set> 4#include <set>
5#include <vector>
5#include "vector.h" 6#include "vector.h"
6#include "enums.h" 7#include "enums.h"
7#include "direction.h" 8#include "direction.h"
8 9
10class Entity;
11
12using id_type = std::vector<Entity>::size_type;
13
9class Entity { 14class Entity {
10public: 15public:
11 16
17 Entity(id_type id) : id(id)
18 {
19 }
20
21 id_type id;
22
12 // Transform 23 // Transform
13 vec2s pos; 24 vec2s pos;
14 vec2s size; 25 vec2s size;
diff --git a/src/renderer.cpp b/src/renderer.cpp index 64b3a8e..0feee50 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp
@@ -76,10 +76,8 @@ void Renderer::render(const Simulation& sim)
76 } 76 }
77 } 77 }
78 78
79 for (Simulation::id_type id : sim.getActive()) 79 for (const Entity& entity : sim.getActive() | sim.entityView())
80 { 80 {
81 const Entity& entity = sim.getEntity(id);
82
83 SDL_SetRenderDrawColor(ren_.get(), entity.colorVal, entity.colorVal, 65, 255); 81 SDL_SetRenderDrawColor(ren_.get(), entity.colorVal, entity.colorVal, 65, 255);
84 82
85 SDL_Rect rect { 83 SDL_Rect rect {
diff --git a/src/simulation.cpp b/src/simulation.cpp index 77a9a3e..f75bd3d 100644 --- a/src/simulation.cpp +++ b/src/simulation.cpp
@@ -1,8 +1,8 @@
1#include "simulation.h" 1#include "simulation.h"
2 2
3#include <range/v3/all.hpp>
4#include "consts.h" 3#include "consts.h"
5#include "level.h" 4#include "level.h"
5#include "views.h"
6 6
7Simulation::Simulation( 7Simulation::Simulation(
8 const Level& level) : 8 const Level& level) :
@@ -61,14 +61,14 @@ Simulation::Simulation(
61 train.gridPos = vec2s { 6, 1 }; 61 train.gridPos = vec2s { 6, 1 };
62 train.moveDir = Direction::left; 62 train.moveDir = Direction::left;
63 63
64 id_type player = emplaceEntity(); 64 id_type playerId = emplaceEntity();
65 Entity& entity = getEntity(player); 65 Entity& player = getEntity(playerId);
66 entity.size = TILE_SIZE; 66 player.size = TILE_SIZE;
67 entity.speed = 3.0; 67 player.speed = 3.0;
68 entity.controllable = true; 68 player.controllable = true;
69 entity.colliderType = ColliderType::player; 69 player.colliderType = ColliderType::player;
70 entity.colorVal = 180; 70 player.colorVal = 180;
71 entity.gridPos = vec2s { 1, 5 }; 71 player.gridPos = vec2s { 1, 5 };
72 72
73 id_type crateId = emplaceEntity(); 73 id_type crateId = emplaceEntity();
74 Entity& crate = getEntity(crateId); 74 Entity& crate = getEntity(crateId);
@@ -91,11 +91,9 @@ Simulation::Simulation(
91 crate2.gridPos = vec2s { 6, 7 }; 91 crate2.gridPos = vec2s { 6, 7 };
92 92
93 93
94 for (id_type id : active_) 94 for (Entity& entity : active_ | entityView())
95 { 95 {
96 Entity& entity = entities_.at(id); 96 posCache_.set(entity.id, entity.gridPos);
97
98 posCache_.set(id, entity.gridPos);
99 } 97 }
100} 98}
101 99
@@ -104,75 +102,73 @@ void Simulation::tick(
104 const Uint8* keystate) 102 const Uint8* keystate)
105{ 103{
106 // Control 104 // Control
107 for (id_type id : active_) 105 for (Entity& entity :
106 active_ |
107 entityView() |
108 views::isControllable() |
109 views::isNotMoving())
108 { 110 {
109 Entity& entity = entities_.at(id); 111 if (keystate[SDL_SCANCODE_LSHIFT] || keystate[SDL_SCANCODE_RSHIFT])
110
111 if (entity.controllable &&
112 !entity.moving)
113 { 112 {
114 if (keystate[SDL_SCANCODE_LSHIFT] || keystate[SDL_SCANCODE_RSHIFT]) 113 Direction lookDir = Direction::none;
115 {
116 Direction lookDir = Direction::none;
117 114
118 if (keystate[SDL_SCANCODE_LEFT]) 115 if (keystate[SDL_SCANCODE_LEFT])
119 { 116 {
120 lookDir = Direction::left; 117 lookDir = Direction::left;
121 } 118 }
122 else if (keystate[SDL_SCANCODE_UP]) 119 else if (keystate[SDL_SCANCODE_UP])
123 { 120 {
124 lookDir = Direction::up; 121 lookDir = Direction::up;
125 } 122 }
126 else if (keystate[SDL_SCANCODE_RIGHT]) 123 else if (keystate[SDL_SCANCODE_RIGHT])
127 { 124 {
128 lookDir = Direction::right; 125 lookDir = Direction::right;
129 } 126 }
130 else if (keystate[SDL_SCANCODE_DOWN]) 127 else if (keystate[SDL_SCANCODE_DOWN])
131 { 128 {
132 lookDir = Direction::down; 129 lookDir = Direction::down;
133 } 130 }
134
135 vec2s lookPos = posInDir(entity.gridPos, lookDir);
136 131
137 for (id_type blockId : posCache_.at(lookPos)) 132 vec2s lookPos = posInDir(entity.gridPos, lookDir);
138 {
139 Entity& block = entities_.at(blockId);
140 133
141 if (!block.moving && block.canBePushedBy.count(ColliderType::player)) 134 for (Entity& block :
142 { 135 posCache_.at(lookPos) |
143 moveEntityOnGrid(blockId, lookDir); 136 entityView() |
144 } 137 views::isNotMoving() |
145 } 138 views::canBePushedBy(entity.colliderType) |
146 } else { 139 views::isOnLayer(entity.layer))
147 if (keystate[SDL_SCANCODE_LEFT] && 140 {
148 moveEntityOnGrid(id, Direction::left, true)) 141 moveEntityOnGrid(block, lookDir);
149 { 142 }
150 entity.shouldMoveTo = Direction::left; 143 } else {
151 } 144 if (keystate[SDL_SCANCODE_LEFT] &&
152 else if (keystate[SDL_SCANCODE_UP] && 145 moveEntityOnGrid(entity, Direction::left, true))
153 moveEntityOnGrid(id, Direction::up, true)) 146 {
154 { 147 entity.shouldMoveTo = Direction::left;
155 entity.shouldMoveTo = Direction::up; 148 }
156 } 149 else if (keystate[SDL_SCANCODE_UP] &&
157 else if (keystate[SDL_SCANCODE_RIGHT] && 150 moveEntityOnGrid(entity, Direction::up, true))
158 moveEntityOnGrid(id, Direction::right, true)) 151 {
159 { 152 entity.shouldMoveTo = Direction::up;
160 entity.shouldMoveTo = Direction::right; 153 }
161 } 154 else if (keystate[SDL_SCANCODE_RIGHT] &&
162 else if (keystate[SDL_SCANCODE_DOWN] && 155 moveEntityOnGrid(entity, Direction::right, true))
163 moveEntityOnGrid(id, Direction::down, true)) 156 {
164 { 157 entity.shouldMoveTo = Direction::right;
165 entity.shouldMoveTo = Direction::down; 158 }
166 } 159 else if (keystate[SDL_SCANCODE_DOWN] &&
167 else 160 moveEntityOnGrid(entity, Direction::down, true))
168 { 161 {
169 entity.shouldMoveTo = Direction::none; 162 entity.shouldMoveTo = Direction::down;
170 } 163 }
164 else
165 {
166 entity.shouldMoveTo = Direction::none;
167 }
171 168
172 if (entity.shouldMoveTo != Direction::none) 169 if (entity.shouldMoveTo != Direction::none)
173 { 170 {
174 moveEntityOnGrid(id, entity.shouldMoveTo); 171 moveEntityOnGrid(entity, entity.shouldMoveTo);
175 }
176 } 172 }
177 } 173 }
178 } 174 }
@@ -182,34 +178,33 @@ void Simulation::tick(
182 178
183 if (schedule_.step()) 179 if (schedule_.step())
184 { 180 {
185 for (id_type id : active_) 181 for (Entity& entity :
182 active_ |
183 entityView() |
184 views::isScheduled() |
185 views::isNotMoving())
186 { 186 {
187 Entity& entity = entities_.at(id); 187 auto tracks =
188 posCache_.at(entity.gridPos) |
189 entityView() |
190 views::isTrack();
188 191
189 if (entity.scheduled && !entity.moving) 192 if (!ranges::empty(tracks))
190 { 193 {
191 auto tracks = 194 Entity& track = ranges::front(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 195
203 if (from == track.trackDir1) 196 Direction dir = Direction::none;
204 { 197 Direction from = oppositeDir(entity.moveDir);
205 dir = track.trackDir2;
206 } else if (from == track.trackDir2)
207 {
208 dir = track.trackDir1;
209 }
210 198
211 moveEntityOnGrid(id, dir); 199 if (from == track.trackDir1)
200 {
201 dir = track.trackDir2;
202 } else if (from == track.trackDir2)
203 {
204 dir = track.trackDir1;
212 } 205 }
206
207 moveEntityOnGrid(entity, dir);
213 } 208 }
214 } 209 }
215 } 210 }
@@ -226,10 +221,10 @@ void Simulation::tick(
226 221
227 222
228 // Movement 223 // Movement
229 for (id_type id : active_) 224 for (Entity& entity :
225 active_ |
226 entityView())
230 { 227 {
231 Entity& entity = entities_.at(id);
232
233 if (entity.moving) 228 if (entity.moving)
234 { 229 {
235 entity.movementTween += entity.speed * dt; 230 entity.movementTween += entity.speed * dt;
@@ -238,8 +233,8 @@ void Simulation::tick(
238 { 233 {
239 entity.moving = false; 234 entity.moving = false;
240 entity.gridPos = entity.destPos; 235 entity.gridPos = entity.destPos;
241 posCache_.set(id, entity.gridPos); 236 posCache_.set(entity.id, entity.gridPos);
242 moveToCache_.remove(id); 237 moveToCache_.remove(entity.id);
243 } 238 }
244 } 239 }
245 240
@@ -258,7 +253,7 @@ void Simulation::tick(
258 } 253 }
259} 254}
260 255
261Simulation::id_type Simulation::emplaceEntity() 256id_type Simulation::emplaceEntity()
262{ 257{
263 id_type nextId; 258 id_type nextId;
264 259
@@ -267,10 +262,10 @@ Simulation::id_type Simulation::emplaceEntity()
267 nextId = available_.front(); 262 nextId = available_.front();
268 available_.pop_front(); 263 available_.pop_front();
269 264
270 entities_.at(nextId) = Entity(); 265 entities_.at(nextId) = Entity(nextId);
271 } else { 266 } else {
272 nextId = entities_.size(); 267 nextId = entities_.size();
273 entities_.emplace_back(); 268 entities_.emplace_back(nextId);
274 } 269 }
275 270
276 active_.insert(nextId); 271 active_.insert(nextId);
@@ -285,14 +280,12 @@ void Simulation::deleteEntity(id_type id)
285} 280}
286 281
287bool Simulation::moveEntityOnGrid( 282bool Simulation::moveEntityOnGrid(
288 id_type id, 283 Entity& entity,
289 Direction moveDir, 284 Direction moveDir,
290 bool validate) 285 bool validate)
291{ 286{
292 bool actuallyMove = true; 287 bool actuallyMove = true;
293 288
294 Entity& entity = entities_.at(id);
295
296 vec2s shouldMoveTo = posInDir(entity.gridPos, moveDir); 289 vec2s shouldMoveTo = posInDir(entity.gridPos, moveDir);
297 290
298 switch (moveDir) 291 switch (moveDir)
@@ -348,21 +341,17 @@ bool Simulation::moveEntityOnGrid(
348 // Can't move into a space that something else is already moving into. 341 // Can't move into a space that something else is already moving into.
349 if (!ranges::empty( 342 if (!ranges::empty(
350 moveToCache_.at(shouldMoveTo) | 343 moveToCache_.at(shouldMoveTo) |
351 ranges::view::transform([&] (id_type id) -> Entity& { return entities_.at(id); }) | 344 entityView() |
352 ranges::view::filter([&] (Entity& other) { return other.layer == entity.layer; }))) 345 views::isOnLayer(entity.layer)))
353 { 346 {
354 return false; 347 return false;
355 } 348 }
356 349
357 for (id_type blockId : posCache_.at(shouldMoveTo)) 350 for (Entity& block :
351 posCache_.at(shouldMoveTo) |
352 entityView() |
353 views::isOnLayer(entity.layer))
358 { 354 {
359 Entity& block = entities_.at(blockId);
360
361 if (block.layer != entity.layer)
362 {
363 continue;
364 }
365
366 if (!block.moving) 355 if (!block.moving)
367 { 356 {
368 if (!block.canBePushedBy.count(entity.colliderType)) 357 if (!block.canBePushedBy.count(entity.colliderType))
@@ -370,7 +359,7 @@ bool Simulation::moveEntityOnGrid(
370 return false; 359 return false;
371 } 360 }
372 361
373 if (!moveEntityOnGrid(blockId, moveDir, validate)) 362 if (!moveEntityOnGrid(block, moveDir, validate))
374 { 363 {
375 return false; 364 return false;
376 } 365 }
@@ -401,7 +390,7 @@ bool Simulation::moveEntityOnGrid(
401 entity.movementTween = 0.0; 390 entity.movementTween = 0.0;
402 entity.moveDir = moveDir; 391 entity.moveDir = moveDir;
403 392
404 moveToCache_.set(id, entity.destPos); 393 moveToCache_.set(entity.id, entity.destPos);
405 } 394 }
406 395
407 return true; 396 return true;
diff --git a/src/simulation.h b/src/simulation.h index fbe0a43..a205796 100644 --- a/src/simulation.h +++ b/src/simulation.h
@@ -5,6 +5,7 @@
5#include "renderer.h" 5#include "renderer.h"
6#include "schedule.h" 6#include "schedule.h"
7#include "grid_cache.h" 7#include "grid_cache.h"
8#include <range/v3/all.hpp>
8#include <vector> 9#include <vector>
9#include <deque> 10#include <deque>
10#include <set> 11#include <set>
@@ -14,8 +15,6 @@ class Level;
14class Simulation { 15class Simulation {
15public: 16public:
16 17
17 using id_type = std::vector<Entity>::size_type;
18
19 // Constructor 18 // Constructor
20 explicit Simulation(const Level& level); 19 explicit Simulation(const Level& level);
21 20
@@ -47,13 +46,27 @@ public:
47 return level_; 46 return level_;
48 } 47 }
49 48
49 auto entityView()
50 {
51 return ranges::view::transform([&] (id_type id) -> Entity& {
52 return entities_.at(id);
53 });
54 }
55
56 auto entityView() const
57 {
58 return ranges::view::transform([&] (id_type id) -> const Entity& {
59 return entities_.at(id);
60 });
61 }
62
50private: 63private:
51 64
52 65
53 66
54 67
55 bool moveEntityOnGrid( 68 bool moveEntityOnGrid(
56 id_type id, 69 Entity& entity,
57 Direction moveDir, 70 Direction moveDir,
58 bool validate = false); 71 bool validate = false);
59 72
diff --git a/src/views.h b/src/views.h new file mode 100644 index 0000000..69bd2b5 --- /dev/null +++ b/src/views.h
@@ -0,0 +1,62 @@
1#ifndef VIEWS_H_98651096
2#define VIEWS_H_98651096
3
4#include "entity.h"
5#include <range/v3/all.hpp>
6
7namespace views {
8
9 inline auto isMoving()
10 {
11 return ranges::view::filter([] (const Entity& entity) {
12 return entity.moving;
13 });
14 }
15
16 inline auto isNotMoving()
17 {
18 return ranges::view::filter([] (const Entity& entity) {
19 return !entity.moving;
20 });
21 }
22
23 inline auto isControllable()
24 {
25 return ranges::view::filter([] (const Entity& entity) {
26 return entity.controllable;
27 });
28 }
29
30 inline auto isTrack()
31 {
32 return ranges::view::filter([] (const Entity& entity) {
33 return entity.isTrack;
34 });
35 }
36
37 inline auto isScheduled()
38 {
39 return ranges::view::filter([] (const Entity& entity) {
40 return entity.scheduled;
41 });
42 }
43
44 inline auto isOnLayer(Layer layer)
45 {
46 return ranges::view::filter([layer] (const Entity& entity) {
47 return entity.layer == layer;
48 });
49 }
50
51 inline auto canBePushedBy(ColliderType ctype)
52 {
53 return ranges::view::filter([ctype] (const Entity& entity) {
54 return entity.canBePushedBy.count(ctype);
55 });
56 }
57
58
59
60}
61
62#endif /* end of include guard: VIEWS_H_98651096 */