Initial publish
Dependencies: mbed
Fork of el17dg by
game/game.cpp
- Committer:
- Noximilien
- Date:
- 2019-05-07
- Revision:
- 40:e3bbda7444fa
- Parent:
- 39:ca77a6d574e6
File content as of revision 40:e3bbda7444fa:
#include "mbed.h" #include "N5110.h" #include "Gamepad.h" #include "collision_lib.h" #include "models.h" #include "main.h" #include "game.h" #include "gameobject.h" #include "boss.h" #include "enemies.h" #include "constants.h" #include "stars.h" #include "player.h" #include "hud.h" #include "gameovermanager.h" const int increase_difficulty = 70; int GameGlobals::game_score = 0; int GameGlobals::score_count_for_difficulty = 0; int GameGlobals::player_lifes = 3; int GameGlobals::high_score = 0; bool GameGlobals::is_shield_on = false; int GameGlobals::score_count_for_boss_mode = 0; Boss boss; Enemies enemies; Enemy enemy; Stars stars; Player player; GameOverManager gameOverManager; Hud hud; void Game::updateAndDrawGameplay() { checkButtonToShoot(); player.updateAndDraw(); player.updateAndDrawBlasts(); stars.updateAndDrawSmallStars(); stars.updateAndDrawMediumStars(); stars.starsSpawnDelay(); increaseGameDifficultyAndEnemySpawnDelay(); hud.displayLifes(); hud.drawScore(); collideEnemiesAndBlasts(); collideEnemiesBlastsAndPlayer(); collideEnemiesAndPlayer(); enemies.updateAndDrawEnemies(); enemies.updateAndDrawEnemyBlasts(); boss.updateAndDrawBossBlasts(); if (checkForGameOver()) { game_state = GameState_gameover;} if (is_boss_active) { game_state = GameState_boss_cutscene;} } void Game::updateAndDrawGameover() { gameOverManager.updateAndDraw(); lcd.normalMode(); if (gamepad.check_event(gamepad.Y_PRESSED) && !gameOverManager.isPlayingAnimation()) { gameOverManager.reset(); game_state = GameState_newgame; } } void Game::updateAndDrawBossCutscene() { boss.updateCutscene(); enemies.updateAndDrawEnemyBlasts(); boss.draw(); player.draw(); stars.updateAndDrawSmallStars(); stars.updateAndDrawMediumStars(); gamepad.tone(60,2); for (int i = 0; i < enemies.max_enemies; ++i) { enemies.enemies[i].active = false; } for (int i = 0; i < enemies.max_enemy_blasts; ++i) { enemies.enemy_blasts[i].active = false; } if (boss.isFinishedCutscene()) { game_state = GameState_boss_gameplay; boss.resetCutscene(); } } void Game::updateAndDrawBossGameplay() { checkButtonToShoot(); enemies.updateAndDrawEnemyBlasts(); player.updateAndDraw(); player.updateAndDrawBlasts(); stars.updateAndDrawSmallStars(); stars.starsSpawnDelay(); hud.displayLifes(); hud.drawScore(); boss.updateAndDrawBossBlasts(); collideBossAndPlayerBlasts(); collideBossBlastsAndPlayer(); is_boss_active = boss.updateAndDrawBoss(); if (checkForGameOver()) { game_state = GameState_gameover;} if (!is_boss_active) { game_state = GameState_gameplay;} } /** * This is the main function of game.cpp, where the actual gameplay happens. * Here all other functions are activeated, and when the player dies, it * returns back to main menu "main.cpp". */ bool Game::updateAndDraw() { if (game_state == GameState_newgame) { DG_PRINTF("start game \n"); startNewGame(); } if (game_state == GameState_gameplay) { updateAndDrawGameplay(); } else if (game_state == GameState_boss_cutscene) { updateAndDrawBossCutscene(); } else if (game_state == GameState_boss_gameplay) { updateAndDrawBossGameplay(); } else if (game_state == GameState_gameover) { updateAndDrawGameover(); } return checkIfNeedsToReturnToMenu(); } void Game::checkButtonToShoot(){ if (gamepad.check_event(gamepad.X_PRESSED) && !GameGlobals::is_shield_on){ // Checking the button second time to prevent double blast. gamepad.check_event(gamepad.X_PRESSED); player.fireNewBlast(); gamepad.tone(200,0.1); } } /** * This function checks whether the requirments for the collision of the two objects, * are met. When those requirments are met the collision of two objects function will * be checking wheter the boundaries of the objects colide. If they do, the blast * becomes inactive, in game score increases and enemy dies. */ void Game::collideEnemiesAndBlasts() { for (int i = 0; i < enemies.max_enemies; ++i) { for (int j = 0; j < player.max_player_blasts; ++j) { Enemy& enemy = enemies.enemies[i]; GameObject& blast = player.blasts[j]; if (enemy.active && !enemy.dead && blast.active) { bool collision = circleCollideTwoObjects( enemy.pos, enemies.enemy_bounds, blast.pos, player.blast_bounds ); if (collision) { enemy.die(); DG_PRINTF("enemy got hit and dies \n"); GameGlobals::game_score += 30; GameGlobals::score_count_for_difficulty +=30; GameGlobals::score_count_for_boss_mode += 30; blast.active = false; } } } } } /** * This code does the same work as the one before but with two other objects. * It checks whether the requirments for the collision of the two objects, * are met. When those requirments are met the collision of two objects function will * be checking wheter the boundaries of the objects colide. If they do, the blast * becomes inactive, in game score increases and enemy dies. */ void Game::collideEnemiesBlastsAndPlayer() { for (int i = 0; i < enemies.max_enemies; ++i) { GameObject& blast = enemies.enemy_blasts[i]; if (blast.active) { bool collision = circleCollideTwoObjects( player.pos, player.player_bounds, blast.pos, enemies.enemy_blast_bounds ); if (collision) { if (!GameGlobals::is_shield_on){ gamepad.tone(423,0.4); GameGlobals::player_lifes -= 1; DG_PRINTF("lost a life from blast. left: %i \n", GameGlobals::player_lifes); blast.active = false; }else{ blast.active = false; gamepad.tone(700,0.6); } } } } } /** * This code does the same work as the one before but with two other object. * of enemy ship and the player's ship */ void Game::collideEnemiesAndPlayer() { for (int i = 0; i < enemies.max_enemies; ++i) { Enemy& enemy = enemies.enemies[i]; if (enemy.active && !enemy.dead) { bool collision = circleCollideTwoObjects( player.pos, player.player_bounds, enemy.pos, enemies.enemy_bounds ); if (collision) { GameGlobals::player_lifes -= 1; enemy.die(); DG_PRINTF("enemy got hit from collsion and dies"); DG_PRINTF("lost a life from enemy col. left: %i \n", GameGlobals::player_lifes); } } } } void Game::collideBossAndPlayerBlasts() { for (int i = 0; i < player.max_player_blasts; ++i) { GameObject& blast = player.blasts[i]; if (blast.active) { bool collision = circleCollideTwoObjects( boss.pos, boss.boss_bounds, blast.pos, player.blast_bounds ); if (collision) { boss.boss_lives -= 1; gamepad.tone(123,0.4); blast.active = false; DG_PRINTF("boss has. left: %i \n", boss.boss_lives); } } } } void Game::collideBossBlastsAndPlayer() { for (int i = 0; i < boss.max_boss_blasts; ++i) { GameObject& blast = boss.boss_blasts[i]; if (blast.active) { bool collision = circleCollideTwoObjects( player.pos, player.player_bounds, blast.pos, boss.boss_blast_bounds ); DG_PRINTF("player pos:%i,%i; offset:%i,%i; radius:%f.3; \n", player.pos.x, player.pos.y, player.player_bounds.center.x, player.player_bounds.center.y, player.player_bounds.radius); DG_PRINTF("blast pos:%i,%i; offset:%i,%i; radius:%f.3; \n", blast.pos.x, blast.pos.y, boss.boss_blast_bounds.center.x, boss.boss_blast_bounds.center.y, boss.boss_blast_bounds.radius); if (collision) { if (!GameGlobals::is_shield_on){ gamepad.tone(423,0.4); GameGlobals::player_lifes -= 1; blast.active = false; DG_PRINTF("collision happened;\n"); DG_PRINTF("lost a life from blast. left: %i \n", GameGlobals::player_lifes); }else{ blast.active = false; gamepad.tone(700,0.6); } } } } } /** * This function resets all the values to their intial states when the game is * first began when the player dies and wants to restart the game. * It does not reset the values when the game is paused. */ void Game::startNewGame() { is_boss_active = false; game_state = GameState_gameplay; player.pos.x = 0; //player was defined in player.h player.pos.y = 24; stars.stars_delay = 0; enemy_ship_delay_max = 40; enemy_ship_delay_counter = enemy_ship_delay_max; GameGlobals::is_shield_on = false; GameGlobals::game_score = 0; GameGlobals::score_count_for_difficulty = 0; GameGlobals::player_lifes = 3; GameGlobals::score_count_for_boss_mode = 0; hud.resetRedLed(); enemies.enemy_blast_speed = 3; enemy.enemy_speed = 1; gamepad.check_event(gamepad.START_PRESSED); for (int i = 0; i < enemies.max_enemies; ++i) { enemies.enemies[i].active = false; } for (int i = 0; i < player.max_player_blasts; ++i) { player.blasts[i].active = false; } for (int i = 0; i < enemies.max_enemy_blasts; ++i) { enemies.enemy_blasts[i].active = false; } for (int i = 0; i < boss.max_boss_blasts; ++i) { boss.boss_blasts[i].active = false; } gamepad.check_event(gamepad.START_PRESSED); } /** * A function tbat delays enemy spawn on low game score. * It decreases the enemy spawn delay as in game score increases. * The enemy spawn delay is located in game.cpp because the game difficulty * depends on the on how fast enemy appears. */ void Game::increaseGameDifficultyAndEnemySpawnDelay(){ if (enemy_ship_delay_counter <= 0){ enemies.spawnNewEnemy(); enemy_ship_delay_counter = enemy_ship_delay_max; } else { enemy_ship_delay_counter -= 1;} if (enemy_ship_delay_max >= 4 && GameGlobals::score_count_for_difficulty >= increase_difficulty){ //decrease enemy delay spawn. enemy_ship_delay_max -= 3; if (enemy_ship_delay_max <= 20 && enemy_ship_delay_max >= 15){ enemies.enemy_blast_speed += 1; enemy.enemy_speed += 1; } GameGlobals::score_count_for_difficulty = 0; } if (GameGlobals::score_count_for_boss_mode >= 400){ is_boss_active = true; lcd.inverseMode(); } } bool Game::forceShildActivate(){ if (gamepad.check_event(gamepad.R_PRESSED)){ GameGlobals::is_shield_on = !GameGlobals::is_shield_on; } return GameGlobals::is_shield_on; } /** * This is a single line function to set the player lifes to 0 when the. * game is over. */ bool Game::checkForGameOver() { return GameGlobals::player_lifes <= 0; } /** This small statment checks whether the pause button was pressed or not. * If it was pressed, then the game will go back to main menu and will save * the current status of the object until the game is continued. */ bool Game::checkIfNeedsToReturnToMenu(){ bool want_to_pause = false; if (gamepad.check_event(gamepad.START_PRESSED)){ DG_PRINTF("game paused\n"); gamepad.check_event(gamepad.START_PRESSED); gamepad.check_event(gamepad.A_PRESSED); want_to_pause = true; } return want_to_pause; }