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

Game.c

Committer:
Oshyrath
Date:
2017-11-17
Revision:
1:527a11035e0b

File content as of revision 1:527a11035e0b:

#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();     
}