summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/components.cpp353
-rw-r--r--src/components.h76
-rw-r--r--src/entity.cpp32
-rw-r--r--src/entity.h81
-rw-r--r--src/game.cpp135
-rw-r--r--src/game.h38
-rw-r--r--src/main.cpp10
-rw-r--r--src/map.cpp41
-rw-r--r--src/map.h14
-rw-r--r--src/renderer.cpp256
-rw-r--r--src/renderer.h44
-rw-r--r--src/world.cpp32
-rw-r--r--src/world.h27
13 files changed, 510 insertions, 629 deletions
diff --git a/src/components.cpp b/src/components.cpp index f9c7c10..369bb9e 100644 --- a/src/components.cpp +++ b/src/components.cpp
@@ -3,7 +3,7 @@
3 3
4// User movement component 4// User movement component
5 5
6void UserMovementComponent::input(int key, int action) 6void UserMovementComponent::input(Game& game, Entity& entity, int key, int action)
7{ 7{
8 if (action == GLFW_PRESS) 8 if (action == GLFW_PRESS)
9 { 9 {
@@ -11,30 +11,22 @@ void UserMovementComponent::input(int key, int action)
11 { 11 {
12 holdingLeft = true; 12 holdingLeft = true;
13 13
14 message_t msg; 14 Message msg(Message::Type::walkLeft);
15 msg.type = CM_WALK_LEFT; 15 entity.send(game, msg);
16
17 entity.send(msg);
18 } else if (key == GLFW_KEY_RIGHT) 16 } else if (key == GLFW_KEY_RIGHT)
19 { 17 {
20 holdingRight = true; 18 holdingRight = true;
21 19
22 message_t msg; 20 Message msg(Message::Type::walkRight);
23 msg.type = CM_WALK_RIGHT; 21 entity.send(game, msg);
24
25 entity.send(msg);
26 } else if (key == GLFW_KEY_UP) 22 } else if (key == GLFW_KEY_UP)
27 { 23 {
28 message_t msg; 24 Message msg(Message::Type::jump);
29 msg.type = CM_JUMP; 25 entity.send(game, msg);
30
31 entity.send(msg);
32 } else if (key == GLFW_KEY_DOWN) 26 } else if (key == GLFW_KEY_DOWN)
33 { 27 {
34 message_t msg; 28 Message msg(Message::Type::canDrop);
35 msg.type = CM_CAN_DROP; 29 entity.send(game, msg);
36
37 entity.send(msg);
38 } 30 }
39 } else if (action == GLFW_RELEASE) 31 } else if (action == GLFW_RELEASE)
40 { 32 {
@@ -44,15 +36,11 @@ void UserMovementComponent::input(int key, int action)
44 36
45 if (holdingRight) 37 if (holdingRight)
46 { 38 {
47 message_t msg; 39 Message msg(Message::Type::walkRight);
48 msg.type = CM_WALK_RIGHT; 40 entity.send(game, msg);
49
50 entity.send(msg);
51 } else { 41 } else {
52 message_t msg; 42 Message msg(Message::Type::stopWalking);
53 msg.type = CM_STOP_WALKING; 43 entity.send(game, msg);
54
55 entity.send(msg);
56 } 44 }
57 } else if (key == GLFW_KEY_RIGHT) 45 } else if (key == GLFW_KEY_RIGHT)
58 { 46 {
@@ -60,95 +48,82 @@ void UserMovementComponent::input(int key, int action)
60 48
61 if (holdingLeft) 49 if (holdingLeft)
62 { 50 {
63 message_t msg; 51 Message msg(Message::Type::walkLeft);
64 msg.type = CM_WALK_LEFT; 52 entity.send(game, msg);
65
66 entity.send(msg);
67 } else { 53 } else {
68 message_t msg; 54 Message msg(Message::Type::stopWalking);
69 msg.type = CM_STOP_WALKING; 55 entity.send(game, msg);
70
71 entity.send(msg);
72 } 56 }
73 } else if (key == GLFW_KEY_DOWN) 57 } else if (key == GLFW_KEY_DOWN)
74 { 58 {
75 message_t msg; 59 Message msg(Message::Type::cantDrop);
76 msg.type = CM_CANT_DROP; 60 entity.send(game, msg);
77
78 entity.send(msg);
79 } else if (key == GLFW_KEY_UP) 61 } else if (key == GLFW_KEY_UP)
80 { 62 {
81 message_t msg; 63 Message msg(Message::Type::stopJump);
82 msg.type = CM_STOP_JUMP; 64 entity.send(game, msg);
83
84 entity.send(msg);
85 } 65 }
86 } 66 }
87} 67}
88 68
89// Physics component 69// Physics component
90 70
91void PhysicsBodyComponent::receive(message_t msg) 71void PhysicsBodyComponent::receive(Game&, Entity&, Message& msg)
92{ 72{
93 if (msg.type == CM_WALK_LEFT) 73 if (msg.type == Message::Type::walkLeft)
94 { 74 {
95 velocity.first = -1.5; 75 velocity.first = -1.5;
96 } else if (msg.type == CM_WALK_RIGHT) 76 } else if (msg.type == Message::Type::walkRight)
97 { 77 {
98 velocity.first = 1.5; 78 velocity.first = 1.5;
99 } else if (msg.type == CM_STOP_WALKING) 79 } else if (msg.type == Message::Type::stopWalking)
100 { 80 {
101 velocity.first = 0.0; 81 velocity.first = 0.0;
82 } else if (msg.type == Message::Type::stopMovingHorizontally)
83 {
84 velocity.first = 0.0;
85 } else if (msg.type == Message::Type::stopMovingVertically)
86 {
87 velocity.second = 0.0;
102 } 88 }
103} 89}
104 90
105void PhysicsBodyComponent::tick() 91void PhysicsBodyComponent::tick(Game&, Entity& entity)
106{ 92{
107 velocity.first += accel.first; 93 velocity.first += accel.first;
108 velocity.second += accel.second; 94 velocity.second += accel.second;
109 95
110 position.first += velocity.first; 96 entity.position.first += velocity.first;
111 position.second += velocity.second; 97 entity.position.second += velocity.second;
112} 98}
113 99
114void PhysicsBodyComponent::detectCollision(Entity& player, Locatable& physics, std::pair<double, double> old_position) 100void PhysicsBodyComponent::detectCollision(Game& game, Entity& entity, Entity& collider, std::pair<double, double> old_position)
115{ 101{
116 // If already colliding, do nothing! 102 // If already colliding, do nothing!
117 if ((old_position.first + physics.size.first > this->position.first) 103 if ((old_position.first + collider.size.first > entity.position.first)
118 && (old_position.first < this->position.first + this->size.first) 104 && (old_position.first < entity.position.first + entity.size.first)
119 && (old_position.second + physics.size.second > this->position.second) 105 && (old_position.second + collider.size.second > entity.position.second)
120 && (old_position.second < this->position.second + this->size.second)) 106 && (old_position.second < entity.position.second + entity.size.second))
121 { 107 {
122 return; 108 return;
123 } 109 }
124 110
125 // If newly colliding, SHOCK AND HORROR! 111 // If newly colliding, SHOCK AND HORROR!
126 if ((physics.position.first + physics.size.first > this->position.first) 112 if ((collider.position.first + collider.size.first > entity.position.first)
127 && (physics.position.first < this->position.first + this->size.first) 113 && (collider.position.first < entity.position.first + entity.size.first)
128 && (physics.position.second + physics.size.second > this->position.second) 114 && (collider.position.second + collider.size.second > entity.position.second)
129 && (physics.position.second < this->position.second + this->size.second)) 115 && (collider.position.second < entity.position.second + entity.size.second))
130 { 116 {
131 message_t msg; 117 Message msg(Message::Type::collision);
132 msg.type = CM_COLLISION; 118 msg.collisionEntity = &collider;
133 msg.collisionEntity = &player;
134 119
135 entity.send(msg); 120 entity.send(game, msg);
136 } 121 }
137} 122}
138 123
139// Render player 124// Render player
140 125
141PlayerSpriteComponent::PlayerSpriteComponent(Entity& entity, Locatable& physics) : Component(entity), physics(physics) 126void PlayerSpriteComponent::render(Game&, Entity& entity, Texture& buffer)
142{
143 sprite = loadTextureFromFile("../res/Starla.png");
144}
145
146PlayerSpriteComponent::~PlayerSpriteComponent()
147{
148 destroyTexture(sprite);
149}
150
151void PlayerSpriteComponent::render(Texture* buffer)
152{ 127{
153 int frame = 0; 128 int frame = 0;
154 if (isMoving) 129 if (isMoving)
@@ -162,28 +137,28 @@ void PlayerSpriteComponent::render(Texture* buffer)
162 } 137 }
163 if (facingLeft) frame++; 138 if (facingLeft) frame++;
164 139
165 Rectangle src_rect(frame*10, 0, 10, 12); 140 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); 141 Rectangle dst_rect {(int) entity.position.first, (int) entity.position.second, entity.size.first, entity.size.second};
167 blitTexture(sprite, buffer, &src_rect, &dst_rect); 142 buffer.blit(sprite, src_rect, dst_rect);
168} 143}
169 144
170void PlayerSpriteComponent::receive(message_t msg) 145void PlayerSpriteComponent::receive(Game&, Entity&, Message& msg)
171{ 146{
172 if (msg.type == CM_WALK_LEFT) 147 if (msg.type == Message::Type::walkLeft)
173 { 148 {
174 facingLeft = true; 149 facingLeft = true;
175 isMoving = true; 150 isMoving = true;
176 } else if (msg.type == CM_WALK_RIGHT) 151 } else if (msg.type == Message::Type::walkRight)
177 { 152 {
178 facingLeft = false; 153 facingLeft = false;
179 isMoving = true; 154 isMoving = true;
180 } else if (msg.type == CM_STOP_WALKING) 155 } else if (msg.type == Message::Type::stopWalking)
181 { 156 {
182 isMoving = false; 157 isMoving = false;
183 } 158 }
184} 159}
185 160
186void PlayerSpriteComponent::tick() 161void PlayerSpriteComponent::tick(Game&, Entity&)
187{ 162{
188 animFrame++; 163 animFrame++;
189 animFrame %= 20; 164 animFrame %= 20;
@@ -194,7 +169,7 @@ void PlayerSpriteComponent::tick()
194#define JUMP_VELOCITY(h, l) (-2 * (h) / (l)) 169#define JUMP_VELOCITY(h, l) (-2 * (h) / (l))
195#define JUMP_GRAVITY(h, l) (2 * ((h) / (l)) / (l)) 170#define JUMP_GRAVITY(h, l) (2 * ((h) / (l)) / (l))
196 171
197PlayerPhysicsComponent::PlayerPhysicsComponent(Entity& entity) : Component(entity) 172PlayerPhysicsComponent::PlayerPhysicsComponent()
198{ 173{
199 jump_velocity = JUMP_VELOCITY(TILE_HEIGHT*4.5, 0.3*FRAMES_PER_SECOND); 174 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); 175 jump_gravity = JUMP_GRAVITY(TILE_HEIGHT*4.5, 0.3*FRAMES_PER_SECOND);
@@ -203,46 +178,52 @@ PlayerPhysicsComponent::PlayerPhysicsComponent(Entity& entity) : Component(entit
203 accel.second = jump_gravity_short; 178 accel.second = jump_gravity_short;
204} 179}
205 180
206void PlayerPhysicsComponent::receive(message_t msg) 181void PlayerPhysicsComponent::receive(Game&, Entity& entity, Message& msg)
207{ 182{
208 if (msg.type == CM_WALK_LEFT) 183 if (msg.type == Message::Type::walkLeft)
209 { 184 {
210 velocity.first = -1.5; 185 velocity.first = -1.5;
211 direction = -1; 186 direction = -1;
212 } else if (msg.type == CM_WALK_RIGHT) 187 } else if (msg.type == Message::Type::walkRight)
213 { 188 {
214 velocity.first = 1.5; 189 velocity.first = 1.5;
215 direction = 1; 190 direction = 1;
216 } else if (msg.type == CM_STOP_WALKING) 191 } else if (msg.type == Message::Type::stopWalking)
217 { 192 {
218 velocity.first = 0.0; 193 velocity.first = 0.0;
219 direction = 0; 194 direction = 0;
220 } else if (msg.type == CM_JUMP) 195 } else if (msg.type == Message::Type::stopMovingHorizontally)
196 {
197 velocity.first = 0.0;
198 } else if (msg.type == Message::Type::stopMovingVertically)
199 {
200 velocity.second = 0.0;
201 } else if (msg.type == Message::Type::jump)
221 { 202 {
222 velocity.second = jump_velocity; 203 velocity.second = jump_velocity;
223 accel.second = jump_gravity; 204 accel.second = jump_gravity;
224 } else if (msg.type == CM_STOP_JUMP) 205 } else if (msg.type == Message::Type::stopJump)
225 { 206 {
226 accel.second = jump_gravity_short; 207 accel.second = jump_gravity_short;
227 } else if (msg.type == CM_CAN_DROP) 208 } else if (msg.type == Message::Type::canDrop)
228 { 209 {
229 canDrop = true; 210 canDrop = true;
230 } else if (msg.type == CM_CANT_DROP) 211 } else if (msg.type == Message::Type::cantDrop)
231 { 212 {
232 canDrop = false; 213 canDrop = false;
233 } else if (msg.type == CM_DROP) 214 } else if (msg.type == Message::Type::drop)
234 { 215 {
235 if (canDrop) 216 if (canDrop)
236 { 217 {
237 canDrop = false; 218 canDrop = false;
238 } else { 219 } else {
239 position.second = msg.dropAxis - size.second; 220 entity.position.second = msg.dropAxis - entity.size.second;
240 velocity.second = 0; 221 velocity.second = 0;
241 } 222 }
242 } 223 }
243} 224}
244 225
245void PlayerPhysicsComponent::tick() 226void PlayerPhysicsComponent::tick(Game& game, Entity& entity)
246{ 227{
247 // Continue walking even if blocked earlier 228 // Continue walking even if blocked earlier
248 if (velocity.first == 0) 229 if (velocity.first == 0)
@@ -273,80 +254,67 @@ void PlayerPhysicsComponent::tick()
273 if (velocity.second > 16) velocity.second = 16; 254 if (velocity.second > 16) velocity.second = 16;
274 255
275 // Do the movement 256 // Do the movement
276 std::pair<double, double> old_position = std::make_pair(position.first, position.second); 257 std::pair<double, double> old_position = entity.position;
277 position.first += velocity.first; 258 entity.position.first += velocity.first;
278 position.second += velocity.second; 259 entity.position.second += velocity.second;
279 260
280 // Check for collisions 261 // Check for collisions
281 for (auto it = entity.world->bodies.begin(); it != entity.world->bodies.end(); it++) 262 game.detectCollision(entity, old_position);
282 {
283 auto poop = *it;
284 poop->detectCollision(entity, *this, old_position);
285 }
286} 263}
287 264
288// Map rendering 265// Map rendering
289 266
290MapRenderComponent::MapRenderComponent(Entity& entity, Map* map) : Component(entity) 267MapRenderComponent::MapRenderComponent(Map& map)
291{ 268{
292 screen = createTexture(GAME_WIDTH, GAME_HEIGHT); 269 screen.fill(screen.entirety(), 0, 0, 0);
293 fillTexture(screen, NULL, 0, 0, 0);
294 270
295 Texture* tiles = loadTextureFromFile("../res/tiles.png"); 271 Texture tiles("../res/tiles.png");
296 272
297 for (int i=0; i<MAP_WIDTH*(MAP_HEIGHT-1); i++) 273 for (int i=0; i<MAP_WIDTH*(MAP_HEIGHT-1); i++)
298 { 274 {
299 int tile = map->mapdata()[i]; 275 int tile = map.mapdata()[i];
300 int x = i % MAP_WIDTH; 276 int x = i % MAP_WIDTH;
301 int y = i / MAP_WIDTH; 277 int y = i / MAP_WIDTH;
302 Rectangle dst(x*TILE_WIDTH, y*TILE_HEIGHT, TILE_WIDTH, TILE_HEIGHT); 278 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); 279 Rectangle src {tile%8*TILE_WIDTH, tile/8*TILE_HEIGHT, TILE_WIDTH, TILE_HEIGHT};
304 280
305 if (tile > 0) 281 if (tile > 0)
306 { 282 {
307 blitTexture(tiles, screen, &src, &dst); 283 screen.blit(tiles, src, dst);
308 } 284 }
309 } 285 }
310 286
311 destroyTexture(tiles); 287 Texture font("../res/font.bmp");
312 288 const char* map_name = map.title();
313 Texture* font = loadTextureFromFile("../res/font.bmp");
314 const char* map_name = map->title();
315 int start_x = (40/2) - (strlen(map_name)/2); 289 int start_x = (40/2) - (strlen(map_name)/2);
316 for (size_t i=0; i<strlen(map_name); i++) 290 for (size_t i=0; i<strlen(map_name); i++)
317 { 291 {
318 Rectangle srcRect(map_name[i] % 16 * 8, map_name[i] / 16 * 8, 8, 8); 292 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); 293 Rectangle dstRect {(start_x + (int)i)*8, 24*8, 8, 8};
320 blitTexture(font, screen, &srcRect, &dstRect); 294 screen.blit(font, srcRect, dstRect);
321 } 295 }
322
323 destroyTexture(font);
324} 296}
325 297
326MapRenderComponent::~MapRenderComponent() 298void MapRenderComponent::render(Game&, Entity&, Texture& buffer)
327{ 299{
328 destroyTexture(screen); 300 buffer.blit(screen, screen.entirety(), buffer.entirety());
329}
330
331void MapRenderComponent::render(Texture* buffer)
332{
333 blitTexture(screen, buffer, NULL, NULL);
334} 301}
335 302
336// Map collision 303// Map collision
337 304
338MapCollisionComponent::MapCollisionComponent(Entity& entity, Map* map) : Component(entity) 305MapCollisionComponent::MapCollisionComponent(Map& map)
339{ 306{
340 this->map = map; 307 leftMap = map.getLeftMap();
308 rightMap = map.getRightMap();
341 309
342 add_collision(-6, 0, GAME_WIDTH, left, (map->getLeftMap() == NULL) ? 1 : 2); 310 add_collision(-6, 0, GAME_WIDTH, left, (map.getLeftMap() == nullptr) ? 1 : 2);
343 add_collision(GAME_WIDTH+6, 0, GAME_WIDTH, right, (map->getRightMap() == NULL) ? 3 : 2); 311 add_collision(GAME_WIDTH+6, 0, GAME_WIDTH, right, (map.getRightMap() == nullptr) ? 3 : 2);
344 312
345 for (int i=0; i<MAP_WIDTH*(MAP_HEIGHT-1); i++) 313 for (int i=0; i<MAP_WIDTH*(MAP_HEIGHT-1); i++)
346 { 314 {
347 int x = i % MAP_WIDTH; 315 int x = i % MAP_WIDTH;
348 int y = i / MAP_WIDTH; 316 int y = i / MAP_WIDTH;
349 int tile = map->mapdata()[i]; 317 int tile = map.mapdata()[i];
350 318
351 if ((tile > 0) && (!((tile >= 5) && (tile <= 7)))) 319 if ((tile > 0) && (!((tile >= 5) && (tile <= 7))))
352 { 320 {
@@ -410,34 +378,36 @@ void MapCollisionComponent::add_collision(int axis, int lower, int upper, direct
410 } 378 }
411} 379}
412 380
413void MapCollisionComponent::detectCollision(Entity& player, Locatable& physics, std::pair<double, double> old_position) 381void MapCollisionComponent::detectCollision(Game& game, Entity&, Entity& collider, std::pair<double, double> old_position)
414{ 382{
415 int fixed_x = (int) physics.position.first; 383 int fixed_x = (int) collider.position.first;
416 int fixed_y = (int) physics.position.second; 384 int fixed_y = (int) collider.position.second;
417 int fixed_ox = (int) old_position.first; 385 int fixed_ox = (int) old_position.first;
418 int fixed_oy = (int) old_position.second; 386 int fixed_oy = (int) old_position.second;
419 387
420 if (fixed_x < fixed_ox) 388 if (fixed_x < fixed_ox)
421 { 389 {
422 for (auto it=left_collisions.begin(); it!=left_collisions.end(); it++) 390 for (auto collision : left_collisions)
423 { 391 {
424 if (it->axis > fixed_ox) continue; 392 if (collision.axis > fixed_ox) continue;
425 if (it->axis < fixed_x) break; 393 if (collision.axis < fixed_x) break;
426 394
427 if ((fixed_oy+physics.size.second > it->lower) && (fixed_oy < it->upper)) 395 if ((fixed_oy+collider.size.second > collision.lower) && (fixed_oy < collision.upper))
428 { 396 {
429 // We have a collision! 397 // We have a collision!
430 if (it->type == 0) 398 if (collision.type == 0)
431 { 399 {
432 physics.position.first = it->axis; 400 collider.position.first = collision.axis;
433 physics.velocity.first = 0; 401
434 } else if (it->type == 1) 402 Message msg(Message::Type::stopMovingHorizontally);
403 collider.send(game, msg);
404 } else if (collision.type == 1)
435 { 405 {
436 physics.position.first = GAME_WIDTH-physics.size.first/2; 406 collider.position.first = GAME_WIDTH-collider.size.first/2;
437 } else if (it->type == 2) 407 } else if (collision.type == 2)
438 { 408 {
439 physics.position.first = GAME_WIDTH-physics.size.first/2; 409 collider.position.first = GAME_WIDTH-collider.size.first/2;
440 Game::getInstance().loadMap(map->getLeftMap()); 410 game.loadMap(*leftMap);
441 } 411 }
442 412
443 break; 413 break;
@@ -445,32 +415,33 @@ void MapCollisionComponent::detectCollision(Entity& player, Locatable& physics,
445 } 415 }
446 } else if (fixed_x > fixed_ox) 416 } else if (fixed_x > fixed_ox)
447 { 417 {
448 for (auto it=right_collisions.begin(); it!=right_collisions.end(); it++) 418 for (auto collision : right_collisions)
449 { 419 {
450 if (it->axis < fixed_ox+physics.size.first) continue; 420 if (collision.axis < fixed_ox+collider.size.first) continue;
451 if (it->axis > fixed_x+physics.size.first) break; 421 if (collision.axis > fixed_x+collider.size.first) break;
452 422
453 if ((fixed_oy+physics.size.second > it->lower) && (fixed_oy < it->upper)) 423 if ((fixed_oy+collider.size.second > collision.lower) && (fixed_oy < collision.upper))
454 { 424 {
455 // We have a collision! 425 // We have a collision!
456 if (it->type == 0) 426 if (collision.type == 0)
457 { 427 {
458 physics.position.first = it->axis - physics.size.first; 428 collider.position.first = collision.axis - collider.size.first;
459 physics.velocity.first = 0; 429
460 } else if (it->type == 1) 430 Message msg(Message::Type::stopMovingHorizontally);
431 collider.send(game, msg);
432 } else if (collision.type == 1)
461 { 433 {
462 physics.position.first = -physics.size.first/2; 434 collider.position.first = -collider.size.first/2;
463 } else if (it->type == 2) 435 } else if (collision.type == 2)
464 { 436 {
465 physics.position.first = -physics.size.first/2; 437 collider.position.first = -collider.size.first/2;
466 Game::getInstance().loadMap(map->getRightMap()); 438 game.loadMap(*rightMap);
467 } else if (it->type == 3) 439 } else if (collision.type == 3)
468 { 440 {
469 physics.position.first = it->axis - physics.size.first; 441 collider.position.first = collision.axis - collider.size.first;
470 442
471 message_t msg; 443 Message msg(Message::Type::walkLeft);
472 msg.type = CM_WALK_LEFT; 444 collider.send(game, msg);
473 player.send(msg);
474 } 445 }
475 446
476 break; 447 break;
@@ -478,26 +449,28 @@ void MapCollisionComponent::detectCollision(Entity& player, Locatable& physics,
478 } 449 }
479 } 450 }
480 451
481 fixed_x = (int) physics.position.first; 452 fixed_x = (int) collider.position.first;
482 fixed_y = (int) physics.position.second; 453 fixed_y = (int) collider.position.second;
483 454
484 if (fixed_y < fixed_oy) 455 if (fixed_y < fixed_oy)
485 { 456 {
486 for (auto it=up_collisions.begin(); it!=up_collisions.end(); it++) 457 for (auto collision : up_collisions)
487 { 458 {
488 if (it->axis > fixed_oy) continue; 459 if (collision.axis > fixed_oy) continue;
489 if (it->axis < fixed_y) break; 460 if (collision.axis < fixed_y) break;
490 461
491 if ((fixed_x+physics.size.first > it->lower) && (fixed_x < it->upper)) 462 if ((fixed_x+collider.size.first > collision.lower) && (fixed_x < collision.upper))
492 { 463 {
493 // We have a collision! 464 // We have a collision!
494 if (it->type == 0) 465 if (collision.type == 0)
495 { 466 {
496 physics.position.second = it->axis; 467 collider.position.second = collision.axis;
497 physics.velocity.second = 0; 468
498 } else if (it->type == 1) 469 Message msg(Message::Type::stopMovingVertically);
470 collider.send(game, msg);
471 } else if (collision.type == 1)
499 { 472 {
500 physics.position.second = GAME_HEIGHT-physics.size.second/2-1; 473 collider.position.second = GAME_HEIGHT-collider.size.second/2-1;
501 } 474 }
502 475
503 break; 476 break;
@@ -505,29 +478,29 @@ void MapCollisionComponent::detectCollision(Entity& player, Locatable& physics,
505 } 478 }
506 } else if (fixed_y > fixed_oy) 479 } else if (fixed_y > fixed_oy)
507 { 480 {
508 for (auto it=down_collisions.begin(); it!=down_collisions.end(); it++) 481 for (auto collision : down_collisions)
509 { 482 {
510 if (it->axis < fixed_oy+physics.size.second) continue; 483 if (collision.axis < fixed_oy+collider.size.second) continue;
511 if (it->axis > fixed_y+physics.size.second) break; 484 if (collision.axis > fixed_y+collider.size.second) break;
512 485
513 if ((fixed_x+physics.size.first > it->lower) && (fixed_x < it->upper)) 486 if ((fixed_x+collider.size.first > collision.lower) && (fixed_x < collision.upper))
514 { 487 {
515 // We have a collision! 488 // We have a collision!
516 if (it->type == 0) 489 if (collision.type == 0)
517 { 490 {
518 physics.position.second = it->axis - physics.size.second; 491 collider.position.second = collision.axis - collider.size.second;
519 physics.velocity.second = 0; 492
520 //mob->onGround = true; 493 Message msg(Message::Type::stopMovingVertically);
521 } else if (it->type == 1) 494 collider.send(game, msg);
495 } else if (collision.type == 1)
522 { 496 {
523 physics.position.second = -physics.size.second/2; 497 collider.position.second = -collider.size.second/2;
524 } else if (it->type == 3) 498 } else if (collision.type == 3)
525 { 499 {
526 message_t msg; 500 Message msg(Message::Type::drop);
527 msg.type = CM_DROP; 501 msg.dropAxis = collision.axis;
528 msg.dropAxis = it->axis; 502
529 503 collider.send(game, msg);
530 player.send(msg);
531 } 504 }
532 505
533 break; 506 break;
diff --git a/src/components.h b/src/components.h index 687eab1..f9b6e1e 100644 --- a/src/components.h +++ b/src/components.h
@@ -5,48 +5,50 @@
5#include <utility> 5#include <utility>
6#include <list> 6#include <list>
7#include "map.h" 7#include "map.h"
8#include <memory>
8 9
9class UserMovementComponent : public Component { 10class UserMovementComponent : public Component {
10 public: 11 public:
11 UserMovementComponent(Entity& parent) : Component(parent) {}; 12 void input(Game& game, Entity& entity, int key, int action);
12 void input(int key, int action);
13 13
14 private: 14 private:
15 bool holdingLeft = false; 15 bool holdingLeft = false;
16 bool holdingRight = false; 16 bool holdingRight = false;
17}; 17};
18 18
19class PhysicsBodyComponent : public Component, public Collidable, public Locatable { 19class PhysicsBodyComponent : public Component {
20 public: 20 public:
21 PhysicsBodyComponent(Entity& parent) : Component(parent) {}; 21 void receive(Game& game, Entity& entity, Message& msg);
22 void receive(message_t msg); 22 void tick(Game& game, Entity& entity);
23 void tick(); 23 void detectCollision(Game& game, Entity& entity, Entity& collider, std::pair<double, double> old_position);
24 void detectCollision(Entity& player, Locatable& physics, std::pair<double, double> old_position); 24
25 private:
26 std::pair<double, double> velocity;
27 std::pair<double, double> accel;
25}; 28};
26 29
27class PlayerSpriteComponent : public Component { 30class PlayerSpriteComponent : public Component {
28 public: 31 public:
29 PlayerSpriteComponent(Entity& parent, Locatable& physics); 32 void render(Game& game, Entity& entity, Texture& buffer);
30 ~PlayerSpriteComponent(); 33 void receive(Game& game, Entity& entity, Message& msg);
31 void render(Texture* buffer); 34 void tick(Game& game, Entity& entity);
32 void receive(message_t msg);
33 void tick();
34 35
35 private: 36 private:
36 Locatable& physics; 37 Texture sprite{"../res/Starla.png"};
37 Texture* sprite;
38 int animFrame = 0; 38 int animFrame = 0;
39 bool facingLeft = false; 39 bool facingLeft = false;
40 bool isMoving = false; 40 bool isMoving = false;
41}; 41};
42 42
43class PlayerPhysicsComponent : public Component, public Locatable { 43class PlayerPhysicsComponent : public Component {
44 public: 44 public:
45 PlayerPhysicsComponent(Entity& parent); 45 PlayerPhysicsComponent();
46 void tick(); 46 void tick(Game& game, Entity& entity);
47 void receive(message_t msg); 47 void receive(Game& game, Entity& entity, Message& msg);
48 48
49 private: 49 private:
50 std::pair<double, double> velocity;
51 std::pair<double, double> accel;
50 double jump_velocity; 52 double jump_velocity;
51 double jump_gravity; 53 double jump_gravity;
52 double jump_gravity_short; 54 double jump_gravity_short;
@@ -56,38 +58,38 @@ class PlayerPhysicsComponent : public Component, public Locatable {
56 58
57class MapRenderComponent : public Component { 59class MapRenderComponent : public Component {
58 public: 60 public:
59 MapRenderComponent(Entity& parent, Map* map); 61 MapRenderComponent(Map& map);
60 ~MapRenderComponent(); 62 void render(Game& game, Entity& entity, Texture& buffer);
61 void render(Texture* buffer);
62 63
63 private: 64 private:
64 Texture* screen; 65 Texture screen{GAME_WIDTH, GAME_HEIGHT};
65};
66
67enum direction_t {
68 up, left, down, right
69}; 66};
70 67
71typedef struct { 68class MapCollisionComponent : public Component {
72 int axis;
73 int lower;
74 int upper;
75 int type;
76} collision_t;
77
78class MapCollisionComponent : public Component, public Collidable {
79 public: 69 public:
80 MapCollisionComponent(Entity& parent, Map* map); 70 MapCollisionComponent(Map& map);
81 void detectCollision(Entity& player, Locatable& physics, std::pair<double, double> old_position); 71 void detectCollision(Game& game, Entity& entity, Entity& collider, std::pair<double, double> old_position);
82 72
83 private: 73 private:
74 enum direction_t {
75 up, left, down, right
76 };
77
78 typedef struct {
79 int axis;
80 int lower;
81 int upper;
82 int type;
83 } collision_t;
84
84 void add_collision(int axis, int lower, int upper, direction_t dir, int type); 85 void add_collision(int axis, int lower, int upper, direction_t dir, int type);
85 86
86 std::list<collision_t> left_collisions; 87 std::list<collision_t> left_collisions;
87 std::list<collision_t> right_collisions; 88 std::list<collision_t> right_collisions;
88 std::list<collision_t> up_collisions; 89 std::list<collision_t> up_collisions;
89 std::list<collision_t> down_collisions; 90 std::list<collision_t> down_collisions;
90 Map* map; 91 Map* leftMap;
92 Map* rightMap;
91}; 93};
92 94
93#endif 95#endif
diff --git a/src/entity.cpp b/src/entity.cpp index 405de24..950969e 100644 --- a/src/entity.cpp +++ b/src/entity.cpp
@@ -5,34 +5,42 @@ void Entity::addComponent(std::shared_ptr<Component> c)
5 components.push_back(c); 5 components.push_back(c);
6} 6}
7 7
8void Entity::send(message_t msg) 8void Entity::send(Game& game, Message& msg)
9{ 9{
10 for (auto it = components.begin(); it != components.end(); it++) 10 for (auto component : components)
11 { 11 {
12 (*it)->receive(msg); 12 component->receive(game, *this, msg);
13 } 13 }
14} 14}
15 15
16void Entity::tick() 16void Entity::tick(Game& game)
17{ 17{
18 for (auto it = components.begin(); it != components.end(); it++) 18 for (auto component : components)
19 { 19 {
20 (*it)->tick(); 20 component->tick(game, *this);
21 } 21 }
22} 22}
23 23
24void Entity::input(int key, int action) 24void Entity::input(Game& game, int key, int action)
25{ 25{
26 for (auto it = components.begin(); it != components.end(); it++) 26 for (auto component : components)
27 { 27 {
28 (*it)->input(key, action); 28 component->input(game, *this, key, action);
29 } 29 }
30} 30}
31 31
32void Entity::render(Texture* buffer) 32void Entity::render(Game& game, Texture& buffer)
33{ 33{
34 for (auto it = components.begin(); it != components.end(); it++) 34 for (auto component : components)
35 { 35 {
36 (*it)->render(buffer); 36 component->render(game, *this, buffer);
37 }
38}
39
40void Entity::detectCollision(Game& game, Entity& collider, std::pair<double, double> old_position)
41{
42 for (auto component : components)
43 {
44 component->detectCollision(game, *this, collider, old_position);
37 } 45 }
38} 46}
diff --git a/src/entity.h b/src/entity.h index 5a37147..803a9b8 100644 --- a/src/entity.h +++ b/src/entity.h
@@ -3,42 +3,45 @@
3 3
4class Entity; 4class Entity;
5class Component; 5class Component;
6class Locatable;
7class Collidable;
8 6
9#include <list> 7#include <list>
10#include "renderer.h" 8#include "renderer.h"
11#include "world.h" 9#include "game.h"
12 10
13enum message_type { 11class Message {
14 CM_WALK_LEFT, 12 public:
15 CM_WALK_RIGHT, 13 enum class Type {
16 CM_STOP_WALKING, 14 walkLeft,
17 CM_COLLISION, 15 walkRight,
18 CM_JUMP, 16 stopWalking,
19 CM_STOP_JUMP, 17 stopMovingHorizontally,
20 CM_DROP, 18 stopMovingVertically,
21 CM_CAN_DROP, 19 collision,
22 CM_CANT_DROP 20 jump,
21 stopJump,
22 drop,
23 canDrop,
24 cantDrop
25 };
26
27 Message(Type type) : type(type) {}
28
29 Type type;
30 Entity* collisionEntity;
31 int dropAxis;
23}; 32};
24 33
25typedef struct {
26 message_type type;
27 Entity* collisionEntity;
28 int dropAxis;
29} message_t;
30
31class Entity { 34class Entity {
32 public: 35 public:
33 Entity(World* world) : world(world) {}
34 ~Entity() {};
35 void addComponent(std::shared_ptr<Component> c); 36 void addComponent(std::shared_ptr<Component> c);
36 void send(message_t msg); 37 void send(Game& game, Message& msg);
37 void tick(); 38 void tick(Game& game);
38 void input(int key, int action); 39 void input(Game& game, int key, int action);
39 void render(Texture* buffer); 40 void render(Game& game, Texture& buffer);
41 void detectCollision(Game& game, Entity& collider, std::pair<double, double> old_position);
40 42
41 World* world; 43 std::pair<double, double> position;
44 std::pair<int, int> size;
42 45
43 private: 46 private:
44 std::list<std::shared_ptr<Component>> components; 47 std::list<std::shared_ptr<Component>> components;
@@ -46,27 +49,11 @@ class Entity {
46 49
47class Component { 50class Component {
48 public: 51 public:
49 Component(Entity& entity) : entity(entity) {} 52 virtual void receive(Game&, Entity&, Message&) {}
50 virtual ~Component() {}; 53 virtual void render(Game&, Entity&, Texture&) {}
51 virtual void receive(message_t msg) {(void)msg;} 54 virtual void tick(Game&, Entity&) {}
52 virtual void render(Texture* tex) {(void)tex;} 55 virtual void input(Game&, Entity&, int, int) {}
53 virtual void tick() {} 56 virtual void detectCollision(Game&, Entity&, Entity&, std::pair<double, double>) {}
54 virtual void input(int key, int action) {(void)key; (void)action;}
55
56 Entity& entity;
57};
58
59class Locatable {
60 public:
61 std::pair<double, double> position;
62 std::pair<int, int> size;
63 std::pair<double, double> velocity;
64 std::pair<double, double> accel;
65};
66
67class Collidable {
68 public:
69 virtual void detectCollision(Entity& player, Locatable& physics, std::pair<double, double> old_position) = 0;
70}; 57};
71 58
72#endif 59#endif
diff --git a/src/game.cpp b/src/game.cpp index 2db0a2c..cbbae06 100644 --- a/src/game.cpp +++ b/src/game.cpp
@@ -1,124 +1,113 @@
1#include "game.h" 1#include "game.h"
2#include "renderer.h" 2#include "renderer.h"
3#include "components.h"
3 4
4Game::Game() 5Game::Game()
5{ 6{
6 window = initRenderer(); 7 m.setLeftMap(&m2);
7 glfwSwapInterval(1); 8 m2.setRightMap(&m);
8
9 m = new Map("../maps/embarass.txt");
10 m2 = new Map("../maps/second.txt");
11
12 m->setLeftMap(m2);
13 m2->setRightMap(m);
14
15 world = new World();
16 9
17 auto player = std::make_shared<Entity>(world); 10 player = std::make_shared<Entity>();
11 player->position = std::make_pair(100.0,100.0);
12 player->size = std::make_pair(10.0,12.0);
18 13
19 auto player_input = std::make_shared<UserMovementComponent>(*player); 14 auto player_input = std::make_shared<UserMovementComponent>();
20 player->addComponent(player_input); 15 player->addComponent(player_input);
21 16
22 auto player_physics = std::make_shared<PlayerPhysicsComponent>(*player); 17 auto player_physics = std::make_shared<PlayerPhysicsComponent>();
23 player_physics->position = std::make_pair(100.0,100.0);
24 player_physics->size = std::make_pair(10.0,12.0);
25 player->addComponent(player_physics); 18 player->addComponent(player_physics);
26 19
27 auto player_anim = std::make_shared<PlayerSpriteComponent>(*player, *player_physics); 20 auto player_anim = std::make_shared<PlayerSpriteComponent>();
28 player->addComponent(player_anim); 21 player->addComponent(player_anim);
29 22
30 world->addEntity(player);
31 world->player = player;
32
33 loadMap(m); 23 loadMap(m);
34} 24}
35 25
36Game::~Game() 26void key_callback(GLFWwindow* window, int key, int, int action, int)
37{ 27{
38 if (world != 0) 28 Game* game = (Game*) glfwGetWindowUserPointer(window);
39 {
40 delete world;
41 }
42 29
43 if (nextWorld != 0) 30 if ((key == GLFW_KEY_ESCAPE) && (action == GLFW_PRESS))
44 { 31 {
45 delete nextWorld; 32 game->shouldQuit = true;
46 } 33 }
47 34
48 delete m; 35 for (auto entity : game->entities)
49 delete m2;
50
51 destroyRenderer();
52}
53
54void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
55{
56 (void)window;
57 (void)scancode;
58 (void)mods;
59
60 if ((key == GLFW_KEY_ESCAPE) && (action == GLFW_PRESS))
61 { 36 {
62 Game::getInstance().shouldQuit = true; 37 entity->input(*game, key, action);
63 } 38 }
64
65 Game::getInstance().input(key, action);
66} 39}
67 40
68void Game::execute() 41void Game::execute(GLFWwindow* window)
69{ 42{
43 glfwSwapInterval(1);
44 glfwSetWindowUserPointer(window, this);
70 glfwSetKeyCallback(window, key_callback); 45 glfwSetKeyCallback(window, key_callback);
71 46
72 Texture* buffer = createTexture(GAME_WIDTH, GAME_HEIGHT); 47 Texture buffer(GAME_WIDTH, GAME_HEIGHT);
73 48
49 double lastTime = glfwGetTime();
50 int nbFrames = 0;
74 while (!(shouldQuit || glfwWindowShouldClose(window))) 51 while (!(shouldQuit || glfwWindowShouldClose(window)))
75 { 52 {
53 double currentTime = glfwGetTime();
54 nbFrames++;
55 if (currentTime - lastTime >= 1.0)
56 {
57 printf("%f ms/frame\n", 1000.0/double(nbFrames));
58 nbFrames = 0;
59 lastTime += 1.0;
60 }
61
76 // Should we load a new world? 62 // Should we load a new world?
77 if (nextWorld != 0) 63 if (newWorld)
78 { 64 {
79 delete world; 65 newWorld = false;
80 world = nextWorld; 66 entities.clear();
81 world->player->world = world; 67 entities = std::move(nextEntities);
82 nextWorld = 0;
83 } 68 }
84 69
85 // Handle input 70 // Handle input
86 glfwPollEvents(); 71 glfwPollEvents();
87 72
88 // Tick! 73 // Tick!
89 world->tick(); 74 for (auto entity : entities)
75 {
76 entity->tick(*this);
77 }
90 78
91 // Do rendering 79 // Do rendering
92 world->render(buffer); 80 buffer.fill(buffer.entirety(), 0, 0, 0);
93 renderScreen(buffer); 81 for (auto entity : entities)
94 } 82 {
95 83 entity->render(*this, buffer);
96 destroyTexture(buffer); 84 }
97}
98 85
99void Game::input(int key, int action) 86 buffer.renderScreen();
100{
101 if (world != NULL)
102 {
103 world->input(key, action);
104 } 87 }
105} 88}
106 89
107void Game::loadMap(Map* map) 90void Game::loadMap(Map& map)
108{ 91{
109 nextWorld = new World(); 92 auto mapEn = std::make_shared<Entity>();
110
111 nextWorld->player = world->player;
112
113 auto mapEn = std::make_shared<Entity>(nextWorld);
114 93
115 auto map_render = std::make_shared<MapRenderComponent>(*mapEn, map); 94 auto map_render = std::make_shared<MapRenderComponent>(map);
116 mapEn->addComponent(map_render); 95 mapEn->addComponent(map_render);
117 96
118 auto map_collision = std::make_shared<MapCollisionComponent>(*mapEn, map); 97 auto map_collision = std::make_shared<MapCollisionComponent>(map);
119 mapEn->addComponent(map_collision); 98 mapEn->addComponent(map_collision);
120 nextWorld->bodies.push_back(map_collision.get());
121 99
122 nextWorld->addEntity(mapEn); 100 nextEntities.clear();
123 nextWorld->addEntity(nextWorld->player); 101 nextEntities.push_back(mapEn);
102 nextEntities.push_back(player);
103
104 newWorld = true;
105}
106
107void Game::detectCollision(Entity& collider, std::pair<double, double> old_position)
108{
109 for (auto entity : entities)
110 {
111 entity->detectCollision(*this, collider, old_position);
112 }
124} 113}
diff --git a/src/game.h b/src/game.h index 69224dc..c419c5d 100644 --- a/src/game.h +++ b/src/game.h
@@ -1,7 +1,11 @@
1#ifndef GAME_H 1#ifndef GAME_H
2#define GAME_H 2#define GAME_H
3 3
4#include "components.h" 4class Game;
5
6#include "map.h"
7#include <memory>
8#include "entity.h"
5 9
6const int TILE_WIDTH = 8; 10const int TILE_WIDTH = 8;
7const int TILE_HEIGHT = 8; 11const int TILE_HEIGHT = 8;
@@ -15,29 +19,21 @@ const double SECONDS_PER_FRAME = 1.0 / FRAMES_PER_SECOND;
15 19
16class Game { 20class Game {
17 public: 21 public:
18 static Game& getInstance() 22 Game();
19 { 23 void execute(GLFWwindow* window);
20 static Game instance; 24 void loadMap(Map& map);
21 25 void detectCollision(Entity& collider, std::pair<double, double> old_position);
22 return instance;
23 }
24
25 ~Game();
26 void execute();
27 void loadMap(Map* map);
28 void input(int key, int action);
29 26
30 bool shouldQuit = false; 27 bool shouldQuit = false;
31 private: 28 private:
32 Game(); 29 friend void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods);
33 Game(Game const&); 30
34 void operator=(Game const&); 31 std::list<std::shared_ptr<Entity>> entities;
35 32 std::list<std::shared_ptr<Entity>> nextEntities;
36 GLFWwindow* window; 33 bool newWorld;
37 World* world; 34 std::shared_ptr<Entity> player;
38 World* nextWorld; 35 Map m{"../maps/embarass.txt"};
39 Map* m; 36 Map m2{"../maps/second.txt"};
40 Map* m2;
41}; 37};
42 38
43#endif 39#endif
diff --git a/src/main.cpp b/src/main.cpp index c552d2a..e37c2dd 100644 --- a/src/main.cpp +++ b/src/main.cpp
@@ -8,7 +8,15 @@ int main()
8{ 8{
9 srand(time(NULL)); 9 srand(time(NULL));
10 10
11 Game::getInstance().execute(); 11 GLFWwindow* window = initRenderer();
12
13 // Put this in a block so game goes out of scope before we destroy the renderer
14 {
15 Game game;
16 game.execute(window);
17 }
18
19 destroyRenderer();
12 20
13 return 0; 21 return 0;
14} 22}
diff --git a/src/map.cpp b/src/map.cpp index fda8009..87080e8 100644 --- a/src/map.cpp +++ b/src/map.cpp
@@ -1,7 +1,14 @@
1#include "map.h" 1#include "map.h"
2#include "game.h" 2#include "game.h"
3#include <cstdlib>
4#include <cstring>
3 5
4Map::Map(char* filename) 6Map::Map()
7{
8
9}
10
11Map::Map(const char* filename)
5{ 12{
6 FILE* f = fopen(filename, "r"); 13 FILE* f = fopen(filename, "r");
7 14
@@ -22,12 +29,44 @@ Map::Map(char* filename)
22 fclose(f); 29 fclose(f);
23} 30}
24 31
32Map::Map(Map& map)
33{
34 m_mapdata = (int*) malloc(MAP_WIDTH*(MAP_HEIGHT-1)*sizeof(int));
35 memcpy(m_mapdata, map.m_mapdata, MAP_WIDTH*(MAP_HEIGHT-1)*sizeof(int));
36
37 m_title = (char*) malloc((MAP_WIDTH+1)*sizeof(char));
38 strncpy(m_title, map.m_title, MAP_WIDTH+1);
39
40 m_leftMap = map.m_leftMap;
41 m_rightMap = map.m_rightMap;
42}
43
44Map::Map(Map&& map) : Map()
45{
46 swap(*this, map);
47}
48
25Map::~Map() 49Map::~Map()
26{ 50{
27 free(m_mapdata); 51 free(m_mapdata);
28 free(m_title); 52 free(m_title);
29} 53}
30 54
55Map& Map::operator= (Map map)
56{
57 swap(*this, map);
58
59 return *this;
60}
61
62void swap(Map& first, Map& second)
63{
64 std::swap(first.m_mapdata, second.m_mapdata);
65 std::swap(first.m_title, second.m_title);
66 std::swap(first.m_leftMap, second.m_leftMap);
67 std::swap(first.m_rightMap, second.m_rightMap);
68}
69
31const int* Map::mapdata() 70const int* Map::mapdata()
32{ 71{
33 return m_mapdata; 72 return m_mapdata;
diff --git a/src/map.h b/src/map.h index d7b4ecf..e3d1802 100644 --- a/src/map.h +++ b/src/map.h
@@ -3,9 +3,13 @@
3 3
4class Map { 4class Map {
5 public: 5 public:
6 Map(); 6 Map(const char* filename);
7 Map(char* filename); 7 Map(Map& map);
8 Map(Map&& map);
8 ~Map(); 9 ~Map();
10 Map& operator= (Map other);
11 friend void swap(Map& first, Map& second);
12
9 const int* mapdata(); 13 const int* mapdata();
10 const char* title(); 14 const char* title();
11 Map* getLeftMap(); 15 Map* getLeftMap();
@@ -13,10 +17,12 @@ class Map {
13 void setLeftMap(Map* m); 17 void setLeftMap(Map* m);
14 void setRightMap(Map* m); 18 void setRightMap(Map* m);
15 private: 19 private:
20 Map();
21
16 int* m_mapdata; 22 int* m_mapdata;
17 char* m_title; 23 char* m_title;
18 Map* m_leftMap = 0; 24 Map* m_leftMap;
19 Map* m_rightMap = 0; 25 Map* m_rightMap;
20}; 26};
21 27
22#endif 28#endif
diff --git a/src/renderer.cpp b/src/renderer.cpp index e7db069..cf6b2bd 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp
@@ -6,6 +6,8 @@
6#include <cstring> 6#include <cstring>
7#include <cstdlib> 7#include <cstdlib>
8#include "game.h" 8#include "game.h"
9#include <glm/glm.hpp>
10#include <glm/gtc/matrix_transform.hpp>
9 11
10// include stb_image 12// include stb_image
11#define STB_IMAGE_IMPLEMENTATION 13#define STB_IMAGE_IMPLEMENTATION
@@ -86,27 +88,27 @@ GLuint LoadShaders(const char* vertex_file_path, const char* fragment_file_path)
86 // Compile Vertex Shader 88 // Compile Vertex Shader
87 printf("Compiling shader : %s\n", vertex_file_path); 89 printf("Compiling shader : %s\n", vertex_file_path);
88 char const * VertexSourcePointer = VertexShaderCode.c_str(); 90 char const * VertexSourcePointer = VertexShaderCode.c_str();
89 glShaderSource(VertexShaderID, 1, &VertexSourcePointer , NULL); 91 glShaderSource(VertexShaderID, 1, &VertexSourcePointer , nullptr);
90 glCompileShader(VertexShaderID); 92 glCompileShader(VertexShaderID);
91 93
92 // Check Vertex Shader 94 // Check Vertex Shader
93 glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result); 95 glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);
94 glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength); 96 glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
95 std::vector<char> VertexShaderErrorMessage(InfoLogLength); 97 std::vector<char> VertexShaderErrorMessage(InfoLogLength);
96 glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]); 98 glGetShaderInfoLog(VertexShaderID, InfoLogLength, nullptr, &VertexShaderErrorMessage[0]);
97 fprintf(stdout, "%s\n", &VertexShaderErrorMessage[0]); 99 fprintf(stdout, "%s\n", &VertexShaderErrorMessage[0]);
98 100
99 // Compile Fragment Shader 101 // Compile Fragment Shader
100 printf("Compiling shader : %s\n", fragment_file_path); 102 printf("Compiling shader : %s\n", fragment_file_path);
101 char const * FragmentSourcePointer = FragmentShaderCode.c_str(); 103 char const * FragmentSourcePointer = FragmentShaderCode.c_str();
102 glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer , NULL); 104 glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer , nullptr);
103 glCompileShader(FragmentShaderID); 105 glCompileShader(FragmentShaderID);
104 106
105 // Check Fragment Shader 107 // Check Fragment Shader
106 glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result); 108 glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result);
107 glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength); 109 glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
108 std::vector<char> FragmentShaderErrorMessage(InfoLogLength); 110 std::vector<char> FragmentShaderErrorMessage(InfoLogLength);
109 glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]); 111 glGetShaderInfoLog(FragmentShaderID, InfoLogLength, nullptr, &FragmentShaderErrorMessage[0]);
110 fprintf(stdout, "%s\n", &FragmentShaderErrorMessage[0]); 112 fprintf(stdout, "%s\n", &FragmentShaderErrorMessage[0]);
111 113
112 // Link the program 114 // Link the program
@@ -120,7 +122,7 @@ GLuint LoadShaders(const char* vertex_file_path, const char* fragment_file_path)
120 glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result); 122 glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
121 glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength); 123 glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
122 std::vector<char> ProgramErrorMessage( glm::max(InfoLogLength, int(1)) ); 124 std::vector<char> ProgramErrorMessage( glm::max(InfoLogLength, int(1)) );
123 glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]); 125 glGetProgramInfoLog(ProgramID, InfoLogLength, nullptr, &ProgramErrorMessage[0]);
124 fprintf(stdout, "%s\n", &ProgramErrorMessage[0]); 126 fprintf(stdout, "%s\n", &ProgramErrorMessage[0]);
125 127
126 glDeleteShader(VertexShaderID); 128 glDeleteShader(VertexShaderID);
@@ -147,7 +149,7 @@ void flipImageData(unsigned char* data, int width, int height, int comps)
147void loadMesh(const char* filename, std::vector<glm::vec3>& out_vertices, std::vector<glm::vec2>& out_uvs, std::vector<glm::vec3>& out_normals) 149void loadMesh(const char* filename, std::vector<glm::vec3>& out_vertices, std::vector<glm::vec2>& out_uvs, std::vector<glm::vec3>& out_normals)
148{ 150{
149 FILE* file = fopen(filename, "r"); 151 FILE* file = fopen(filename, "r");
150 if (file == NULL) 152 if (file == nullptr)
151 { 153 {
152 fprintf(stderr, "Could not open mesh file %s\n", filename); 154 fprintf(stderr, "Could not open mesh file %s\n", filename);
153 exit(1); 155 exit(1);
@@ -168,17 +170,17 @@ void loadMesh(const char* filename, std::vector<glm::vec3>& out_vertices, std::v
168 170
169 if (!strncmp(lineHeader, "v", 2)) 171 if (!strncmp(lineHeader, "v", 2))
170 { 172 {
171 vec3 vertex; 173 glm::vec3 vertex;
172 fscanf(file, "%f %f %f\n", &vertex.x,&vertex.y,&vertex.z); 174 fscanf(file, "%f %f %f\n", &vertex.x,&vertex.y,&vertex.z);
173 temp_vertices.push_back(vertex); 175 temp_vertices.push_back(vertex);
174 } else if (!strncmp(lineHeader, "vt", 3)) 176 } else if (!strncmp(lineHeader, "vt", 3))
175 { 177 {
176 vec2 uv; 178 glm::vec2 uv;
177 fscanf(file, "%f %f\n", &uv.x, &uv.y); 179 fscanf(file, "%f %f\n", &uv.x, &uv.y);
178 temp_uvs.push_back(uv); 180 temp_uvs.push_back(uv);
179 } else if (!strncmp(lineHeader, "vn", 3)) 181 } else if (!strncmp(lineHeader, "vn", 3))
180 { 182 {
181 vec3 normal; 183 glm::vec3 normal;
182 fscanf(file, "%f %f %f\n", &normal.x, &normal.y, &normal.z); 184 fscanf(file, "%f %f %f\n", &normal.x, &normal.y, &normal.z);
183 temp_normals.push_back(normal); 185 temp_normals.push_back(normal);
184 } else if (!strncmp(lineHeader, "f", 2)) 186 } else if (!strncmp(lineHeader, "f", 2))
@@ -265,8 +267,8 @@ GLFWwindow* initRenderer()
265 glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); 267 glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
266 268
267 // Create a window 269 // Create a window
268 window = glfwCreateWindow(1024, 768, "Aromatherapy", NULL, NULL); 270 window = glfwCreateWindow(1024, 768, "Aromatherapy", nullptr, nullptr);
269 if (window == NULL) 271 if (window == nullptr)
270 { 272 {
271 fprintf(stderr, "Failed to open GLFW window\n"); 273 fprintf(stderr, "Failed to open GLFW window\n");
272 glfwTerminate(); 274 glfwTerminate();
@@ -367,15 +369,15 @@ GLFWwindow* initRenderer()
367 369
368 glGenBuffers(1, &mesh_vertexbuffer); 370 glGenBuffers(1, &mesh_vertexbuffer);
369 glBindBuffer(GL_ARRAY_BUFFER, mesh_vertexbuffer); 371 glBindBuffer(GL_ARRAY_BUFFER, mesh_vertexbuffer);
370 glBufferData(GL_ARRAY_BUFFER, mesh_vertices.size() * sizeof(vec3), &mesh_vertices[0], GL_STATIC_DRAW); 372 glBufferData(GL_ARRAY_BUFFER, mesh_vertices.size() * sizeof(glm::vec3), &mesh_vertices[0], GL_STATIC_DRAW);
371 373
372 glGenBuffers(1, &mesh_uvbuffer); 374 glGenBuffers(1, &mesh_uvbuffer);
373 glBindBuffer(GL_ARRAY_BUFFER, mesh_uvbuffer); 375 glBindBuffer(GL_ARRAY_BUFFER, mesh_uvbuffer);
374 glBufferData(GL_ARRAY_BUFFER, mesh_uvs.size() * sizeof(vec3), &mesh_uvs[0], GL_STATIC_DRAW); 376 glBufferData(GL_ARRAY_BUFFER, mesh_uvs.size() * sizeof(glm::vec3), &mesh_uvs[0], GL_STATIC_DRAW);
375 377
376 glGenBuffers(1, &mesh_normalbuffer); 378 glGenBuffers(1, &mesh_normalbuffer);
377 glBindBuffer(GL_ARRAY_BUFFER, mesh_normalbuffer); 379 glBindBuffer(GL_ARRAY_BUFFER, mesh_normalbuffer);
378 glBufferData(GL_ARRAY_BUFFER, mesh_normals.size() * sizeof(vec3), &mesh_normals[0], GL_STATIC_DRAW); 380 glBufferData(GL_ARRAY_BUFFER, mesh_normals.size() * sizeof(glm::vec3), &mesh_normals[0], GL_STATIC_DRAW);
379 381
380 // Load the vertices of a flat surface 382 // Load the vertices of a flat surface
381 GLfloat g_quad_vertex_buffer_data[] = { 383 GLfloat g_quad_vertex_buffer_data[] = {
@@ -471,7 +473,7 @@ void destroyRenderer()
471 rendererInitialized = false; 473 rendererInitialized = false;
472} 474}
473 475
474Texture* createTexture(int width, int height) 476Texture::Texture(int width, int height)
475{ 477{
476 if (!rendererInitialized) 478 if (!rendererInitialized)
477 { 479 {
@@ -479,22 +481,19 @@ Texture* createTexture(int width, int height)
479 exit(-1); 481 exit(-1);
480 } 482 }
481 483
482 Texture* tex = new Texture(); 484 this->width = width;
483 tex->width = width; 485 this->height = height;
484 tex->height = height;
485 486
486 glGenTextures(1, &(tex->texID)); 487 glGenTextures(1, &texID);
487 glBindTexture(GL_TEXTURE_2D, tex->texID); 488 glBindTexture(GL_TEXTURE_2D, texID);
488 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); 489 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
489 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 490 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
490 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 491 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
491 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 492 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
492 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 493 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
493
494 return tex;
495} 494}
496 495
497void destroyTexture(Texture* tex) 496Texture::Texture(const char* filename)
498{ 497{
499 if (!rendererInitialized) 498 if (!rendererInitialized)
500 { 499 {
@@ -502,12 +501,19 @@ void destroyTexture(Texture* tex)
502 exit(-1); 501 exit(-1);
503 } 502 }
504 503
505 glDeleteTextures(1, &(tex->texID)); 504 glGenTextures(1, &texID);
506 505 glBindTexture(GL_TEXTURE_2D, texID);
507 delete tex; 506 unsigned char* data = stbi_load(filename, &width, &height, 0, 4);
507 flipImageData(data, width, height, 4);
508 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
509 stbi_image_free(data);
510 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
511 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
512 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
513 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
508} 514}
509 515
510Texture* loadTextureFromFile(char* filename) 516Texture::Texture(Texture& tex)
511{ 517{
512 if (!rendererInitialized) 518 if (!rendererInitialized)
513 { 519 {
@@ -515,22 +521,30 @@ Texture* loadTextureFromFile(char* filename)
515 exit(-1); 521 exit(-1);
516 } 522 }
517 523
518 Texture* tex = new Texture(); 524 width = tex.width;
519 glGenTextures(1, &(tex->texID)); 525 height = tex.height;
520 glBindTexture(GL_TEXTURE_2D, tex->texID); 526
521 unsigned char* data = stbi_load(filename, &(tex->width), &(tex->height), 0, 4); 527 unsigned char* data = (unsigned char*) malloc(4 * width * height);
522 flipImageData(data, tex->width, tex->height, 4); 528 glBindTexture(GL_TEXTURE_2D, tex.texID);
523 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex->width, tex->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); 529 glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
524 stbi_image_free(data); 530
531 glGenTextures(1, &texID);
532 glBindTexture(GL_TEXTURE_2D, texID);
533 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
525 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 534 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
526 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 535 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
527 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
528 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 536 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
537 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
529 538
530 return tex; 539 free(data);
531} 540}
532 541
533void saveTextureToBMP(Texture* tex, char* filename) 542Texture::Texture(Texture&& tex) : Texture(0, 0)
543{
544 swap(*this, tex);
545}
546
547Texture::~Texture()
534{ 548{
535 if (!rendererInitialized) 549 if (!rendererInitialized)
536 { 550 {
@@ -538,29 +552,24 @@ void saveTextureToBMP(Texture* tex, char* filename)
538 exit(-1); 552 exit(-1);
539 } 553 }
540 554
541 int size = 54 + 3*tex->width*tex->height; 555 glDeleteTextures(1, &texID);
542 556}
543 char* buf = (char*) calloc(size, sizeof(char)); 557
544 buf[0x00] = 'B'; 558Texture& Texture::operator= (Texture tex)
545 buf[0x01] = 'M'; 559{
546 *(int*)&(buf[0x0A]) = 54; 560 swap(*this, tex);
547 *(int*)&(buf[0x12]) = tex->width;
548 *(int*)&(buf[0x16]) = tex->height;
549 *(int*)&(buf[0x1C]) = 24;
550 *(int*)&(buf[0x1E]) = 0;
551 *(int*)&(buf[0x22]) = size;
552
553 glBindTexture(GL_TEXTURE_2D, tex->texID);
554 glGetTexImage(GL_TEXTURE_2D, 0, GL_BGR, GL_UNSIGNED_BYTE, buf + 54);
555
556 FILE* f = fopen(filename, "wb");
557 fwrite(buf, sizeof(char), size, f);
558 fclose(f);
559 561
560 free(buf); 562 return *this;
563}
564
565void swap(Texture& tex1, Texture& tex2)
566{
567 std::swap(tex1.width, tex2.width);
568 std::swap(tex1.height, tex2.height);
569 std::swap(tex1.texID, tex2.texID);
561} 570}
562 571
563void fillTexture(Texture* tex, Rectangle* dstrect, int r, int g, int b) 572void Texture::fill(Rectangle dstrect, int r, int g, int b)
564{ 573{
565 if (!rendererInitialized) 574 if (!rendererInitialized)
566 { 575 {
@@ -570,18 +579,13 @@ void fillTexture(Texture* tex, Rectangle* dstrect, int r, int g, int b)
570 579
571 // Target the framebuffer 580 // Target the framebuffer
572 glBindFramebuffer(GL_FRAMEBUFFER, generic_framebuffer); 581 glBindFramebuffer(GL_FRAMEBUFFER, generic_framebuffer);
573 glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex->texID, 0); 582 glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texID, 0);
574 583
575 // Set up the vertex attributes 584 // Set up the vertex attributes
576 GLfloat minx = (dstrect == NULL) ? 0.0f : dstrect->x; 585 GLfloat minx = (GLfloat) dstrect.x / width * 2.0 - 1.0;
577 GLfloat miny = (dstrect == NULL) ? 0.0f : dstrect->y; 586 GLfloat miny = -((GLfloat) dstrect.y / height * 2.0 - 1.0);
578 GLfloat maxx = (dstrect == NULL) ? tex->width : dstrect->x + dstrect->w; 587 GLfloat maxx = (GLfloat) (dstrect.x + dstrect.w) / width * 2.0 - 1.0;
579 GLfloat maxy = (dstrect == NULL) ? tex->height : dstrect->y + dstrect->h; 588 GLfloat maxy = -((GLfloat) (dstrect.y + dstrect.h) / height * 2.0 - 1.0);
580
581 minx = minx / tex->width * 2.0 - 1.0;
582 miny = -(miny / tex->height * 2.0 - 1.0);
583 maxx = maxx / tex->width * 2.0 - 1.0;
584 maxy = -(maxy / tex->height * 2.0 - 1.0);
585 589
586 GLfloat vertexbuffer_data[] = { 590 GLfloat vertexbuffer_data[] = {
587 minx, miny, 591 minx, miny,
@@ -598,7 +602,7 @@ void fillTexture(Texture* tex, Rectangle* dstrect, int r, int g, int b)
598 glEnableVertexAttribArray(0); 602 glEnableVertexAttribArray(0);
599 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)0); 603 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);
600 604
601 glViewport(0, 0, tex->width, tex->height); 605 glViewport(0, 0, width, height);
602 glClear(GL_DEPTH_BUFFER_BIT); 606 glClear(GL_DEPTH_BUFFER_BIT);
603 glUseProgram(fillShader); 607 glUseProgram(fillShader);
604 glUniform3f(glGetUniformLocation(fillShader, "vecColor"), r / 255.0, g / 255.0, b / 255.0); 608 glUniform3f(glGetUniformLocation(fillShader, "vecColor"), r / 255.0, g / 255.0, b / 255.0);
@@ -609,7 +613,7 @@ void fillTexture(Texture* tex, Rectangle* dstrect, int r, int g, int b)
609 glDeleteBuffers(1, &vertexbuffer); 613 glDeleteBuffers(1, &vertexbuffer);
610} 614}
611 615
612void blitTexture(Texture* srctex, Texture* dsttex, Rectangle* srcrect, Rectangle* dstrect) 616void Texture::blit(Texture& srctex, Rectangle srcrect, Rectangle dstrect)
613{ 617{
614 if (!rendererInitialized) 618 if (!rendererInitialized)
615 { 619 {
@@ -619,18 +623,13 @@ void blitTexture(Texture* srctex, Texture* dsttex, Rectangle* srcrect, Rectangle
619 623
620 // Target the framebuffer 624 // Target the framebuffer
621 glBindFramebuffer(GL_FRAMEBUFFER, generic_framebuffer); 625 glBindFramebuffer(GL_FRAMEBUFFER, generic_framebuffer);
622 glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, dsttex->texID, 0); 626 glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texID, 0);
623 627
624 // Set up the vertex attributes 628 // Set up the vertex attributes
625 GLfloat minx = (dstrect == NULL) ? 0.0f : dstrect->x; 629 GLfloat minx = (GLfloat) dstrect.x / width * 2.0 - 1.0;
626 GLfloat miny = (dstrect == NULL) ? 0.0f : dstrect->y; 630 GLfloat miny = -((GLfloat) dstrect.y / height * 2.0 - 1.0);
627 GLfloat maxx = (dstrect == NULL) ? dsttex->width : dstrect->x + dstrect->w; 631 GLfloat maxx = (GLfloat) (dstrect.x + dstrect.w) / width * 2.0 - 1.0;
628 GLfloat maxy = (dstrect == NULL) ? dsttex->height : dstrect->y + dstrect->h; 632 GLfloat maxy = -((GLfloat) (dstrect.y + dstrect.h) / height * 2.0 - 1.0);
629
630 minx = minx / dsttex->width * 2.0 - 1.0;
631 miny = -(miny / dsttex->height * 2.0 - 1.0);
632 maxx = maxx / dsttex->width * 2.0 - 1.0;
633 maxy = -(maxy / dsttex->height * 2.0 - 1.0);
634 633
635 GLfloat vertexbuffer_data[] = { 634 GLfloat vertexbuffer_data[] = {
636 minx, miny, 635 minx, miny,
@@ -645,15 +644,10 @@ void blitTexture(Texture* srctex, Texture* dsttex, Rectangle* srcrect, Rectangle
645 glEnableVertexAttribArray(0); 644 glEnableVertexAttribArray(0);
646 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)0); 645 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);
647 646
648 GLfloat minu = (srcrect == NULL) ? 0.0f : srcrect->x; 647 GLfloat minu = (GLfloat) srcrect.x / srctex.width;
649 GLfloat minv = (srcrect == NULL) ? 0.0f : srcrect->y; 648 GLfloat minv = 1 - ((GLfloat) srcrect.y / srctex.height);
650 GLfloat maxu = (srcrect == NULL) ? srctex->width : srcrect->x + srcrect->w; 649 GLfloat maxu = (GLfloat) (srcrect.x + srcrect.w) / srctex.width;
651 GLfloat maxv = (srcrect == NULL) ? srctex->height : srcrect->y + srcrect->h; 650 GLfloat maxv = 1 - ((GLfloat) (srcrect.y + srcrect.h) / srctex.height);
652
653 minu = minu / srctex->width;
654 minv = 1 - (minv / srctex->height);
655 maxu = maxu / srctex->width;
656 maxv = 1 - (maxv / srctex->height);
657 651
658 GLfloat texcoordbuffer_data[] = { 652 GLfloat texcoordbuffer_data[] = {
659 minu, minv, 653 minu, minv,
@@ -671,10 +665,10 @@ void blitTexture(Texture* srctex, Texture* dsttex, Rectangle* srcrect, Rectangle
671 // Set up the shader 665 // Set up the shader
672 glUseProgram(blitShader); 666 glUseProgram(blitShader);
673 glClear(GL_DEPTH_BUFFER_BIT); 667 glClear(GL_DEPTH_BUFFER_BIT);
674 glViewport(0, 0, dsttex->width, dsttex->height); 668 glViewport(0, 0, width, height);
675 669
676 glActiveTexture(GL_TEXTURE0); 670 glActiveTexture(GL_TEXTURE0);
677 glBindTexture(GL_TEXTURE_2D, srctex->texID); 671 glBindTexture(GL_TEXTURE_2D, srctex.texID);
678 glUniform1i(glGetUniformLocation(blitShader, "srctex"), 0); 672 glUniform1i(glGetUniformLocation(blitShader, "srctex"), 0);
679 673
680 // Blit! 674 // Blit!
@@ -687,63 +681,7 @@ void blitTexture(Texture* srctex, Texture* dsttex, Rectangle* srcrect, Rectangle
687 glDeleteBuffers(1, &vertexbuffer); 681 glDeleteBuffers(1, &vertexbuffer);
688} 682}
689 683
690void renderWithoutEffects(Texture* tex) 684void bloomPass1(GLuint srcTex, GLuint dstTex, bool horizontal, glm::vec2 srcRes, glm::vec2 dstRes)
691{
692 if (!rendererInitialized)
693 {
694 fprintf(stderr, "Renderer not initialized\n");
695 exit(-1);
696 }
697
698 glBindFramebuffer(GL_FRAMEBUFFER, 0);
699 glViewport(0, 0, buffer_width, buffer_height);
700 glClear(GL_COLOR_BUFFER_BIT);
701 glUseProgram(blitShader);
702
703 const GLfloat fullBlitVertices_data[] = {
704 -1.0, -1.0,
705 1.0, -1.0,
706 -1.0, 1.0,
707 1.0, 1.0
708 };
709
710 GLuint fullBlitVertices;
711 glGenBuffers(1, &fullBlitVertices);
712 glBindBuffer(GL_ARRAY_BUFFER, fullBlitVertices);
713 glBufferData(GL_ARRAY_BUFFER, sizeof(fullBlitVertices_data), fullBlitVertices_data, GL_STATIC_DRAW);
714 glEnableVertexAttribArray(0);
715 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);
716
717 const GLfloat fullBlitTex_data[] = {
718 0.0, 0.0,
719 1.0, 0.0,
720 0.0, 1.0,
721 1.0, 1.0
722 };
723
724 GLuint fullBlitTex;
725 glGenBuffers(1, &fullBlitTex);
726 glBindBuffer(GL_ARRAY_BUFFER, fullBlitTex);
727 glBufferData(GL_ARRAY_BUFFER, sizeof(fullBlitTex_data), fullBlitTex_data, GL_STATIC_DRAW);
728 glEnableVertexAttribArray(1);
729 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);
730
731 glActiveTexture(GL_TEXTURE0);
732 glBindTexture(GL_TEXTURE_2D, tex->texID);
733 glUniform1i(glGetUniformLocation(blitShader, "srctex"), 0);
734
735 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
736
737 glDisableVertexAttribArray(1);
738 glDisableVertexAttribArray(0);
739
740 glDeleteBuffers(1, &fullBlitTex);
741 glDeleteBuffers(1, &fullBlitVertices);
742
743 glfwSwapBuffers(window);
744}
745
746void bloomPass1(GLuint srcTex, GLuint dstTex, bool horizontal, vec2 srcRes, vec2 dstRes)
747{ 685{
748 glBindFramebuffer(GL_FRAMEBUFFER, generic_framebuffer); 686 glBindFramebuffer(GL_FRAMEBUFFER, generic_framebuffer);
749 glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, dstTex, 0); 687 glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, dstTex, 0);
@@ -755,7 +693,7 @@ void bloomPass1(GLuint srcTex, GLuint dstTex, bool horizontal, vec2 srcRes, vec2
755 glBindTexture(GL_TEXTURE_2D, srcTex); 693 glBindTexture(GL_TEXTURE_2D, srcTex);
756 glUniform1i(glGetUniformLocation(bloom1Shader, "inTex"), 0); 694 glUniform1i(glGetUniformLocation(bloom1Shader, "inTex"), 0);
757 695
758 vec2 offset = vec2(0.0); 696 glm::vec2 offset = glm::vec2(0.0);
759 if (horizontal) 697 if (horizontal)
760 { 698 {
761 offset.x = 1.2/srcRes.x; 699 offset.x = 1.2/srcRes.x;
@@ -772,7 +710,7 @@ void bloomPass1(GLuint srcTex, GLuint dstTex, bool horizontal, vec2 srcRes, vec2
772 glDisableVertexAttribArray(0); 710 glDisableVertexAttribArray(0);
773} 711}
774 712
775void renderScreen(Texture* tex) 713void Texture::renderScreen()
776{ 714{
777 if (!rendererInitialized) 715 if (!rendererInitialized)
778 { 716 {
@@ -792,7 +730,7 @@ void renderScreen(Texture* tex)
792 730
793 // Use the current frame texture, nearest neighbor and clamped to edge 731 // Use the current frame texture, nearest neighbor and clamped to edge
794 glActiveTexture(GL_TEXTURE0); 732 glActiveTexture(GL_TEXTURE0);
795 glBindTexture(GL_TEXTURE_2D, tex->texID); 733 glBindTexture(GL_TEXTURE_2D, texID);
796 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 734 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
797 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 735 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
798 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 736 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
@@ -832,7 +770,6 @@ void renderScreen(Texture* tex)
832 // We're going to render the screen now 770 // We're going to render the screen now
833 glBindFramebuffer(GL_FRAMEBUFFER, bloom_framebuffer); 771 glBindFramebuffer(GL_FRAMEBUFFER, bloom_framebuffer);
834 glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, preBloomTex, 0); 772 glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, preBloomTex, 0);
835 //glBindFramebuffer(GL_FRAMEBUFFER, 0);
836 glViewport(0,0,buffer_width,buffer_height); 773 glViewport(0,0,buffer_width,buffer_height);
837 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 774 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
838 glUseProgram(finalShader); 775 glUseProgram(finalShader);
@@ -855,11 +792,10 @@ void renderScreen(Texture* tex)
855 glUniform1i(glGetUniformLocation(finalShader, "scanlinestex"), 1); 792 glUniform1i(glGetUniformLocation(finalShader, "scanlinestex"), 1);
856 793
857 // Initialize the MVP matrices 794 // Initialize the MVP matrices
858 mat4 p_matrix = perspective(42.5f, (float) buffer_width / (float) buffer_height, 0.1f, 100.0f); 795 glm::mat4 p_matrix = glm::perspective(42.5f, (float) buffer_width / (float) buffer_height, 0.1f, 100.0f);
859 mat4 v_matrix = lookAt(vec3(2,0,0), vec3(0,0,0), vec3(0,1,0)); 796 glm::mat4 v_matrix = glm::lookAt(glm::vec3(2,0,0), glm::vec3(0,0,0), glm::vec3(0,1,0));
860 mat4 m_matrix = mat4(1.0); 797 glm::mat4 m_matrix = glm::mat4(1.0);
861 mat4 mvp_matrix = p_matrix * v_matrix * m_matrix; 798 glm::mat4 mvp_matrix = p_matrix * v_matrix * m_matrix;
862 //mat4 mv_matrix = v_matrix * m_matrix;
863 799
864 glUniformMatrix4fv(glGetUniformLocation(finalShader, "MVP"), 1, GL_FALSE, &mvp_matrix[0][0]); 800 glUniformMatrix4fv(glGetUniformLocation(finalShader, "MVP"), 1, GL_FALSE, &mvp_matrix[0][0]);
865 glUniformMatrix4fv(glGetUniformLocation(finalShader, "worldMat"), 1, GL_FALSE, &m_matrix[0][0]); 801 glUniformMatrix4fv(glGetUniformLocation(finalShader, "worldMat"), 1, GL_FALSE, &m_matrix[0][0]);
@@ -884,7 +820,7 @@ void renderScreen(Texture* tex)
884 glDisableVertexAttribArray(0); 820 glDisableVertexAttribArray(0);
885 821
886 // First pass of bloom! 822 // First pass of bloom!
887 vec2 buffer_size = vec2(buffer_width, buffer_height); 823 glm::vec2 buffer_size = glm::vec2(buffer_width, buffer_height);
888 bloomPass1(preBloomTex, bloomPassTex1, true, buffer_size, buffer_size / 4.0f); 824 bloomPass1(preBloomTex, bloomPassTex1, true, buffer_size, buffer_size / 4.0f);
889 bloomPass1(bloomPassTex1, bloomPassTex2, false, buffer_size / 4.0f, buffer_size / 4.0f); 825 bloomPass1(bloomPassTex1, bloomPassTex2, false, buffer_size / 4.0f, buffer_size / 4.0f);
890 826
@@ -903,7 +839,6 @@ void renderScreen(Texture* tex)
903 glUniform1i(glGetUniformLocation(bloom2Shader, "blurTex"), 1); 839 glUniform1i(glGetUniformLocation(bloom2Shader, "blurTex"), 1);
904 840
905 glUniform1f(glGetUniformLocation(bloom2Shader, "iGlobalTime"), glfwGetTime()); 841 glUniform1f(glGetUniformLocation(bloom2Shader, "iGlobalTime"), glfwGetTime());
906// glUniform2f(glGetUniformLocation(bloom2Shader, "resolution"), buffer_width, buffer_height);
907 842
908 glEnableVertexAttribArray(0); 843 glEnableVertexAttribArray(0);
909 glBindBuffer(GL_ARRAY_BUFFER, quad_vertexbuffer); 844 glBindBuffer(GL_ARRAY_BUFFER, quad_vertexbuffer);
@@ -915,3 +850,8 @@ void renderScreen(Texture* tex)
915 850
916 curBuf = (curBuf + 1) % 2; 851 curBuf = (curBuf + 1) % 2;
917} 852}
853
854Rectangle Texture::entirety()
855{
856 return {0, 0, width, height};
857}
diff --git a/src/renderer.h b/src/renderer.h index a4e21f7..509e935 100644 --- a/src/renderer.h +++ b/src/renderer.h
@@ -1,9 +1,5 @@
1#include <GL/glew.h> 1#include <GL/glew.h>
2#include <GLFW/glfw3.h> 2#include <GLFW/glfw3.h>
3#include <glm/glm.hpp>
4#include <glm/gtc/matrix_transform.hpp>
5
6using namespace glm;
7 3
8#ifndef RENDERER_H 4#ifndef RENDERER_H
9#define RENDERER_H 5#define RENDERER_H
@@ -13,33 +9,29 @@ struct Rectangle {
13 int y; 9 int y;
14 int w; 10 int w;
15 int h; 11 int h;
16
17 Rectangle() {};
18
19 Rectangle(int m_x, int m_y, int m_w, int m_h)
20 {
21 x = m_x;
22 y = m_y;
23 w = m_w;
24 h = m_h;
25 }
26}; 12};
27 13
28struct Texture { 14class Texture {
29 GLuint texID; 15 public:
30 int width; 16 Texture(int width, int height);
31 int height; 17 Texture(const char* file);
18 Texture(Texture& tex);
19 Texture(Texture&& tex);
20 ~Texture();
21 Texture& operator= (Texture tex);
22 friend void swap(Texture& tex1, Texture& tex2);
23 void fill(Rectangle loc, int r, int g, int b);
24 void blit(Texture& src, Rectangle srcrect, Rectangle dstrect);
25 void renderScreen();
26 Rectangle entirety();
27
28 private:
29 GLuint texID;
30 int width;
31 int height;
32}; 32};
33 33
34GLFWwindow* initRenderer(); 34GLFWwindow* initRenderer();
35void destroyRenderer(); 35void destroyRenderer();
36Texture* createTexture(int width, int height);
37void destroyTexture(Texture* tex);
38Texture* loadTextureFromFile(char* filename);
39void saveTextureToBMP(Texture* tex, char* filename);
40void fillTexture(Texture* tex, Rectangle* loc, int r, int g, int b);
41void blitTexture(Texture* srctex, Texture* dsttex, Rectangle* srcrect, Rectangle* dstrect);
42void renderWithoutEffects(Texture* tex);
43void renderScreen(Texture* tex);
44 36
45#endif 37#endif
diff --git a/src/world.cpp b/src/world.cpp deleted file mode 100644 index 90d9ab8..0000000 --- a/src/world.cpp +++ /dev/null
@@ -1,32 +0,0 @@
1#include "world.h"
2
3void World::tick()
4{
5 for (auto it = entities.begin(); it != entities.end(); it++)
6 {
7 (*it)->tick();
8 }
9}
10
11void World::input(int key, int action)
12{
13 for (auto it = entities.begin(); it != entities.end(); it++)
14 {
15 (*it)->input(key, action);
16 }
17}
18
19void World::render(Texture* buffer)
20{
21 fillTexture(buffer, NULL, 0, 0, 0);
22
23 for (auto it = entities.begin(); it != entities.end(); it++)
24 {
25 (*it)->render(buffer);
26 }
27}
28
29void World::addEntity(std::shared_ptr<Entity> e)
30{
31 entities.push_back(e);
32}
diff --git a/src/world.h b/src/world.h deleted file mode 100644 index ad6c788..0000000 --- a/src/world.h +++ /dev/null
@@ -1,27 +0,0 @@
1#ifndef WORLD_H
2#define WORLD_H
3
4class World;
5
6#include <list>
7#include "renderer.h"
8#include "entity.h"
9#include <cstdio>
10
11class World {
12 public:
13 World() {};
14 ~World() {};
15 void tick();
16 void input(int key, int action);
17 void render(Texture* buffer);
18 void addEntity(std::shared_ptr<Entity> e);
19
20 std::list<Collidable*> bodies;
21 std::shared_ptr<Entity> player;
22
23 private:
24 std::list<std::shared_ptr<Entity>> entities;
25};
26
27#endif