Asteroids for MBED game with Bluetooth LE UART Friend Controller, uLCD, speaker, and uSD.

Dependencies:   4DGL-uLCD-SE mbed-rtos mbed

Asteroids for MBED game with Bluetooth LE UART Friend Controller

main.cpp

Committer:
agamemaker
Date:
2016-03-12
Revision:
9:49f4b9dcab22
Parent:
7:ff87ab834590
Child:
10:6bb7504e0f5a

File content as of revision 9:49f4b9dcab22:

#include "mbed.h"
#include "rtos.h"
#include "uLCD_4DGL.h"
#include <math.h>
#include <list>
#include <time.h> 
#include "SongPlayer.h"
using namespace std;

//constants
#define ACCEL .5
#define ROTTA .3
#define MAXSP 7
#define BULSP 10
#define ASTSP 3
#define PI 3.14159265359

//devices
//DigitalOut myled(LED1);
uLCD_4DGL ulcd(p28,p27,p29);
BusOut myled(LED1,LED2,LED3,LED4);
Serial blue(p13,p14);
SongPlayer myspkr(p26);

//Globals
int game_speed = 25;
bool up = 0;
bool left = 0;
bool right = 0;
bool stop = 0;
bool four = 0;
bool colsound = 0;
int lives = 3;
int round = 1;

class Movement
{
public:
    double x_pos;   // x position of object
    double y_pos;   //
    double x_vel;   // x velocity of object
    double y_vel;   //
    double angle;   // angle of object
    int hit_rad;     // hit box radius of object
    bool wrap;
    Movement(double xp,double yp,double xv,double yv,double a,double r,double w);
    void assign(double xp,double yp,double xv,double yv,double a,double r,double w);
    //void move();
    void accelerate();
    void turn_left();
    void turn_right();

};

Movement::Movement(double xp,double yp,double xv,double yv,double a,double r,double w)
{
    x_pos = xp;
    y_pos = yp;
    x_vel = xv;
    y_vel = yv;
    angle = a;
    hit_rad = r;
    wrap = w;
}

void Movement::assign(double xp,double yp,double xv,double yv,double a,double r,double w)
{
    x_pos = xp;
    y_pos = yp;
    x_vel = xv;
    y_vel = yv;
    angle = a;
    hit_rad = r;
    wrap = w;
}

/*void Movement::move()
{
    x_pos += x_vel;
    y_pos += y_vel;
    if(x_pos < 0 || x_pos > 144 || y_pos < 0 || y_pos > 144) {
        if(wrap) {
            x_pos += 144*(1 - ceil(x_pos/144));
            y_pos += 144*(1 - ceil(y_pos/144));
        } else {
        }
    }
}*/

void Movement::accelerate()
{
    x_vel += ACCEL * cos(angle);
    y_vel += ACCEL * sin(angle);
    if(sqrt(pow(x_vel,2) + pow(y_vel,2)) > MAXSP) {
        x_vel = x_vel * MAXSP / sqrt(pow(x_vel,2) + pow(y_vel,2));
        y_vel = y_vel * MAXSP / sqrt(pow(x_vel,2) + pow(y_vel,2));
    }
}

void Movement::turn_left()
{
    angle -= ROTTA;
}

void Movement::turn_right()
{
    angle += ROTTA;
}

//Threads
//Speaker
void crash(void const *args)
{
    while(1) {
        if(colsound) {
            float note = 1568.0;
            float durration = .5;
            myspkr.PlaySong(&note, &durration);
            colsound = 0;
        }
    }
}

//Controls
int read_getc(Serial &blue)
{
    while(!blue.readable()) {
        Thread::yield();
    }
    return blue.getc();
}

void controls(void const *args)
{
    char bnum=0;
    char bhit=0;
    while(1) {
        //Thread::wait(100);
        if (read_getc(blue)=='!') {
            if (read_getc(blue)=='B') { //button data packet
                bnum = read_getc(blue); //button number
                bhit = read_getc(blue); //1=hit, 0=release
                if (read_getc(blue)==char(~('!' + 'B' + bnum + bhit))) { //checksum OK?
                    myled = bnum - '0'; //current button number will appear on LEDs
                    switch (bnum) {
                        case '1': //number button 1
                            if (bhit=='1') {
                                game_speed = 25;
                            } else {
                                //add release code here
                            }
                            break;
                        case '2': //number button 2
                            if (bhit=='1') {
                                game_speed = 100;
                            } else {
                                //add release code here
                            }
                            break;
                        case '3': //number button 3
                            if (bhit=='1') {
                                //add hit code here
                            } else {
                                //add release code here
                            }
                            break;
                        case '4': //number button 4
                            if (bhit=='1') {
                                four = 1;
                            } else {
                                four = 0;
                            }
                            break;
                        case '5': //button 5 up arrow
                            if (bhit=='1') {
                                up = 1;
                            } else {
                                up = 0;
                            }
                            break;
                        case '6': //button 6 down arrow
                            if (bhit=='1') {
                                stop = 1;
                            } else {
                                stop = 0;
                            }
                            break;
                        case '7': //button 7 left arrow
                            if (bhit=='1') {
                                left = 1;
                            } else {
                                left = 0;
                            }
                            break;
                        case '8': //button 8 right arrow
                            if (bhit=='1') {
                                right = 1;
                            } else {
                                right = 0;
                            }
                            break;
                        default:
                            break;
                    }
                }
            }
        }
    }
}

void move(Movement &p)
{
    p.x_pos += p.x_vel;
    p.y_pos += p.y_vel;
    if(p.x_pos < 0 || p.x_pos > 144 || p.y_pos < 0 || p.y_pos > 144) {
        if(p.wrap) {
            p.x_pos += 144*(1 - ceil(p.x_pos/144));
            p.y_pos += 144*(1 - ceil(p.y_pos/144));
        } else {
        }
    }
}
//game_over
void game_over()
{
    ulcd.cls();
    ulcd.printf("GAME OVER");
    wait(3);
    ulcd.cls();
    lives = 3;
    ulcd.printf("%d",lives);

}
//move
void move_all(Movement &player, list<Movement> &asteroids, list<Movement> &bullets)
{
    move(player);
    list<Movement>::iterator iterator;
    for (iterator = asteroids.begin(); iterator != asteroids.end(); ++iterator) {
        move(*iterator);
    }
    for (iterator = bullets.begin(); iterator != bullets.end(); ++iterator) {
        move(*iterator);
    }
}

//garbage
void garbage(list<Movement> &bullets)
{
    bool del = 0;
    list<Movement>::iterator iterator;
    list<Movement>::iterator itcpy;
    for (iterator = bullets.begin(); iterator != bullets.end(); ++iterator) {
        if(iterator->x_pos < 0 || iterator->x_pos > 144 || iterator->y_pos < 0 || iterator->y_pos > 144) {
            //bullets.erase(iterator);
            del = 1;
            itcpy = iterator;
        }
    }
    if(del) {
        bullets.erase(itcpy);
    }
}

//collisions
bool collision(Movement p1, Movement p2)
{
    int rad = p1.hit_rad + p2.hit_rad;
    double dist = sqrt(pow((p1.x_pos - p2.x_pos),2) + pow((p1.y_pos - p2.y_pos),2));
    return dist < rad;
}

void new_asteroid(list<Movement> &asteroids, int x, int y, int size){
    double ast_ang = rand()%1000 * 2*PI/1000;
    double a_x_vel = ASTSP * cos(ast_ang);
    double a_y_vel = ASTSP * sin(ast_ang);
    Movement temp(x, y, a_x_vel, a_y_vel, 0, size, 1);
    asteroids.push_back(temp);
}

void calc_collisions(Movement &player, list<Movement> &asteroids, list<Movement> &bullets)
{
    bool hit = 0;
    list<Movement>::iterator it;
    list<Movement>::iterator it2;
    list<Movement>::iterator itacpy;
    list<Movement>::iterator itbcpy;
    for (it = asteroids.begin(); it != asteroids.end(); ++it) {
        if(collision(player,*it)) {
            //ulcd.printf("crash");
            colsound = 1;
            player.assign(70,70,0,0,0,10,1);
            lives--;
            if(!lives) {
                game_over();
            }
            ulcd.cls();
            ulcd.printf("%d",lives);
        }
    }
    for (it = asteroids.begin(); it != asteroids.end(); ++it) {
        for (it2 = bullets.begin(); it2 != bullets.end(); ++it2) {
            if(collision(*it,*it2)) {
                //ulcd.printf("hit");
                hit = 1;
                itacpy = it;
                itbcpy = it2;
            }
        }
    }
    if(hit) {
        if(itacpy->hit_rad == 10){
            new_asteroid(asteroids, itacpy->x_pos, itacpy->y_pos, 7);
            new_asteroid(asteroids, itacpy->x_pos, itacpy->y_pos, 7);
        }
        if(itacpy->hit_rad == 7){
            new_asteroid(asteroids, itacpy->x_pos, itacpy->y_pos, 5);
            new_asteroid(asteroids, itacpy->x_pos, itacpy->y_pos, 5);
        }
        
        asteroids.erase(itacpy);
        bullets.erase(itbcpy);
    }
}

//drawing
void draw_triangle(Movement p, int color)
{
    int x1 = p.x_pos + p.hit_rad * cos(p.angle);
    int y1 = p.y_pos + p.hit_rad * sin(p.angle);
    int x2 = p.x_pos + p.hit_rad * cos(p.angle + 2.5);
    int y2 = p.y_pos + p.hit_rad * sin(p.angle + 2.5);
    int x3 = p.x_pos + p.hit_rad * cos(p.angle - 2.5);
    int y3 = p.y_pos + p.hit_rad * sin(p.angle - 2.5);
    ulcd.triangle(x1,y1,x2,y2,x3,y3,color);
}

void draw_objs(Movement player, list<Movement> asteroids, list<Movement> bullets, int color)
{
    //ulcd.cls();
    draw_triangle(player,color);
    ulcd.circle(player.x_pos,player.y_pos,player.hit_rad,color);
    list<Movement>::const_iterator iterator;
    for (iterator = asteroids.begin(); iterator != asteroids.end(); ++iterator) {
        ulcd.circle(iterator->x_pos,iterator->y_pos,iterator->hit_rad,color);
    }
    for (iterator = bullets.begin(); iterator != bullets.end(); ++iterator) {
        ulcd.filled_circle(iterator->x_pos,iterator->y_pos,iterator->hit_rad,color);
    }
}

//round check
void round_check(list<Movement> &asteroids){
    if(asteroids.empty()){
        round++;
        for(int i = 0; i < round; i++){
            new_asteroid(asteroids, 140*(i%2), 140*((i%2)+1),10);
        }
    }
}

int main()
{
    Movement temp(0,0,0,0,0,0,0);
    srand(time(NULL));
    lives = 3;
    ulcd.printf("%d",lives);
    ulcd.baudrate(BAUD_3000000);
    Thread sound(crash);
    Thread buttons(controls);
    Movement player(50, 100, 0, -5, 0, 10, 1);
    list<Movement> asteroids;
    list<Movement> bullets;
    Movement p_player(50, 100, 0, -5, 0, 10, 1);
    list<Movement> p_asteroids;
    list<Movement> p_bullets;
    while(1) {
        //controls
        if(up) {
            player.accelerate();
        }
        if(left) {
            player.turn_left();
        }
        if(right) {
            player.turn_right();
        }
        if(stop) {
            player.x_vel = 0;
            player.y_vel = 0;
        }
        if(four) {
            temp.x_pos = player.x_pos + player.hit_rad * cos(player.angle);
            temp.y_pos = player.y_pos + player.hit_rad * sin(player.angle);
            temp.x_vel = BULSP * cos(player.angle);
            temp.y_vel = BULSP * sin(player.angle);
            temp.angle = player.angle;
            temp.hit_rad = 1;
            temp.wrap = 0;
            bullets.push_back(temp);
        }

        //move
        round_check(asteroids);
        move_all(player, asteroids, bullets);
        garbage(bullets);
        calc_collisions(player, asteroids, bullets);
        draw_objs(p_player, p_asteroids, p_bullets,BLACK);
        draw_objs(player, asteroids, bullets,WHITE);
        p_player = player;
        p_asteroids = asteroids;
        p_bullets = bullets;
        Thread::wait(game_speed);
    }
}