This code contains the game Starship designed for the STM32F429i-DISC1 board. It requires a keyboard to play.
Dependencies: Starship LCD_DISCO_F429ZI USBHost mbed
Diff: Game.c
- Revision:
- 1:527a11035e0b
diff -r c9afe145b57b -r 527a11035e0b Game.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Game.c Fri Nov 17 02:23:33 2017 +0000 @@ -0,0 +1,247 @@ +#include "Game.h" + + +int16_t level; +int16_t levelScore; +int16_t totalScore; +int16_t lives; +int8_t X_DIR; +int8_t Y_DIR; +int8_t didUserRequestFire; + +void newGame() +{ + lives = STARTING_LIFE_TOTAL; + level = 1; + levelScore = 0; + totalScore = 0; +} +void newLevel() +{ + X_DIR = NO_DIR; + Y_DIR = NO_DIR; + clearEnemies(); + clearBullets(); + resetPlayer(); + clearPowerUps(); + levelScore = 0; +} +char didLoseLife() +{ + return player.health ? 0 : 1; +} +char isGameOver() +{ + return lives ? 0 : 1; +} +int8_t shouldAddEnemy() +{ + return enemyCount<(level+2) ? 1 : 0; +} +void addRandomEnemy() +{ + int16_t x_pos = randomInt(0,LCD_WIDTH-ENEMY_WIDTH); + int8_t x_vel_var = level>=3 ? 3 : level; + int16_t x_vel = randomInt(-x_vel_var,x_vel_var)*SLOWEST_ENEMY_X_VELOCITY; + int8_t y_vel_var = level>=3 ? 3 : level; + int16_t y_vel = randomInt(1,y_vel_var)*SLOWEST_ENEMY_Y_VELOCITY; + int16_t health = randomInt(1,level); + addEnemy(x_pos,x_vel,y_vel,health); +} +char didLevelUp() +{ + if(levelScore>= level*4+6) + return 1; + return 0; +} +void callMultiFunc() +{ + callMultiFuncEnemy(); + callMultiFuncBullet(); + callMultiFuncPowerUp();//DEBUG!!! + callMultiFuncPlayer();//DEBUG!!! +} +void addWideShotBullets() +{ + int16_t xP = getPlayerBulletPos(X_ID); + int16_t yP = getPlayerBulletPos(Y_ID); + int16_t yV = -DEFAULT_BULLET_SPEED; + int16_t xV_Right = (int16_t)(yV * WIDE_SHOT_X_VELOCITY_FACTOR); + int16_t xV_Left = -xV_Right; + int8_t powr = player.powerShotTimer ? POWER_BULLET_ID : DEFAULT_BULLET_ID; + addPlayerBullet(xP, yP, xV_Right, yV, powr, NOT_BOMB_ID); + addPlayerBullet(xP, yP, xV_Left, yV, powr, NOT_BOMB_ID); +} + +void firePlayerBullet() +{ + player.gunTimer = PLAYER_FIRE_PERIOD; + int16_t xP = getPlayerBulletPos(X_ID); + int16_t yP = getPlayerBulletPos(Y_ID); + int16_t xV = 0; + int16_t yV = -DEFAULT_BULLET_SPEED; + int8_t powr = player.powerShotTimer ? POWER_BULLET_ID : DEFAULT_BULLET_ID; + addPlayerBullet(xP, yP, xV, yV, powr, NOT_BOMB_ID); + if(player.wideShotTimer) + addWideShotBullets(); +} +int8_t didBulletHitEnemy(struct Enemy * enemy, struct Bullet * bullet) +{ + return !((bullet->y_pos>enemy->y_pos+ENEMY_HEIGHT)|| + (bullet->y_pos+BULLET_SIZE<enemy->y_pos)|| + (bullet->x_pos>enemy->x_pos+ENEMY_WIDTH)|| + (bullet->x_pos+BULLET_SIZE<enemy->x_pos)); + +} +int8_t didBulletHitPlayer(struct Bullet * bullet) +{ + return !((bullet->y_pos>player.y_pos+PLAYER_HEIGHT)|| + (bullet->y_pos+BULLET_SIZE<player.y_pos)|| + (bullet->x_pos>player.x_pos+PLAYER_WIDTH)|| + (bullet->x_pos+BULLET_SIZE<player.x_pos)); +} +int8_t didPlayerCollideWithEnemy(struct Enemy * enemy) +{ + return !((enemy->y_pos>player.y_pos+PLAYER_HEIGHT)|| + (enemy->y_pos+ENEMY_HEIGHT<player.y_pos)|| + (enemy->x_pos>player.x_pos+PLAYER_WIDTH)|| + (enemy->x_pos+ENEMY_WIDTH<player.x_pos)) && + !player.shieldTimer; +} +void collideBulletsWithPlayer() +{ + int j; + for(j = enemyBulletCount; j;j--) + { + enemyBulletPTR=enemyBulletPTR->next; + if(didBulletHitPlayer(enemyBulletPTR)) + { + dealDamageToPlayer(); + removeBullet(enemyBulletPTR); + } + } +} +void checkIfBulletsHitEnemies() +{ + int i; + for(i = enemyCount; i; i--) + { + enemyPTR = enemyPTR->next; + int j; + for(j = playerBulletCount; j;j--) + { + playerBulletPTR=playerBulletPTR->next; + if(didBulletHitEnemy(enemyPTR,playerBulletPTR)) + { + int16_t PowUpPosX = enemyPTR->x_pos + ENEMY_WIDTH/2 - POWER_UP_SIZE/2; + int16_t PowUpPosY = enemyPTR->y_pos + ENEMY_HEIGHT/2 - POWER_UP_SIZE/2; + int8_t points = dealDamageToEnemy(enemyPTR,playerBulletPTR->powerShot ? POWER_BULLET_DAMAGE : NORMAL_BULLET_DAMAGE); + if(points && probabilityOfSuccess(PROPABILITY_DROP_POWERUP)) + addPowerUp(PowUpPosX,PowUpPosY); + levelScore+=points; + totalScore+=points; + removeBullet(playerBulletPTR); + if(points) + break; + } + } + } +} +void enemiesFireBullet() +{ + int i; + for(i = enemyCount; i; i--) + { + if(!(enemyPTR->gunTimer)) + addEnemyBullet(getEnemyBulletPos(enemyPTR,X_ID),getEnemyBulletPos(enemyPTR,Y_ID)); + enemyPTR = enemyPTR->next; + } +} +void generateExplosion() +{ + int16_t xP = getPlayerBulletPos(X_ID); + int16_t yP = getPlayerBulletPos(Y_ID); + int16_t i; + for(i = 0; i<NUMBER_OF_BULLETS_PER_EXPLOSION; i++) + { + double angle = PI * 2.0 / NUMBER_OF_BULLETS_PER_EXPLOSION * i; + int16_t xV = (int16_t)(sin(angle)*DEFAULT_BULLET_SPEED); + int16_t yV = (int16_t)(cos(angle)*DEFAULT_BULLET_SPEED); + addPlayerBullet(xP, yP, xV, yV, POWER_BULLET_ID, BOMB_BULLET_ID); + } +} +void usePowerUpAbility(enum PowerUpType type) +{ + switch(type) + { + case PU_RapidFire: + player.rapidFireTimer = RAPID_FIRE_TIME; + return; + case PU_PowerShot: + player.powerShotTimer = POWER_SHOT_TIME; + return; + case PU_FreezeEnemies: + freezeEnemies(); + return; + case PU_WideShot: + player.wideShotTimer = WIDE_SHOT_TIME; + return; + case PU_Explosion: + generateExplosion(); + return; + case PU_BonusHealth: + player.health = PLAYER_STARTING_HEALTH; + return; + case PU_Shield: + player.shieldTimer = SHIELD_TIME; + return; + } +} +int8_t didPlayerHitPowerUp(struct PowerUp * powerUp) +{ + return !((powerUp->y_pos>player.y_pos+PLAYER_HEIGHT)|| + (powerUp->y_pos+POWER_UP_SIZE<player.y_pos)|| + (powerUp->x_pos>player.x_pos+PLAYER_WIDTH)|| + (powerUp->x_pos+POWER_UP_SIZE<player.x_pos)); +} +void pickUpPowerUps() +{ + int i; + for(i = powerUpCount; i; i--) + { + powerUpPTR = powerUpPTR->next; + if(didPlayerHitPowerUp(powerUpPTR)) + { + usePowerUpAbility(powerUpPTR->type); + removePowerUp(powerUpPTR); + } + } +} +void collideWithEnemies() +{ + int i; + for(i = enemyCount; i; i--) + { + enemyPTR = enemyPTR->next; + if(didPlayerCollideWithEnemy(enemyPTR)) + { + player.health = 0; + break; + } + } +} +void loopIteration() +{ + if(shouldFire(didUserRequestFire)) + firePlayerBullet(); + didUserRequestFire = 0; + if(shouldAddEnemy()) + addRandomEnemy(); + checkIfBulletsHitEnemies(); + movePlayer(X_DIR,Y_DIR); + enemiesFireBullet(); + pickUpPowerUps(); + collideBulletsWithPlayer(); + collideWithEnemies(); + callMultiFunc(); +} \ No newline at end of file