diff options
author | Kelly Rauchenberger <fefferburbia@gmail.com> | 2015-03-07 11:29:57 -0500 |
---|---|---|
committer | Kelly Rauchenberger <fefferburbia@gmail.com> | 2015-03-07 11:29:57 -0500 |
commit | b53826079429939cdfbda073608cb85be8ba0738 (patch) | |
tree | 3c40de4658f0cea01cd3938f07fe82788ef3dd01 /src/components.cpp | |
parent | 0751446e1d069263d25abcff49a32a380231709a (diff) | |
download | therapy-b53826079429939cdfbda073608cb85be8ba0738.tar.gz therapy-b53826079429939cdfbda073608cb85be8ba0738.tar.bz2 therapy-b53826079429939cdfbda073608cb85be8ba0738.zip |
Created entity-component system
Also tweaked the bloom flicker, tweaked the scanline texture, created a second test map, and created some currently unused sound effects.
Diffstat (limited to 'src/components.cpp')
-rw-r--r-- | src/components.cpp | 537 |
1 files changed, 537 insertions, 0 deletions
diff --git a/src/components.cpp b/src/components.cpp new file mode 100644 index 0000000..f9c7c10 --- /dev/null +++ b/src/components.cpp | |||
@@ -0,0 +1,537 @@ | |||
1 | #include "components.h" | ||
2 | #include "game.h" | ||
3 | |||
4 | // User movement component | ||
5 | |||
6 | void UserMovementComponent::input(int key, int action) | ||
7 | { | ||
8 | if (action == GLFW_PRESS) | ||
9 | { | ||
10 | if (key == GLFW_KEY_LEFT) | ||
11 | { | ||
12 | holdingLeft = true; | ||
13 | |||
14 | message_t msg; | ||
15 | msg.type = CM_WALK_LEFT; | ||
16 | |||
17 | entity.send(msg); | ||
18 | } else if (key == GLFW_KEY_RIGHT) | ||
19 | { | ||
20 | holdingRight = true; | ||
21 | |||
22 | message_t msg; | ||
23 | msg.type = CM_WALK_RIGHT; | ||
24 | |||
25 | entity.send(msg); | ||
26 | } else if (key == GLFW_KEY_UP) | ||
27 | { | ||
28 | message_t msg; | ||
29 | msg.type = CM_JUMP; | ||
30 | |||
31 | entity.send(msg); | ||
32 | } else if (key == GLFW_KEY_DOWN) | ||
33 | { | ||
34 | message_t msg; | ||
35 | msg.type = CM_CAN_DROP; | ||
36 | |||
37 | entity.send(msg); | ||
38 | } | ||
39 | } else if (action == GLFW_RELEASE) | ||
40 | { | ||
41 | if (key == GLFW_KEY_LEFT) | ||
42 | { | ||
43 | holdingLeft = false; | ||
44 | |||
45 | if (holdingRight) | ||
46 | { | ||
47 | message_t msg; | ||
48 | msg.type = CM_WALK_RIGHT; | ||
49 | |||
50 | entity.send(msg); | ||
51 | } else { | ||
52 | message_t msg; | ||
53 | msg.type = CM_STOP_WALKING; | ||
54 | |||
55 | entity.send(msg); | ||
56 | } | ||
57 | } else if (key == GLFW_KEY_RIGHT) | ||
58 | { | ||
59 | holdingRight = false; | ||
60 | |||
61 | if (holdingLeft) | ||
62 | { | ||
63 | message_t msg; | ||
64 | msg.type = CM_WALK_LEFT; | ||
65 | |||
66 | entity.send(msg); | ||
67 | } else { | ||
68 | message_t msg; | ||
69 | msg.type = CM_STOP_WALKING; | ||
70 | |||
71 | entity.send(msg); | ||
72 | } | ||
73 | } else if (key == GLFW_KEY_DOWN) | ||
74 | { | ||
75 | message_t msg; | ||
76 | msg.type = CM_CANT_DROP; | ||
77 | |||
78 | entity.send(msg); | ||
79 | } else if (key == GLFW_KEY_UP) | ||
80 | { | ||
81 | message_t msg; | ||
82 | msg.type = CM_STOP_JUMP; | ||
83 | |||
84 | entity.send(msg); | ||
85 | } | ||
86 | } | ||
87 | } | ||
88 | |||
89 | // Physics component | ||
90 | |||
91 | void PhysicsBodyComponent::receive(message_t msg) | ||
92 | { | ||
93 | if (msg.type == CM_WALK_LEFT) | ||
94 | { | ||
95 | velocity.first = -1.5; | ||
96 | } else if (msg.type == CM_WALK_RIGHT) | ||
97 | { | ||
98 | velocity.first = 1.5; | ||
99 | } else if (msg.type == CM_STOP_WALKING) | ||
100 | { | ||
101 | velocity.first = 0.0; | ||
102 | } | ||
103 | } | ||
104 | |||
105 | void PhysicsBodyComponent::tick() | ||
106 | { | ||
107 | velocity.first += accel.first; | ||
108 | velocity.second += accel.second; | ||
109 | |||
110 | position.first += velocity.first; | ||
111 | position.second += velocity.second; | ||
112 | } | ||
113 | |||
114 | void PhysicsBodyComponent::detectCollision(Entity& player, Locatable& physics, std::pair<double, double> old_position) | ||
115 | { | ||
116 | // If already colliding, do nothing! | ||
117 | if ((old_position.first + physics.size.first > this->position.first) | ||
118 | && (old_position.first < this->position.first + this->size.first) | ||
119 | && (old_position.second + physics.size.second > this->position.second) | ||
120 | && (old_position.second < this->position.second + this->size.second)) | ||
121 | { | ||
122 | return; | ||
123 | } | ||
124 | |||
125 | // If newly colliding, SHOCK AND HORROR! | ||
126 | if ((physics.position.first + physics.size.first > this->position.first) | ||
127 | && (physics.position.first < this->position.first + this->size.first) | ||
128 | && (physics.position.second + physics.size.second > this->position.second) | ||
129 | && (physics.position.second < this->position.second + this->size.second)) | ||
130 | { | ||
131 | message_t msg; | ||
132 | msg.type = CM_COLLISION; | ||
133 | msg.collisionEntity = &player; | ||
134 | |||
135 | entity.send(msg); | ||
136 | } | ||
137 | } | ||
138 | |||
139 | // Render player | ||
140 | |||
141 | PlayerSpriteComponent::PlayerSpriteComponent(Entity& entity, Locatable& physics) : Component(entity), physics(physics) | ||
142 | { | ||
143 | sprite = loadTextureFromFile("../res/Starla.png"); | ||
144 | } | ||
145 | |||
146 | PlayerSpriteComponent::~PlayerSpriteComponent() | ||
147 | { | ||
148 | destroyTexture(sprite); | ||
149 | } | ||
150 | |||
151 | void PlayerSpriteComponent::render(Texture* buffer) | ||
152 | { | ||
153 | int frame = 0; | ||
154 | if (isMoving) | ||
155 | { | ||
156 | frame += 2; | ||
157 | |||
158 | if (animFrame < 10) | ||
159 | { | ||
160 | frame += 2; | ||
161 | } | ||
162 | } | ||
163 | if (facingLeft) frame++; | ||
164 | |||
165 | Rectangle src_rect(frame*10, 0, 10, 12); | ||
166 | Rectangle dst_rect((int) physics.position.first, (int) physics.position.second, physics.size.first, physics.size.second); | ||
167 | blitTexture(sprite, buffer, &src_rect, &dst_rect); | ||
168 | } | ||
169 | |||
170 | void PlayerSpriteComponent::receive(message_t msg) | ||
171 | { | ||
172 | if (msg.type == CM_WALK_LEFT) | ||
173 | { | ||
174 | facingLeft = true; | ||
175 | isMoving = true; | ||
176 | } else if (msg.type == CM_WALK_RIGHT) | ||
177 | { | ||
178 | facingLeft = false; | ||
179 | isMoving = true; | ||
180 | } else if (msg.type == CM_STOP_WALKING) | ||
181 | { | ||
182 | isMoving = false; | ||
183 | } | ||
184 | } | ||
185 | |||
186 | void PlayerSpriteComponent::tick() | ||
187 | { | ||
188 | animFrame++; | ||
189 | animFrame %= 20; | ||
190 | } | ||
191 | |||
192 | // Player physics | ||
193 | |||
194 | #define JUMP_VELOCITY(h, l) (-2 * (h) / (l)) | ||
195 | #define JUMP_GRAVITY(h, l) (2 * ((h) / (l)) / (l)) | ||
196 | |||
197 | PlayerPhysicsComponent::PlayerPhysicsComponent(Entity& entity) : Component(entity) | ||
198 | { | ||
199 | jump_velocity = JUMP_VELOCITY(TILE_HEIGHT*4.5, 0.3*FRAMES_PER_SECOND); | ||
200 | jump_gravity = JUMP_GRAVITY(TILE_HEIGHT*4.5, 0.3*FRAMES_PER_SECOND); | ||
201 | jump_gravity_short = JUMP_GRAVITY(TILE_HEIGHT*3.5, 0.233*FRAMES_PER_SECOND); | ||
202 | |||
203 | accel.second = jump_gravity_short; | ||
204 | } | ||
205 | |||
206 | void PlayerPhysicsComponent::receive(message_t msg) | ||
207 | { | ||
208 | if (msg.type == CM_WALK_LEFT) | ||
209 | { | ||
210 | velocity.first = -1.5; | ||
211 | direction = -1; | ||
212 | } else if (msg.type == CM_WALK_RIGHT) | ||
213 | { | ||
214 | velocity.first = 1.5; | ||
215 | direction = 1; | ||
216 | } else if (msg.type == CM_STOP_WALKING) | ||
217 | { | ||
218 | velocity.first = 0.0; | ||
219 | direction = 0; | ||
220 | } else if (msg.type == CM_JUMP) | ||
221 | { | ||
222 | velocity.second = jump_velocity; | ||
223 | accel.second = jump_gravity; | ||
224 | } else if (msg.type == CM_STOP_JUMP) | ||
225 | { | ||
226 | accel.second = jump_gravity_short; | ||
227 | } else if (msg.type == CM_CAN_DROP) | ||
228 | { | ||
229 | canDrop = true; | ||
230 | } else if (msg.type == CM_CANT_DROP) | ||
231 | { | ||
232 | canDrop = false; | ||
233 | } else if (msg.type == CM_DROP) | ||
234 | { | ||
235 | if (canDrop) | ||
236 | { | ||
237 | canDrop = false; | ||
238 | } else { | ||
239 | position.second = msg.dropAxis - size.second; | ||
240 | velocity.second = 0; | ||
241 | } | ||
242 | } | ||
243 | } | ||
244 | |||
245 | void PlayerPhysicsComponent::tick() | ||
246 | { | ||
247 | // Continue walking even if blocked earlier | ||
248 | if (velocity.first == 0) | ||
249 | { | ||
250 | if (direction < 0) | ||
251 | { | ||
252 | velocity.first = -1.5; | ||
253 | } else if (direction > 0) | ||
254 | { | ||
255 | velocity.first = 1.5; | ||
256 | } | ||
257 | } | ||
258 | |||
259 | // Increase gravity at the height of jump | ||
260 | if ((accel.second == jump_gravity) && (velocity.second >= 0)) | ||
261 | { | ||
262 | accel.second = jump_gravity_short; | ||
263 | } | ||
264 | |||
265 | // Apply acceleration | ||
266 | velocity.first += accel.first; | ||
267 | velocity.second += accel.second; | ||
268 | |||
269 | // Terminal velocity | ||
270 | if (velocity.first < -16) velocity.first = -16; | ||
271 | if (velocity.first > 16) velocity.first = 16; | ||
272 | if (velocity.second < -16) velocity.second = -16; | ||
273 | if (velocity.second > 16) velocity.second = 16; | ||
274 | |||
275 | // Do the movement | ||
276 | std::pair<double, double> old_position = std::make_pair(position.first, position.second); | ||
277 | position.first += velocity.first; | ||
278 | position.second += velocity.second; | ||
279 | |||
280 | // Check for collisions | ||
281 | for (auto it = entity.world->bodies.begin(); it != entity.world->bodies.end(); it++) | ||
282 | { | ||
283 | auto poop = *it; | ||
284 | poop->detectCollision(entity, *this, old_position); | ||
285 | } | ||
286 | } | ||
287 | |||
288 | // Map rendering | ||
289 | |||
290 | MapRenderComponent::MapRenderComponent(Entity& entity, Map* map) : Component(entity) | ||
291 | { | ||
292 | screen = createTexture(GAME_WIDTH, GAME_HEIGHT); | ||
293 | fillTexture(screen, NULL, 0, 0, 0); | ||
294 | |||
295 | Texture* tiles = loadTextureFromFile("../res/tiles.png"); | ||
296 | |||
297 | for (int i=0; i<MAP_WIDTH*(MAP_HEIGHT-1); i++) | ||
298 | { | ||
299 | int tile = map->mapdata()[i]; | ||
300 | int x = i % MAP_WIDTH; | ||
301 | int y = i / MAP_WIDTH; | ||
302 | Rectangle dst(x*TILE_WIDTH, y*TILE_HEIGHT, TILE_WIDTH, TILE_HEIGHT); | ||
303 | Rectangle src(tile%8*TILE_WIDTH, tile/8*TILE_HEIGHT, TILE_WIDTH, TILE_HEIGHT); | ||
304 | |||
305 | if (tile > 0) | ||
306 | { | ||
307 | blitTexture(tiles, screen, &src, &dst); | ||
308 | } | ||
309 | } | ||
310 | |||
311 | destroyTexture(tiles); | ||
312 | |||
313 | Texture* font = loadTextureFromFile("../res/font.bmp"); | ||
314 | const char* map_name = map->title(); | ||
315 | int start_x = (40/2) - (strlen(map_name)/2); | ||
316 | for (size_t i=0; i<strlen(map_name); i++) | ||
317 | { | ||
318 | Rectangle srcRect(map_name[i] % 16 * 8, map_name[i] / 16 * 8, 8, 8); | ||
319 | Rectangle dstRect((start_x + i)*8, 24*8, 8, 8); | ||
320 | blitTexture(font, screen, &srcRect, &dstRect); | ||
321 | } | ||
322 | |||
323 | destroyTexture(font); | ||
324 | } | ||
325 | |||
326 | MapRenderComponent::~MapRenderComponent() | ||
327 | { | ||
328 | destroyTexture(screen); | ||
329 | } | ||
330 | |||
331 | void MapRenderComponent::render(Texture* buffer) | ||
332 | { | ||
333 | blitTexture(screen, buffer, NULL, NULL); | ||
334 | } | ||
335 | |||
336 | // Map collision | ||
337 | |||
338 | MapCollisionComponent::MapCollisionComponent(Entity& entity, Map* map) : Component(entity) | ||
339 | { | ||
340 | this->map = map; | ||
341 | |||
342 | add_collision(-6, 0, GAME_WIDTH, left, (map->getLeftMap() == NULL) ? 1 : 2); | ||
343 | add_collision(GAME_WIDTH+6, 0, GAME_WIDTH, right, (map->getRightMap() == NULL) ? 3 : 2); | ||
344 | |||
345 | for (int i=0; i<MAP_WIDTH*(MAP_HEIGHT-1); i++) | ||
346 | { | ||
347 | int x = i % MAP_WIDTH; | ||
348 | int y = i / MAP_WIDTH; | ||
349 | int tile = map->mapdata()[i]; | ||
350 | |||
351 | if ((tile > 0) && (!((tile >= 5) && (tile <= 7)))) | ||
352 | { | ||
353 | add_collision(x*TILE_WIDTH, y*TILE_HEIGHT, (y+1)*TILE_HEIGHT, right, 0); | ||
354 | add_collision((x+1)*TILE_WIDTH, y*TILE_HEIGHT, (y+1)*TILE_HEIGHT, left, 0); | ||
355 | add_collision(y*TILE_HEIGHT, x*TILE_WIDTH, (x+1)*TILE_WIDTH, down, 0); | ||
356 | add_collision((y+1)*TILE_HEIGHT, x*TILE_WIDTH, (x+1)*TILE_WIDTH, up, 0); | ||
357 | } else if ((tile >= 5) && (tile <= 7)) | ||
358 | { | ||
359 | add_collision(y*TILE_HEIGHT, x*TILE_WIDTH, (x+1)*TILE_WIDTH, down, 3); | ||
360 | } | ||
361 | } | ||
362 | } | ||
363 | |||
364 | void MapCollisionComponent::add_collision(int axis, int lower, int upper, direction_t dir, int type) | ||
365 | { | ||
366 | std::list<collision_t>::iterator it; | ||
367 | |||
368 | switch (dir) | ||
369 | { | ||
370 | case up: | ||
371 | it = up_collisions.begin(); | ||
372 | for (; it!=up_collisions.end(); it++) | ||
373 | { | ||
374 | if (it->axis < axis) break; | ||
375 | } | ||
376 | |||
377 | up_collisions.insert(it, {axis, lower, upper, type}); | ||
378 | |||
379 | break; | ||
380 | case down: | ||
381 | it = down_collisions.begin(); | ||
382 | for (; it!=down_collisions.end(); it++) | ||
383 | { | ||
384 | if (it->axis > axis) break; | ||
385 | } | ||
386 | |||
387 | down_collisions.insert(it, {axis, lower, upper, type}); | ||
388 | |||
389 | break; | ||
390 | case left: | ||
391 | it = left_collisions.begin(); | ||
392 | for (; it!=left_collisions.end(); it++) | ||
393 | { | ||
394 | if (it->axis < axis) break; | ||
395 | } | ||
396 | |||
397 | left_collisions.insert(it, {axis, lower, upper, type}); | ||
398 | |||
399 | break; | ||
400 | case right: | ||
401 | it = right_collisions.begin(); | ||
402 | for (; it!=right_collisions.end(); it++) | ||
403 | { | ||
404 | if (it->axis > axis) break; | ||
405 | } | ||
406 | |||
407 | right_collisions.insert(it, {axis, lower, upper, type}); | ||
408 | |||
409 | break; | ||
410 | } | ||
411 | } | ||
412 | |||
413 | void MapCollisionComponent::detectCollision(Entity& player, Locatable& physics, std::pair<double, double> old_position) | ||
414 | { | ||
415 | int fixed_x = (int) physics.position.first; | ||
416 | int fixed_y = (int) physics.position.second; | ||
417 | int fixed_ox = (int) old_position.first; | ||
418 | int fixed_oy = (int) old_position.second; | ||
419 | |||
420 | if (fixed_x < fixed_ox) | ||
421 | { | ||
422 | for (auto it=left_collisions.begin(); it!=left_collisions.end(); it++) | ||
423 | { | ||
424 | if (it->axis > fixed_ox) continue; | ||
425 | if (it->axis < fixed_x) break; | ||
426 | |||
427 | if ((fixed_oy+physics.size.second > it->lower) && (fixed_oy < it->upper)) | ||
428 | { | ||
429 | // We have a collision! | ||
430 | if (it->type == 0) | ||
431 | { | ||
432 | physics.position.first = it->axis; | ||
433 | physics.velocity.first = 0; | ||
434 | } else if (it->type == 1) | ||
435 | { | ||
436 | physics.position.first = GAME_WIDTH-physics.size.first/2; | ||
437 | } else if (it->type == 2) | ||
438 | { | ||
439 | physics.position.first = GAME_WIDTH-physics.size.first/2; | ||
440 | Game::getInstance().loadMap(map->getLeftMap()); | ||
441 | } | ||
442 | |||
443 | break; | ||
444 | } | ||
445 | } | ||
446 | } else if (fixed_x > fixed_ox) | ||
447 | { | ||
448 | for (auto it=right_collisions.begin(); it!=right_collisions.end(); it++) | ||
449 | { | ||
450 | if (it->axis < fixed_ox+physics.size.first) continue; | ||
451 | if (it->axis > fixed_x+physics.size.first) break; | ||
452 | |||
453 | if ((fixed_oy+physics.size.second > it->lower) && (fixed_oy < it->upper)) | ||
454 | { | ||
455 | // We have a collision! | ||
456 | if (it->type == 0) | ||
457 | { | ||
458 | physics.position.first = it->axis - physics.size.first; | ||
459 | physics.velocity.first = 0; | ||
460 | } else if (it->type == 1) | ||
461 | { | ||
462 | physics.position.first = -physics.size.first/2; | ||
463 | } else if (it->type == 2) | ||
464 | { | ||
465 | physics.position.first = -physics.size.first/2; | ||
466 | Game::getInstance().loadMap(map->getRightMap()); | ||
467 | } else if (it->type == 3) | ||
468 | { | ||
469 | physics.position.first = it->axis - physics.size.first; | ||
470 | |||
471 | message_t msg; | ||
472 | msg.type = CM_WALK_LEFT; | ||
473 | player.send(msg); | ||
474 | } | ||
475 | |||
476 | break; | ||
477 | } | ||
478 | } | ||
479 | } | ||
480 | |||
481 | fixed_x = (int) physics.position.first; | ||
482 | fixed_y = (int) physics.position.second; | ||
483 | |||
484 | if (fixed_y < fixed_oy) | ||
485 | { | ||
486 | for (auto it=up_collisions.begin(); it!=up_collisions.end(); it++) | ||
487 | { | ||
488 | if (it->axis > fixed_oy) continue; | ||
489 | if (it->axis < fixed_y) break; | ||
490 | |||
491 | if ((fixed_x+physics.size.first > it->lower) && (fixed_x < it->upper)) | ||
492 | { | ||
493 | // We have a collision! | ||
494 | if (it->type == 0) | ||
495 | { | ||
496 | physics.position.second = it->axis; | ||
497 | physics.velocity.second = 0; | ||
498 | } else if (it->type == 1) | ||
499 | { | ||
500 | physics.position.second = GAME_HEIGHT-physics.size.second/2-1; | ||
501 | } | ||
502 | |||
503 | break; | ||
504 | } | ||
505 | } | ||
506 | } else if (fixed_y > fixed_oy) | ||
507 | { | ||
508 | for (auto it=down_collisions.begin(); it!=down_collisions.end(); it++) | ||
509 | { | ||
510 | if (it->axis < fixed_oy+physics.size.second) continue; | ||
511 | if (it->axis > fixed_y+physics.size.second) break; | ||
512 | |||
513 | if ((fixed_x+physics.size.first > it->lower) && (fixed_x < it->upper)) | ||
514 | { | ||
515 | // We have a collision! | ||
516 | if (it->type == 0) | ||
517 | { | ||
518 | physics.position.second = it->axis - physics.size.second; | ||
519 | physics.velocity.second = 0; | ||
520 | //mob->onGround = true; | ||
521 | } else if (it->type == 1) | ||
522 | { | ||
523 | physics.position.second = -physics.size.second/2; | ||
524 | } else if (it->type == 3) | ||
525 | { | ||
526 | message_t msg; | ||
527 | msg.type = CM_DROP; | ||
528 | msg.dropAxis = it->axis; | ||
529 | |||
530 | player.send(msg); | ||
531 | } | ||
532 | |||
533 | break; | ||
534 | } | ||
535 | } | ||
536 | } | ||
537 | } | ||