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
Diff: Game.cpp
- Revision:
- 16:caf613d5b85e
- Parent:
- 15:d5eb13c4c1c6
- Child:
- 17:d6a3b29cab31
--- a/Game.cpp Sun May 10 09:37:51 2015 +0000 +++ b/Game.cpp Sun May 10 13:14:33 2015 +0000 @@ -3,7 +3,7 @@ Serial pc(USBTX, USBRX); // TO DELETE - DEBUGGING ONLY void Game::init() -{ +{ paused = false; // Set initial values for the player @@ -11,15 +11,19 @@ player.y = 5; // start y player.width = player.height = 5; // important that this is correct, see size of Image::Player in Resources.h player.onGround = false; - - enemy = new Enemy(75, 3, 6, 5); - enemy->vx = -2; +} + +void Game::spawnEnemy() +{ + Enemy *enemy = new Enemy(75, 3, 5, 5, Enemy::SIMPLE); + enemy->vx = -1; enemy->facingLeft = true; + enemies.push_back(enemy); } // Functions void Game::update(float dt) -{ +{ // Pause button input if (input->read(Input::ButtonC)) { @@ -36,8 +40,9 @@ if (paused) return; - - + if ((rand() % 100) > 93) + spawnEnemy(); + // Handle input, should be its own function switch(input->joystick->getDirection()) { @@ -60,23 +65,11 @@ break; } - // Random movement for enemies - if (enemy->onGround && (rand() % 100) > 97) // 3 % chance - { - // jump - enemy->vy = -3; - enemy->onGround = false; - } - else if ((rand() % 100) > 98) // 2% chance - { - // switch direction - enemy->vx *= -1; - enemy->facingLeft = (enemy->vx < 0); - } + + // MOVE: Random enemies // Gravity player.vy += 1; - enemy->vy += 1; // Check if player is trying to jump. Player can only jump if it's on the ground if (input->read(Input::ButtonA) && player.onGround) @@ -89,32 +82,10 @@ if (player.vy > TERMINAL_VELOCITY) player.vy = TERMINAL_VELOCITY; moveWithCollisionTest(&player, map); - - if (!enemy->dead) - moveWithCollisionTest(enemy, map); - else - { - enemy->y += enemy->vy; - enemy->x += enemy->vx; - } - // else if (enemy->y >= HEIGHT) ; // TODO : delete enemy + moveEnemies(); - // Enemy AI - if (!enemy->dead) - { - int nextRight = enemy->getRight() + 1; // Next position of right edge if enemy moves to the right - for (int i = 0; i < enemy->height; ++i) // Check for all heighs - { - // Check if crashing if moving right or left. Bounds should already be limited by moveWithCollisionTest! - // will also try to climb a slope if it can find one - 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])) - { - enemy->vx *= -1; // move in opposite direction - enemy->facingLeft = !enemy->facingLeft; // toggle direction - break; // no further testing required - } - } - } + + // else if (enemy->y >= HEIGHT) ; // TODO : delete enemy // Check if bullet should be fired if (input->read(Input::ButtonB) && releasedBtnB) @@ -160,16 +131,20 @@ // loop through all enemies //bullet // point //enemy // entity - - if (!enemy->dead && bullet->x >= enemy->x && bullet->x <= enemy->getRight() && bullet->y >= enemy->y && bullet->y <= enemy->getBottom()) + for (std::vector<Enemy*>::iterator it = enemies.begin(); it != enemies.end(); ++it) { - col = true; - // break; // todo: make for loop - iterate through all enemies - enemy->vx = bullet->vx / 2; // sends the dead enemy in the same direction as the incoming bullet - enemy->vy = -3; // sends the dead enemy upwards in the air, because of impact + Enemy *enemy = *it; - enemy->dead = true; - // remove enemy - todo: make vector + if (!enemy->dead && bullet->x >= enemy->x && bullet->x <= enemy->getRight() && bullet->y >= enemy->y && bullet->y <= enemy->getBottom()) + { + col = true; + // break; // todo: make for loop - iterate through all enemies + enemy->vx = bullet->vx / 2; // sends the dead enemy in the same direction as the incoming bullet + enemy->vy = -3; // sends the dead enemy upwards in the air, because of impact + + enemy->dead = true; + // remove enemy - todo: make vector + } } } @@ -198,28 +173,12 @@ drawImage(Image::Player, player.x, player.y, false, !player.facingLeft); // Draw enemies - drawImage(Image::Enemy3, enemy->x, enemy->y, false, !enemy->facingLeft, enemy->dead); - - /* - // Draw player - TODO: Make this a part of sprite class (so they can draw themselves) - int x0, x1, y0, y1; - x0 = (player.x < 0) ? 0 : player.x; // x0 = max(0,x); - y0 = (player.y < 0) ? 0 : player.y; // y0 = max(0,y); - x1 = (player.width + player.x > WIDTH) ? WIDTH : player.width + player.x; //x1 = min(WIDTH, width); - y1 = (player.height + player.y > HEIGHT) ? HEIGHT : player.height + player.y; //y1 = min(HEIGHT, height); - - for (int i = y0; i < y1; ++i) - { - for (int j = x0; j < x1; ++j) - { - // If player is going right, obtain data from sprite in reverse order => render in reverse - int xIndex = (player.facingLeft) ? (j-x0) : (player.width - 1 - (j-x0)); - - if (Image::Player[i-y0][xIndex]) - lcd->setPixel(j,i); - } - }*/ - + for (std::vector<Enemy*>::iterator it = enemies.begin(); it != enemies.end(); ++it) + { + Enemy *enemy = *it; + drawImage(Image::EnemySimple, enemy->x, enemy->y, false, !enemy->facingLeft, enemy->dead); + } + // Render bullets for (std::vector<Point*>::iterator it = bullets.begin(); it != bullets.end(); ++it) { @@ -256,6 +215,11 @@ while(steps--) // While it still have more movement left { collision = false; + + // Wrapping + if (entityRight+1 >= WIDTH) + entityRight = -1;// wants entityRight = -1, so next check is entityRight 0*/ + for (int i = 0; i < entity->height; ++i) // Loop through all vertical points on the right hand side of the entity (y+i) { if (map[y+i][entityRight+1]) // If moving to the right leads to collision for given y+i @@ -280,6 +244,10 @@ ++entityRight; // Move entity one px to the right } + // If wrap didn't work, make sure entity is on the correct side of the map + if (entityRight < 0) + entityRight = WIDTH-1; + entity->x = entityRight - (entity->width - 1); // Update entity's position. Need to set upper-left pixel. } else // moving left @@ -288,9 +256,14 @@ { collision = false; + // Wrap around map + if (x-1 < 0) + x = WIDTH; // causes x-1 in the next check to be WIDTH - 1 - for (int i = 0; i < entity->height; ++i) // Check for all y-positions + // Check for all y-positions + for (int i = 0; i < entity->height; ++i) { + if (map[y+i][x-1]) // If solid block { if (!map[y+i-1][x-1] && entity->onGround) // If slope or close to top of wall (=> can climb by going left). @@ -311,11 +284,12 @@ --x; // Move to the left if no collision is detected } - entity->x = x; + x %= WIDTH; // In case wrapping caused entity to crash with wall on other side, x should be 0 instead of WIDTH (invalid). + + entity->x = x; // update position } // Check collision with map in y-direction - works the same way as the x-axis, except for other axis - x = entity->x; y = entity->y; steps = abs(entity->vy); @@ -326,9 +300,10 @@ while(steps--) // Still movement left { collision = false; + for (int i = 0; i < entity->width; ++i) // Loop through all x-position on lower part of entity - { - if (map[entityBottom+1][x+i]) // If moving the entity one step down for a given (x+i)-position gives a collision + { + if (map[(entityBottom+1) % HEIGHT][x+i]) // If moving the entity one step down for a given (x+i)-position gives a collision { collision = true; break; // No further testing required @@ -348,17 +323,24 @@ } } - entity->y = entityBottom - (entity->height - 1); // Update position when done moving, remember that entity.y refers to upper part of the entity + // Wrapping + y = (entityBottom - (entity->height - 1)); + if (y >= HEIGHT) // if completely outside map + y = -entity->height; // wrap to top of map + + entity->y = y; // (entityBottom - (entity->height - 1)); // Update position when done moving, remember that entity.y refers to upper part of the entity } else // moving up, check collision from top { while(steps--) // Still movement left { collision = false; - + for (int i = 0; i < entity->width; ++i) // Check for all x-positions { - if (map[y-1][x+i]) // If moving upwards gives collision for a given x+i + int y1 = ((y-1) + HEIGHT) % HEIGHT; // In case negative, because of wrapping + + if (map[y1][x+i]) // If moving upwards gives collision for a given x+i { collision = true; // Then we have a collision break; // No further testing needed, skip for loop @@ -374,6 +356,10 @@ --y; // Move entity one step up } + // Wrapping + if (y + (entity->height - 1) < 0) // completely outside map (bottom of entity over top of map) + y = HEIGHT-1 - entity->height - 1; // Sets the altitude. + entity->y = y; // Update vertical position of entity } } @@ -397,4 +383,53 @@ } return false; +} + +void Game::moveEnemies() +{ + for (std::vector<Enemy*>::iterator it = enemies.begin(); it != enemies.end(); ++it) + { + Enemy *enemy = *it; + + // Random movement for enemies + if (enemy->onGround && (rand() % 100) > 97) // 3 % chance + { + // jump + enemy->vy = -3; + enemy->onGround = false; + } + else if ((rand() % 100) > 98) // 2% chance + { + // switch direction + enemy->vx *= -1; + enemy->facingLeft = (enemy->vx < 0); + } + + // Gravity + enemy->vy += 1; + + if (!enemy->dead) + { + moveWithCollisionTest(enemy, map); + + // Enemy AI + int nextRight = enemy->getRight() + 1; // Next position of right edge if enemy moves to the right + nextRight %= WIDTH; // wrapping + for (int i = 0; i < enemy->height; ++i) // Check for all heighs + { + // Check if crashing if moving right or left. Bounds should already be limited by moveWithCollisionTest! + if (map[enemy->y + i][nextRight] || map[enemy->y + i][enemy->x - 1]) + { + enemy->vx *= -1; // move in opposite direction + enemy->facingLeft = !enemy->facingLeft; // toggle direction + break; // no further testing required + } + } + } + else + { + enemy->y += enemy->vy; + enemy->x += enemy->vx; + } + } } \ No newline at end of file