A complex 2D-dungeon game on LPC1768 in SWJTU-Leeds Joint School XJEL2645 project. Referenced from the framework contributed by https://os.mbed.com/users/Siriagus/code/SimplePlatformGame/

Dependencies:   mbed N5110 ShiftReg PinDetect

Committer:
Siriagus
Date:
Sun May 10 09:37:51 2015 +0000
Revision:
15:d5eb13c4c1c6
Parent:
14:b4fed570abaf
Child:
16:caf613d5b85e
Enemy - bullet collison + entities can walk upwards slopes or climb walls with a height smaller than themselves.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Siriagus 7:678873947b29 1 #include "Game.h"
Siriagus 7:678873947b29 2
Siriagus 8:9ac6a428fa26 3 Serial pc(USBTX, USBRX); // TO DELETE - DEBUGGING ONLY
Siriagus 8:9ac6a428fa26 4
Siriagus 8:9ac6a428fa26 5 void Game::init()
Siriagus 8:9ac6a428fa26 6 {
Siriagus 15:d5eb13c4c1c6 7 paused = false;
Siriagus 15:d5eb13c4c1c6 8
Siriagus 12:8178fad5e660 9 // Set initial values for the player
Siriagus 13:7ab71c7c311b 10 player.x = 40; // start x
Siriagus 13:7ab71c7c311b 11 player.y = 5; // start y
Siriagus 13:7ab71c7c311b 12 player.width = player.height = 5; // important that this is correct, see size of Image::Player in Resources.h
Siriagus 12:8178fad5e660 13 player.onGround = false;
Siriagus 13:7ab71c7c311b 14
Siriagus 15:d5eb13c4c1c6 15 enemy = new Enemy(75, 3, 6, 5);
Siriagus 15:d5eb13c4c1c6 16 enemy->vx = -2;
Siriagus 15:d5eb13c4c1c6 17 enemy->facingLeft = true;
Siriagus 8:9ac6a428fa26 18 }
Siriagus 8:9ac6a428fa26 19
Siriagus 8:9ac6a428fa26 20 // Functions
Siriagus 7:678873947b29 21 void Game::update(float dt)
Siriagus 7:678873947b29 22 {
Siriagus 15:d5eb13c4c1c6 23 // Pause button input
Siriagus 15:d5eb13c4c1c6 24 if (input->read(Input::ButtonC))
Siriagus 15:d5eb13c4c1c6 25 {
Siriagus 15:d5eb13c4c1c6 26 if (releasedBtnC)
Siriagus 15:d5eb13c4c1c6 27 {
Siriagus 15:d5eb13c4c1c6 28 paused = !paused;
Siriagus 15:d5eb13c4c1c6 29 releasedBtnC = false;
Siriagus 15:d5eb13c4c1c6 30 }
Siriagus 15:d5eb13c4c1c6 31 }
Siriagus 15:d5eb13c4c1c6 32 else
Siriagus 15:d5eb13c4c1c6 33 releasedBtnC = true;
Siriagus 15:d5eb13c4c1c6 34
Siriagus 15:d5eb13c4c1c6 35 // Skip the rest if paused
Siriagus 15:d5eb13c4c1c6 36 if (paused) return;
Siriagus 15:d5eb13c4c1c6 37
Siriagus 15:d5eb13c4c1c6 38
Siriagus 15:d5eb13c4c1c6 39
Siriagus 15:d5eb13c4c1c6 40
Siriagus 8:9ac6a428fa26 41 // Handle input, should be its own function
Siriagus 8:9ac6a428fa26 42 switch(input->joystick->getDirection())
Siriagus 8:9ac6a428fa26 43 {
Siriagus 8:9ac6a428fa26 44 case LEFT:
Siriagus 8:9ac6a428fa26 45 case UP_LEFT:
Siriagus 8:9ac6a428fa26 46 case DOWN_LEFT:
Siriagus 8:9ac6a428fa26 47 player.vx = -2;
Siriagus 11:adb68da98262 48 player.facingLeft = true;
Siriagus 8:9ac6a428fa26 49 break;
Siriagus 8:9ac6a428fa26 50
Siriagus 8:9ac6a428fa26 51 case RIGHT:
Siriagus 8:9ac6a428fa26 52 case UP_RIGHT:
Siriagus 8:9ac6a428fa26 53 case DOWN_RIGHT:
Siriagus 8:9ac6a428fa26 54 player.vx = 2;
Siriagus 11:adb68da98262 55 player.facingLeft = false;
Siriagus 8:9ac6a428fa26 56 break;
Siriagus 8:9ac6a428fa26 57
Siriagus 8:9ac6a428fa26 58 case CENTER:
Siriagus 8:9ac6a428fa26 59 player.vx = 0;
Siriagus 8:9ac6a428fa26 60 break;
Siriagus 8:9ac6a428fa26 61 }
Siriagus 7:678873947b29 62
Siriagus 15:d5eb13c4c1c6 63 // Random movement for enemies
Siriagus 15:d5eb13c4c1c6 64 if (enemy->onGround && (rand() % 100) > 97) // 3 % chance
Siriagus 13:7ab71c7c311b 65 {
Siriagus 15:d5eb13c4c1c6 66 // jump
Siriagus 15:d5eb13c4c1c6 67 enemy->vy = -3;
Siriagus 15:d5eb13c4c1c6 68 enemy->onGround = false;
Siriagus 15:d5eb13c4c1c6 69 }
Siriagus 15:d5eb13c4c1c6 70 else if ((rand() % 100) > 98) // 2% chance
Siriagus 15:d5eb13c4c1c6 71 {
Siriagus 15:d5eb13c4c1c6 72 // switch direction
Siriagus 15:d5eb13c4c1c6 73 enemy->vx *= -1;
Siriagus 15:d5eb13c4c1c6 74 enemy->facingLeft = (enemy->vx < 0);
Siriagus 13:7ab71c7c311b 75 }
Siriagus 13:7ab71c7c311b 76
Siriagus 13:7ab71c7c311b 77 // Gravity
Siriagus 11:adb68da98262 78 player.vy += 1;
Siriagus 15:d5eb13c4c1c6 79 enemy->vy += 1;
Siriagus 8:9ac6a428fa26 80
Siriagus 11:adb68da98262 81 // Check if player is trying to jump. Player can only jump if it's on the ground
Siriagus 12:8178fad5e660 82 if (input->read(Input::ButtonA) && player.onGround)
Siriagus 8:9ac6a428fa26 83 {
Siriagus 8:9ac6a428fa26 84 player.vy = -4;
Siriagus 12:8178fad5e660 85 player.onGround = false;
Siriagus 8:9ac6a428fa26 86 }
Siriagus 8:9ac6a428fa26 87
Siriagus 11:adb68da98262 88 // Terminal velocity 3 px/update
Siriagus 14:b4fed570abaf 89 if (player.vy > TERMINAL_VELOCITY) player.vy = TERMINAL_VELOCITY;
Siriagus 8:9ac6a428fa26 90
Siriagus 13:7ab71c7c311b 91 moveWithCollisionTest(&player, map);
Siriagus 15:d5eb13c4c1c6 92
Siriagus 15:d5eb13c4c1c6 93 if (!enemy->dead)
Siriagus 15:d5eb13c4c1c6 94 moveWithCollisionTest(enemy, map);
Siriagus 15:d5eb13c4c1c6 95 else
Siriagus 15:d5eb13c4c1c6 96 {
Siriagus 15:d5eb13c4c1c6 97 enemy->y += enemy->vy;
Siriagus 15:d5eb13c4c1c6 98 enemy->x += enemy->vx;
Siriagus 15:d5eb13c4c1c6 99 }
Siriagus 15:d5eb13c4c1c6 100 // else if (enemy->y >= HEIGHT) ; // TODO : delete enemy
Siriagus 11:adb68da98262 101
Siriagus 13:7ab71c7c311b 102 // Enemy AI
Siriagus 15:d5eb13c4c1c6 103 if (!enemy->dead)
Siriagus 11:adb68da98262 104 {
Siriagus 15:d5eb13c4c1c6 105 int nextRight = enemy->getRight() + 1; // Next position of right edge if enemy moves to the right
Siriagus 15:d5eb13c4c1c6 106 for (int i = 0; i < enemy->height; ++i) // Check for all heighs
Siriagus 11:adb68da98262 107 {
Siriagus 15:d5eb13c4c1c6 108 // Check if crashing if moving right or left. Bounds should already be limited by moveWithCollisionTest!
Siriagus 15:d5eb13c4c1c6 109 // will also try to climb a slope if it can find one
Siriagus 15:d5eb13c4c1c6 110 if ((map[enemy->y + i][nextRight] && map[enemy->y+i-1][nextRight]) || (map[enemy->y + i][enemy->x - 1] && map[enemy->y + i-1][enemy->x - 1]))
Siriagus 15:d5eb13c4c1c6 111 {
Siriagus 15:d5eb13c4c1c6 112 enemy->vx *= -1; // move in opposite direction
Siriagus 15:d5eb13c4c1c6 113 enemy->facingLeft = !enemy->facingLeft; // toggle direction
Siriagus 15:d5eb13c4c1c6 114 break; // no further testing required
Siriagus 15:d5eb13c4c1c6 115 }
Siriagus 11:adb68da98262 116 }
Siriagus 11:adb68da98262 117 }
Siriagus 8:9ac6a428fa26 118
Siriagus 11:adb68da98262 119 // Check if bullet should be fired
Siriagus 9:da608ae65df9 120 if (input->read(Input::ButtonB) && releasedBtnB)
Siriagus 8:9ac6a428fa26 121 {
Siriagus 11:adb68da98262 122 // Create a new bullet and give it initial values
Siriagus 8:9ac6a428fa26 123 Point* bullet = new Point;
Siriagus 15:d5eb13c4c1c6 124 bullet->x = (int)(player.x + (player.width / 2)); //(player.facingLeft) ? (player.x-1) : (player.x + player.width);
Siriagus 8:9ac6a428fa26 125 bullet->y = player.y + 2;
Siriagus 11:adb68da98262 126 bullet->vx = (player.facingLeft) ? -4 : 4;
Siriagus 9:da608ae65df9 127 bullet->vy = 0;
Siriagus 8:9ac6a428fa26 128
Siriagus 8:9ac6a428fa26 129 bullets.push_back(bullet);
Siriagus 9:da608ae65df9 130 releasedBtnB = false;
Siriagus 8:9ac6a428fa26 131 }
Siriagus 9:da608ae65df9 132 else if (!input->read(Input::ButtonB))
Siriagus 9:da608ae65df9 133 releasedBtnB = true;
Siriagus 8:9ac6a428fa26 134
Siriagus 15:d5eb13c4c1c6 135 // Loop through bullets and move them + collision test
Siriagus 9:da608ae65df9 136 for (std::vector<Point*>::iterator it = bullets.begin(); it != bullets.end();)
Siriagus 8:9ac6a428fa26 137 {
Siriagus 15:d5eb13c4c1c6 138 Point* bullet = *it;
Siriagus 15:d5eb13c4c1c6 139
Siriagus 15:d5eb13c4c1c6 140 int x0; // left border of collision rect
Siriagus 15:d5eb13c4c1c6 141 int x1; // right border of collision rect
Siriagus 15:d5eb13c4c1c6 142
Siriagus 15:d5eb13c4c1c6 143 int oldX = bullet->x;
Siriagus 15:d5eb13c4c1c6 144 int newX = bullet->x + bullet->vx;
Siriagus 15:d5eb13c4c1c6 145
Siriagus 15:d5eb13c4c1c6 146 x0 = min(oldX, newX);
Siriagus 15:d5eb13c4c1c6 147 x1 = max(oldX, newX);
Siriagus 15:d5eb13c4c1c6 148
Siriagus 15:d5eb13c4c1c6 149 // Collision rect for bullet in this time step
Siriagus 15:d5eb13c4c1c6 150 Rectangle bulletColRect(x0, bullet->y, (x1-x0)+1, 1);
Siriagus 9:da608ae65df9 151
Siriagus 15:d5eb13c4c1c6 152 bool col = false;
Siriagus 15:d5eb13c4c1c6 153 // Delete if outside screen
Siriagus 15:d5eb13c4c1c6 154 if (newX < 0 || newX > WIDTH || bulletHitMap(bulletColRect, map)) // if outside screen
Siriagus 15:d5eb13c4c1c6 155 {
Siriagus 15:d5eb13c4c1c6 156 col = true;
Siriagus 15:d5eb13c4c1c6 157 }
Siriagus 15:d5eb13c4c1c6 158 else
Siriagus 9:da608ae65df9 159 {
Siriagus 15:d5eb13c4c1c6 160 // loop through all enemies
Siriagus 15:d5eb13c4c1c6 161 //bullet // point
Siriagus 15:d5eb13c4c1c6 162 //enemy // entity
Siriagus 15:d5eb13c4c1c6 163
Siriagus 15:d5eb13c4c1c6 164 if (!enemy->dead && bullet->x >= enemy->x && bullet->x <= enemy->getRight() && bullet->y >= enemy->y && bullet->y <= enemy->getBottom())
Siriagus 15:d5eb13c4c1c6 165 {
Siriagus 15:d5eb13c4c1c6 166 col = true;
Siriagus 15:d5eb13c4c1c6 167 // break; // todo: make for loop - iterate through all enemies
Siriagus 15:d5eb13c4c1c6 168 enemy->vx = bullet->vx / 2; // sends the dead enemy in the same direction as the incoming bullet
Siriagus 15:d5eb13c4c1c6 169 enemy->vy = -3; // sends the dead enemy upwards in the air, because of impact
Siriagus 15:d5eb13c4c1c6 170
Siriagus 15:d5eb13c4c1c6 171 enemy->dead = true;
Siriagus 15:d5eb13c4c1c6 172 // remove enemy - todo: make vector
Siriagus 15:d5eb13c4c1c6 173 }
Siriagus 15:d5eb13c4c1c6 174 }
Siriagus 15:d5eb13c4c1c6 175
Siriagus 15:d5eb13c4c1c6 176 if (!col)
Siriagus 15:d5eb13c4c1c6 177 {
Siriagus 15:d5eb13c4c1c6 178 ++it; // go to next element
Siriagus 15:d5eb13c4c1c6 179 bullet->x += bullet->vx; // update position
Siriagus 15:d5eb13c4c1c6 180 }
Siriagus 15:d5eb13c4c1c6 181 else
Siriagus 15:d5eb13c4c1c6 182 {
Siriagus 15:d5eb13c4c1c6 183 delete bullet;
Siriagus 9:da608ae65df9 184 it = bullets.erase(it); // go to next element
Siriagus 9:da608ae65df9 185 }
Siriagus 8:9ac6a428fa26 186
Siriagus 8:9ac6a428fa26 187 // TODO: Check for collisions
Siriagus 8:9ac6a428fa26 188 // TODO: Go both ways
Siriagus 8:9ac6a428fa26 189 }
Siriagus 7:678873947b29 190 }
Siriagus 7:678873947b29 191
Siriagus 7:678873947b29 192 void Game::render()
Siriagus 7:678873947b29 193 {
Siriagus 11:adb68da98262 194 // Draw map
Siriagus 11:adb68da98262 195 drawImage(map);
Siriagus 11:adb68da98262 196
Siriagus 12:8178fad5e660 197 // Draw player
Siriagus 13:7ab71c7c311b 198 drawImage(Image::Player, player.x, player.y, false, !player.facingLeft);
Siriagus 13:7ab71c7c311b 199
Siriagus 13:7ab71c7c311b 200 // Draw enemies
Siriagus 15:d5eb13c4c1c6 201 drawImage(Image::Enemy3, enemy->x, enemy->y, false, !enemy->facingLeft, enemy->dead);
Siriagus 12:8178fad5e660 202
Siriagus 12:8178fad5e660 203 /*
Siriagus 8:9ac6a428fa26 204 // Draw player - TODO: Make this a part of sprite class (so they can draw themselves)
Siriagus 8:9ac6a428fa26 205 int x0, x1, y0, y1;
Siriagus 8:9ac6a428fa26 206 x0 = (player.x < 0) ? 0 : player.x; // x0 = max(0,x);
Siriagus 8:9ac6a428fa26 207 y0 = (player.y < 0) ? 0 : player.y; // y0 = max(0,y);
Siriagus 8:9ac6a428fa26 208 x1 = (player.width + player.x > WIDTH) ? WIDTH : player.width + player.x; //x1 = min(WIDTH, width);
Siriagus 8:9ac6a428fa26 209 y1 = (player.height + player.y > HEIGHT) ? HEIGHT : player.height + player.y; //y1 = min(HEIGHT, height);
Siriagus 8:9ac6a428fa26 210
Siriagus 8:9ac6a428fa26 211 for (int i = y0; i < y1; ++i)
Siriagus 8:9ac6a428fa26 212 {
Siriagus 8:9ac6a428fa26 213 for (int j = x0; j < x1; ++j)
Siriagus 8:9ac6a428fa26 214 {
Siriagus 9:da608ae65df9 215 // If player is going right, obtain data from sprite in reverse order => render in reverse
Siriagus 11:adb68da98262 216 int xIndex = (player.facingLeft) ? (j-x0) : (player.width - 1 - (j-x0));
Siriagus 9:da608ae65df9 217
Siriagus 9:da608ae65df9 218 if (Image::Player[i-y0][xIndex])
Siriagus 8:9ac6a428fa26 219 lcd->setPixel(j,i);
Siriagus 8:9ac6a428fa26 220 }
Siriagus 12:8178fad5e660 221 }*/
Siriagus 8:9ac6a428fa26 222
Siriagus 9:da608ae65df9 223 // Render bullets
Siriagus 8:9ac6a428fa26 224 for (std::vector<Point*>::iterator it = bullets.begin(); it != bullets.end(); ++it)
Siriagus 8:9ac6a428fa26 225 {
Siriagus 8:9ac6a428fa26 226 int x, y;
Siriagus 8:9ac6a428fa26 227 x = (*it)->x;
Siriagus 8:9ac6a428fa26 228 y = (*it)->y;
Siriagus 8:9ac6a428fa26 229
Siriagus 8:9ac6a428fa26 230 if (x >= 0 && x < WIDTH && y >= 0 && y < HEIGHT) // Boundary check
Siriagus 8:9ac6a428fa26 231 lcd->setPixel(x,y);
Siriagus 8:9ac6a428fa26 232 }
Siriagus 15:d5eb13c4c1c6 233
Siriagus 15:d5eb13c4c1c6 234 // Draw pause
Siriagus 15:d5eb13c4c1c6 235 if (paused)
Siriagus 15:d5eb13c4c1c6 236 {
Siriagus 15:d5eb13c4c1c6 237 lcd->drawRect(24, 13, 40, 13, 0); // outline
Siriagus 15:d5eb13c4c1c6 238 lcd->drawRect(25, 14, 38, 11, 2); // white fill
Siriagus 15:d5eb13c4c1c6 239 lcd->printString("Paused", 27, 2); // text
Siriagus 15:d5eb13c4c1c6 240 }
Siriagus 13:7ab71c7c311b 241 }
Siriagus 13:7ab71c7c311b 242
Siriagus 13:7ab71c7c311b 243 // Collision test between entites and map
Siriagus 13:7ab71c7c311b 244 void Game::moveWithCollisionTest(Entity* entity, const int map[HEIGHT][WIDTH])
Siriagus 13:7ab71c7c311b 245 {
Siriagus 13:7ab71c7c311b 246 int x = entity->x;
Siriagus 13:7ab71c7c311b 247 int y = entity->y;
Siriagus 13:7ab71c7c311b 248 int steps = abs(entity->vx); // how many units (pixels) the entity should move in said direction
Siriagus 13:7ab71c7c311b 249 bool collision; // true if colliding
Siriagus 13:7ab71c7c311b 250
Siriagus 13:7ab71c7c311b 251 // Check x-axis
Siriagus 13:7ab71c7c311b 252 if (entity->vx > 0) // moving right
Siriagus 13:7ab71c7c311b 253 {
Siriagus 13:7ab71c7c311b 254 int entityRight = x + entity->width - 1; // Need to check right border of entity, since it is moving right
Siriagus 13:7ab71c7c311b 255
Siriagus 13:7ab71c7c311b 256 while(steps--) // While it still have more movement left
Siriagus 13:7ab71c7c311b 257 {
Siriagus 13:7ab71c7c311b 258 collision = false;
Siriagus 13:7ab71c7c311b 259 for (int i = 0; i < entity->height; ++i) // Loop through all vertical points on the right hand side of the entity (y+i)
Siriagus 13:7ab71c7c311b 260 {
Siriagus 13:7ab71c7c311b 261 if (map[y+i][entityRight+1]) // If moving to the right leads to collision for given y+i
Siriagus 13:7ab71c7c311b 262 {
Siriagus 15:d5eb13c4c1c6 263 // Slope + allows player to climb to top of platform by going right if it hits close to top of wall.
Siriagus 15:d5eb13c4c1c6 264 if (!map[y+i-1][entityRight+1] && entity->onGround)
Siriagus 15:d5eb13c4c1c6 265 {
Siriagus 15:d5eb13c4c1c6 266 entity->vy = -1;
Siriagus 15:d5eb13c4c1c6 267 }
Siriagus 15:d5eb13c4c1c6 268 else
Siriagus 15:d5eb13c4c1c6 269 {
Siriagus 15:d5eb13c4c1c6 270 collision = true; // Then collision is true
Siriagus 15:d5eb13c4c1c6 271 break; // Skip the for loop, no need for further testing
Siriagus 15:d5eb13c4c1c6 272 }
Siriagus 15:d5eb13c4c1c6 273
Siriagus 13:7ab71c7c311b 274 }
Siriagus 13:7ab71c7c311b 275 }
Siriagus 13:7ab71c7c311b 276
Siriagus 13:7ab71c7c311b 277 if (collision) // If collision
Siriagus 13:7ab71c7c311b 278 break; // skip the while loop, entity can not move further, even though its velocity is higher
Siriagus 13:7ab71c7c311b 279 else
Siriagus 13:7ab71c7c311b 280 ++entityRight; // Move entity one px to the right
Siriagus 13:7ab71c7c311b 281 }
Siriagus 13:7ab71c7c311b 282
Siriagus 13:7ab71c7c311b 283 entity->x = entityRight - (entity->width - 1); // Update entity's position. Need to set upper-left pixel.
Siriagus 13:7ab71c7c311b 284 }
Siriagus 13:7ab71c7c311b 285 else // moving left
Siriagus 13:7ab71c7c311b 286 {
Siriagus 13:7ab71c7c311b 287 while(steps--) // While still movement left
Siriagus 13:7ab71c7c311b 288 {
Siriagus 13:7ab71c7c311b 289 collision = false;
Siriagus 13:7ab71c7c311b 290
Siriagus 13:7ab71c7c311b 291
Siriagus 13:7ab71c7c311b 292 for (int i = 0; i < entity->height; ++i) // Check for all y-positions
Siriagus 13:7ab71c7c311b 293 {
Siriagus 13:7ab71c7c311b 294 if (map[y+i][x-1]) // If solid block
Siriagus 13:7ab71c7c311b 295 {
Siriagus 15:d5eb13c4c1c6 296 if (!map[y+i-1][x-1] && entity->onGround) // If slope or close to top of wall (=> can climb by going left).
Siriagus 15:d5eb13c4c1c6 297 {
Siriagus 15:d5eb13c4c1c6 298 entity->vy = -1;
Siriagus 15:d5eb13c4c1c6 299 }
Siriagus 15:d5eb13c4c1c6 300 else
Siriagus 15:d5eb13c4c1c6 301 {
Siriagus 15:d5eb13c4c1c6 302 collision = true;
Siriagus 15:d5eb13c4c1c6 303 break; // Collision detected, no further testing required
Siriagus 15:d5eb13c4c1c6 304 }
Siriagus 13:7ab71c7c311b 305 }
Siriagus 13:7ab71c7c311b 306 }
Siriagus 13:7ab71c7c311b 307
Siriagus 13:7ab71c7c311b 308 if (collision)
Siriagus 13:7ab71c7c311b 309 break;
Siriagus 13:7ab71c7c311b 310 else
Siriagus 13:7ab71c7c311b 311 --x; // Move to the left if no collision is detected
Siriagus 13:7ab71c7c311b 312 }
Siriagus 13:7ab71c7c311b 313
Siriagus 13:7ab71c7c311b 314 entity->x = x;
Siriagus 13:7ab71c7c311b 315 }
Siriagus 13:7ab71c7c311b 316
Siriagus 13:7ab71c7c311b 317 // Check collision with map in y-direction - works the same way as the x-axis, except for other axis
Siriagus 13:7ab71c7c311b 318
Siriagus 13:7ab71c7c311b 319 x = entity->x;
Siriagus 13:7ab71c7c311b 320 y = entity->y;
Siriagus 13:7ab71c7c311b 321 steps = abs(entity->vy);
Siriagus 13:7ab71c7c311b 322
Siriagus 13:7ab71c7c311b 323 if (entity->vy > 0) // downwards
Siriagus 13:7ab71c7c311b 324 {
Siriagus 13:7ab71c7c311b 325 int entityBottom = y + entity->height - 1; // Need to check if bottom part collides
Siriagus 13:7ab71c7c311b 326 while(steps--) // Still movement left
Siriagus 13:7ab71c7c311b 327 {
Siriagus 13:7ab71c7c311b 328 collision = false;
Siriagus 13:7ab71c7c311b 329 for (int i = 0; i < entity->width; ++i) // Loop through all x-position on lower part of entity
Siriagus 13:7ab71c7c311b 330 {
Siriagus 13:7ab71c7c311b 331 if (map[entityBottom+1][x+i]) // If moving the entity one step down for a given (x+i)-position gives a collision
Siriagus 13:7ab71c7c311b 332 {
Siriagus 13:7ab71c7c311b 333 collision = true;
Siriagus 13:7ab71c7c311b 334 break; // No further testing required
Siriagus 13:7ab71c7c311b 335 }
Siriagus 13:7ab71c7c311b 336 }
Siriagus 13:7ab71c7c311b 337
Siriagus 13:7ab71c7c311b 338 if (collision) // If collision
Siriagus 13:7ab71c7c311b 339 {
Siriagus 13:7ab71c7c311b 340 entity->vy = 0; // Set vertical velocity to 0 (playe
Siriagus 13:7ab71c7c311b 341 entity->onGround = true; // entity has hit ground
Siriagus 13:7ab71c7c311b 342 break; // Skip the while loop as the entity can not move further downwards
Siriagus 13:7ab71c7c311b 343 }
Siriagus 13:7ab71c7c311b 344 else // Can safely move entity without collision
Siriagus 15:d5eb13c4c1c6 345 {
Siriagus 13:7ab71c7c311b 346 ++entityBottom; // Move entity one step down
Siriagus 15:d5eb13c4c1c6 347 entity->onGround = false;
Siriagus 15:d5eb13c4c1c6 348 }
Siriagus 13:7ab71c7c311b 349 }
Siriagus 13:7ab71c7c311b 350
Siriagus 13:7ab71c7c311b 351 entity->y = entityBottom - (entity->height - 1); // Update position when done moving, remember that entity.y refers to upper part of the entity
Siriagus 13:7ab71c7c311b 352 }
Siriagus 13:7ab71c7c311b 353 else // moving up, check collision from top
Siriagus 13:7ab71c7c311b 354 {
Siriagus 13:7ab71c7c311b 355 while(steps--) // Still movement left
Siriagus 13:7ab71c7c311b 356 {
Siriagus 13:7ab71c7c311b 357 collision = false;
Siriagus 13:7ab71c7c311b 358
Siriagus 13:7ab71c7c311b 359 for (int i = 0; i < entity->width; ++i) // Check for all x-positions
Siriagus 13:7ab71c7c311b 360 {
Siriagus 13:7ab71c7c311b 361 if (map[y-1][x+i]) // If moving upwards gives collision for a given x+i
Siriagus 13:7ab71c7c311b 362 {
Siriagus 13:7ab71c7c311b 363 collision = true; // Then we have a collision
Siriagus 13:7ab71c7c311b 364 break; // No further testing needed, skip for loop
Siriagus 13:7ab71c7c311b 365 }
Siriagus 13:7ab71c7c311b 366 }
Siriagus 13:7ab71c7c311b 367
Siriagus 13:7ab71c7c311b 368 if (collision) // If collision was detected
Siriagus 13:7ab71c7c311b 369 {
Siriagus 13:7ab71c7c311b 370 entity->vy = 0; // Set vertical velocity to zero
Siriagus 13:7ab71c7c311b 371 break; // Skip while loop as entity can not move further up
Siriagus 13:7ab71c7c311b 372 }
Siriagus 13:7ab71c7c311b 373 else // If safe to move for all x-values
Siriagus 13:7ab71c7c311b 374 --y; // Move entity one step up
Siriagus 13:7ab71c7c311b 375 }
Siriagus 13:7ab71c7c311b 376
Siriagus 13:7ab71c7c311b 377 entity->y = y; // Update vertical position of entity
Siriagus 13:7ab71c7c311b 378 }
Siriagus 15:d5eb13c4c1c6 379 }
Siriagus 15:d5eb13c4c1c6 380
Siriagus 15:d5eb13c4c1c6 381 bool Game::hitTestRect(Rectangle r1, Rectangle r2)
Siriagus 15:d5eb13c4c1c6 382 {
Siriagus 15:d5eb13c4c1c6 383 return ((r1.x + r1.width > r2.x) // r1's right edge to the right of r2's left edge
Siriagus 15:d5eb13c4c1c6 384 && (r1.x < r2.x + r2.width) // r1's left edge to the left of r2's right edge
Siriagus 15:d5eb13c4c1c6 385 && (r1.y + r2.height > r2.y) // r1's bottom lower than r2's top
Siriagus 15:d5eb13c4c1c6 386 && (r1.y < r2.y + r2.height)); // r1's top higher than r2's bottom
Siriagus 15:d5eb13c4c1c6 387
Siriagus 15:d5eb13c4c1c6 388 // Note: Right border: r1.x + r1.width - 1, but we don't need to subtract 1 as we use > instead of >=
Siriagus 15:d5eb13c4c1c6 389 }
Siriagus 15:d5eb13c4c1c6 390
Siriagus 15:d5eb13c4c1c6 391 bool Game::bulletHitMap(Rectangle &bulletColRect, const int map[HEIGHT][WIDTH])
Siriagus 15:d5eb13c4c1c6 392 {
Siriagus 15:d5eb13c4c1c6 393 for (int j = 0; j < bulletColRect.width; ++j)
Siriagus 15:d5eb13c4c1c6 394 {
Siriagus 15:d5eb13c4c1c6 395 if (map[bulletColRect.y][bulletColRect.x + j])
Siriagus 15:d5eb13c4c1c6 396 return true;
Siriagus 15:d5eb13c4c1c6 397 }
Siriagus 15:d5eb13c4c1c6 398
Siriagus 15:d5eb13c4c1c6 399 return false;
Siriagus 7:678873947b29 400 }