diff options
| -rw-r--r-- | CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/components.cpp | 353 | ||||
| -rw-r--r-- | src/components.h | 76 | ||||
| -rw-r--r-- | src/entity.cpp | 32 | ||||
| -rw-r--r-- | src/entity.h | 81 | ||||
| -rw-r--r-- | src/game.cpp | 135 | ||||
| -rw-r--r-- | src/game.h | 38 | ||||
| -rw-r--r-- | src/main.cpp | 10 | ||||
| -rw-r--r-- | src/map.cpp | 41 | ||||
| -rw-r--r-- | src/map.h | 14 | ||||
| -rw-r--r-- | src/renderer.cpp | 256 | ||||
| -rw-r--r-- | src/renderer.h | 44 | ||||
| -rw-r--r-- | src/world.cpp | 32 | ||||
| -rw-r--r-- | src/world.h | 27 |
14 files changed, 511 insertions, 630 deletions
| diff --git a/CMakeLists.txt b/CMakeLists.txt index 0937493..82ac3cb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt | |||
| @@ -34,6 +34,6 @@ set(ALL_LIBS | |||
| 34 | 34 | ||
| 35 | # include_directories(${SDL2_INCLUDE_DIR}) | 35 | # include_directories(${SDL2_INCLUDE_DIR}) |
| 36 | set(CMAKE_BUILD_TYPE Debug) | 36 | set(CMAKE_BUILD_TYPE Debug) |
| 37 | add_executable(Aromatherapy src/main.cpp src/map.cpp src/renderer.cpp src/world.cpp src/entity.cpp src/components.cpp src/game.cpp) | 37 | add_executable(Aromatherapy src/main.cpp src/map.cpp src/renderer.cpp src/entity.cpp src/components.cpp src/game.cpp) |
| 38 | target_link_libraries(Aromatherapy ${ALL_LIBS}) | 38 | target_link_libraries(Aromatherapy ${ALL_LIBS}) |
| 39 | install(TARGETS Aromatherapy RUNTIME DESTINATION ${BIN_DIR}) | 39 | install(TARGETS Aromatherapy RUNTIME DESTINATION ${BIN_DIR}) |
| 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 | ||
| 6 | void UserMovementComponent::input(int key, int action) | 6 | void 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 | ||
| 91 | void PhysicsBodyComponent::receive(message_t msg) | 71 | void 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 | ||
| 105 | void PhysicsBodyComponent::tick() | 91 | void 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 | ||
| 114 | void PhysicsBodyComponent::detectCollision(Entity& player, Locatable& physics, std::pair<double, double> old_position) | 100 | void 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 | ||
| 141 | PlayerSpriteComponent::PlayerSpriteComponent(Entity& entity, Locatable& physics) : Component(entity), physics(physics) | 126 | void PlayerSpriteComponent::render(Game&, Entity& entity, Texture& buffer) |
| 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 | { | 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 | ||
| 170 | void PlayerSpriteComponent::receive(message_t msg) | 145 | void 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 | ||
| 186 | void PlayerSpriteComponent::tick() | 161 | void 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 | ||
| 197 | PlayerPhysicsComponent::PlayerPhysicsComponent(Entity& entity) : Component(entity) | 172 | PlayerPhysicsComponent::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 | ||
| 206 | void PlayerPhysicsComponent::receive(message_t msg) | 181 | void 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 | ||
| 245 | void PlayerPhysicsComponent::tick() | 226 | void 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 | ||
| 290 | MapRenderComponent::MapRenderComponent(Entity& entity, Map* map) : Component(entity) | 267 | MapRenderComponent::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 | ||
| 326 | MapRenderComponent::~MapRenderComponent() | 298 | void MapRenderComponent::render(Game&, Entity&, Texture& buffer) |
| 327 | { | 299 | { |
| 328 | destroyTexture(screen); | 300 | buffer.blit(screen, screen.entirety(), buffer.entirety()); |
| 329 | } | ||
| 330 | |||
| 331 | void MapRenderComponent::render(Texture* buffer) | ||
| 332 | { | ||
| 333 | blitTexture(screen, buffer, NULL, NULL); | ||
| 334 | } | 301 | } |
| 335 | 302 | ||
| 336 | // Map collision | 303 | // Map collision |
| 337 | 304 | ||
| 338 | MapCollisionComponent::MapCollisionComponent(Entity& entity, Map* map) : Component(entity) | 305 | MapCollisionComponent::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 | ||
| 413 | void MapCollisionComponent::detectCollision(Entity& player, Locatable& physics, std::pair<double, double> old_position) | 381 | void 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 | ||
| 9 | class UserMovementComponent : public Component { | 10 | class 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 | ||
| 19 | class PhysicsBodyComponent : public Component, public Collidable, public Locatable { | 19 | class 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 | ||
| 27 | class PlayerSpriteComponent : public Component { | 30 | class 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 | ||
| 43 | class PlayerPhysicsComponent : public Component, public Locatable { | 43 | class 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 | ||
| 57 | class MapRenderComponent : public Component { | 59 | class 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 | |||
| 67 | enum direction_t { | ||
| 68 | up, left, down, right | ||
| 69 | }; | 66 | }; |
| 70 | 67 | ||
| 71 | typedef struct { | 68 | class MapCollisionComponent : public Component { |
| 72 | int axis; | ||
| 73 | int lower; | ||
| 74 | int upper; | ||
| 75 | int type; | ||
| 76 | } collision_t; | ||
| 77 | |||
| 78 | class 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 | ||
| 8 | void Entity::send(message_t msg) | 8 | void 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 | ||
| 16 | void Entity::tick() | 16 | void 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 | ||
| 24 | void Entity::input(int key, int action) | 24 | void 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 | ||
| 32 | void Entity::render(Texture* buffer) | 32 | void 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 | |||
| 40 | void 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 | ||
| 4 | class Entity; | 4 | class Entity; |
| 5 | class Component; | 5 | class Component; |
| 6 | class Locatable; | ||
| 7 | class 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 | ||
| 13 | enum message_type { | 11 | class 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 | ||
| 25 | typedef struct { | ||
| 26 | message_type type; | ||
| 27 | Entity* collisionEntity; | ||
| 28 | int dropAxis; | ||
| 29 | } message_t; | ||
| 30 | |||
| 31 | class Entity { | 34 | class 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 | ||
| 47 | class Component { | 50 | class 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 | |||
| 59 | class 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 | |||
| 67 | class 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 | ||
| 4 | Game::Game() | 5 | Game::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 | ||
| 36 | Game::~Game() | 26 | void 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 | |||
| 54 | void 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 | ||
| 68 | void Game::execute() | 41 | void 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 | ||
| 99 | void 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 | ||
| 107 | void Game::loadMap(Map* map) | 90 | void 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 | |||
| 107 | void 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" | 4 | class Game; |
| 5 | |||
| 6 | #include "map.h" | ||
| 7 | #include <memory> | ||
| 8 | #include "entity.h" | ||
| 5 | 9 | ||
| 6 | const int TILE_WIDTH = 8; | 10 | const int TILE_WIDTH = 8; |
| 7 | const int TILE_HEIGHT = 8; | 11 | const int TILE_HEIGHT = 8; |
| @@ -15,29 +19,21 @@ const double SECONDS_PER_FRAME = 1.0 / FRAMES_PER_SECOND; | |||
| 15 | 19 | ||
| 16 | class Game { | 20 | class 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 | ||
| 4 | Map::Map(char* filename) | 6 | Map::Map() |
| 7 | { | ||
| 8 | |||
| 9 | } | ||
| 10 | |||
| 11 | Map::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 | ||
| 32 | Map::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 | |||
| 44 | Map::Map(Map&& map) : Map() | ||
| 45 | { | ||
| 46 | swap(*this, map); | ||
| 47 | } | ||
| 48 | |||
| 25 | Map::~Map() | 49 | Map::~Map() |
| 26 | { | 50 | { |
| 27 | free(m_mapdata); | 51 | free(m_mapdata); |
| 28 | free(m_title); | 52 | free(m_title); |
| 29 | } | 53 | } |
| 30 | 54 | ||
| 55 | Map& Map::operator= (Map map) | ||
| 56 | { | ||
| 57 | swap(*this, map); | ||
| 58 | |||
| 59 | return *this; | ||
| 60 | } | ||
| 61 | |||
| 62 | void 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 | |||
| 31 | const int* Map::mapdata() | 70 | const 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 | ||
| 4 | class Map { | 4 | class 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) | |||
| 147 | void loadMesh(const char* filename, std::vector<glm::vec3>& out_vertices, std::vector<glm::vec2>& out_uvs, std::vector<glm::vec3>& out_normals) | 149 | void 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 | ||
| 474 | Texture* createTexture(int width, int height) | 476 | Texture::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 | ||
| 497 | void destroyTexture(Texture* tex) | 496 | Texture::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 | ||
| 510 | Texture* loadTextureFromFile(char* filename) | 516 | Texture::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 | ||
| 533 | void saveTextureToBMP(Texture* tex, char* filename) | 542 | Texture::Texture(Texture&& tex) : Texture(0, 0) |
| 543 | { | ||
| 544 | swap(*this, tex); | ||
| 545 | } | ||
| 546 | |||
| 547 | Texture::~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'; | 558 | Texture& 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 | |||
| 565 | void 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 | ||
| 563 | void fillTexture(Texture* tex, Rectangle* dstrect, int r, int g, int b) | 572 | void 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 | ||
| 612 | void blitTexture(Texture* srctex, Texture* dsttex, Rectangle* srcrect, Rectangle* dstrect) | 616 | void 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 | ||
| 690 | void renderWithoutEffects(Texture* tex) | 684 | void 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 | |||
| 746 | void 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 | ||
| 775 | void renderScreen(Texture* tex) | 713 | void 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 | |||
| 854 | Rectangle 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 | |||
| 6 | using 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 | ||
| 28 | struct Texture { | 14 | class 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 | ||
| 34 | GLFWwindow* initRenderer(); | 34 | GLFWwindow* initRenderer(); |
| 35 | void destroyRenderer(); | 35 | void destroyRenderer(); |
| 36 | Texture* createTexture(int width, int height); | ||
| 37 | void destroyTexture(Texture* tex); | ||
| 38 | Texture* loadTextureFromFile(char* filename); | ||
| 39 | void saveTextureToBMP(Texture* tex, char* filename); | ||
| 40 | void fillTexture(Texture* tex, Rectangle* loc, int r, int g, int b); | ||
| 41 | void blitTexture(Texture* srctex, Texture* dsttex, Rectangle* srcrect, Rectangle* dstrect); | ||
| 42 | void renderWithoutEffects(Texture* tex); | ||
| 43 | void 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 | |||
| 3 | void World::tick() | ||
| 4 | { | ||
| 5 | for (auto it = entities.begin(); it != entities.end(); it++) | ||
| 6 | { | ||
| 7 | (*it)->tick(); | ||
| 8 | } | ||
| 9 | } | ||
| 10 | |||
| 11 | void 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 | |||
| 19 | void 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 | |||
| 29 | void 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 | |||
| 4 | class World; | ||
| 5 | |||
| 6 | #include <list> | ||
| 7 | #include "renderer.h" | ||
| 8 | #include "entity.h" | ||
| 9 | #include <cstdio> | ||
| 10 | |||
| 11 | class 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 | ||
