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

Dependents:   Starship

Revision:
1:527a11035e0b
--- /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