A simplified version of Galaga that can be run on an mbed

Dependencies:   4DGL-uLCD-SE DebounceIn mbed

Fork of AsteroidDefender by Ryan Quinn

main.cpp

Committer:
rquinn7
Date:
2015-10-20
Revision:
1:34bb7c386b9f
Parent:
0:bbc2ad180020
Child:
2:13ba45ceb03f

File content as of revision 1:34bb7c386b9f:

#include "mbed.h"
#include "game.h"
#include "uLCD_4DGL.h"
#include <list>
#include <stdlib.h>

uLCD_4DGL lcd(p28,p27,p29);

DigitalOut myled(LED1);
Serial pc(USBTX, USBRX);
AnalogIn sliderh(p17);
AnalogIn sliderv(p19);
DigitalIn pb1(p21);
bool down = false;
bool lost = false;
int lives = 2;
//Create lists for missiles and projectiles, so that we can easily remove them when
//destroyed
std::list<Missile> missiles;
std::list<Projectile> projectiles;
Shooter shooter;
int counter = 0;

int speed = 128;

//Render all the missiles, and erase them when they fall off the screen
//Also write black to where the square used to be
void render_missiles() {
    for(std::list<Missile>::iterator j = missiles.begin(); j != missiles.end(); j++){
        if(j->moved) {
            lcd.filled_rectangle(j->old_coord.x, j->old_coord.y, j->old_coord.x + j->size.x, j->old_coord.y + j->size.y, 0x000000);
        }
        lcd.filled_rectangle(j->coord.x, j->coord.y, j->coord.x + j->size.x, j->coord.y + j->size.y, 0xFF0000);
        if(j->coord.y >= 128) {
            j = missiles.erase(j);
            lives--;
            if(lives == 0)
                lost = true;
        }
        else {
            j->move();
        }
    }
}

//Collision checking
void check_collisions() {
    for(std::list<Projectile>::iterator j = projectiles.begin(); j != projectiles.end(); j++){
        for(std::list<Missile>::iterator k = missiles.begin(); k != missiles.end(); k++){
//            if(k->coord.y < (j->coord.y - 6))
//                continue
            if( (j->old_coord.x >= k->old_coord.x && j->old_coord.x <= (k->old_coord.x + k->size.x)) || ((j->coord.x + j->size.x) >= k->old_coord.x && (j->old_coord.x + j->size.x) <= (k->old_coord.x + k->size.x)) ){
                //Now we look at the y axis:
                if( (j->old_coord.y >= k->old_coord.y && j->old_coord.y <= (k->old_coord.y + k->size.y)) ||
                ((j->old_coord.y + j->size.y) >= k->old_coord.y && (j->old_coord.y + j->size.y) <= (k->old_coord.y + k->size.y)) ){
                //The sprites appear to overlap.
                lcd.filled_rectangle(j->old_coord.x, j->old_coord.y, j->old_coord.x + j->size.x, j->old_coord.y + j->size.y, 0x000000);
                lcd.filled_rectangle(k->old_coord.x, k->old_coord.y, k->old_coord.x + k->size.x, k->old_coord.y + k->size.y, 0x000000);
                k = missiles.erase(k);
                j = projectiles.erase(j);
    }
  }
        }
    }
}

void render_shooter() {
    if(shooter.moved) {
        lcd.filled_rectangle(shooter.old_coord.x, shooter.old_coord.y, shooter.old_coord.x + shooter.size.x, shooter.old_coord.y + shooter.size.y, 0x000000);
        shooter.moved = false;
    }
    lcd.filled_rectangle(shooter.coord.x, shooter.coord.y, shooter.coord.x + shooter.size.x, shooter.coord.y + shooter.size.y, 0xFF0000);
}

void render_projectiles() {
    for(std::list<Projectile>::iterator j = projectiles.begin(); j != projectiles.end(); j++){
        if(j->moved) {
            lcd.filled_rectangle(j->old_coord.x, j->old_coord.y, j->old_coord.x + j->size.x, j->old_coord.y + j->size.y, 0x000000);
        }
        lcd.filled_rectangle(j->coord.x, j->coord.y, j->coord.x + j->size.x, j->coord.y + j->size.y, 0xFF0000);
        if(j->coord.y < -4) {
            j = projectiles.erase(j);
        }
        else {
            j->move();
        }
    }
}

//If button is pressed, shoot only once
void check_button() {
    if(pb1 == 0 && !down) {
        down = true;
        if(projectiles.size() >= 3) {
        }
        else{
            Projectile bullet1(shooter.coord);
            projectiles.push_back(bullet1);   
        }
    }
    
    if(pb1 == 1) {
        down = false;
    }
}

//Calls all the necessary render functions,
//but only calls render_missiles every 4
//for speed purposes
void render() {
    if(counter >= 4) {
        render_missiles();
        counter = 0;
    }
    render_shooter();
    check_button();
    render_projectiles();
    check_collisions(); 
    counter++;
}

//Handles moving the shooter
void shooter_move() {
    if(sliderh < 0.4) {
        shooter.old_coord = shooter.coord;
        if(shooter.coord.x - 4 > 0) {
            shooter.coord.x -= 4;
            shooter.moved = true;
        }
    }
    else if(sliderh > 0.6) {
        shooter.old_coord = shooter.coord;
        if(shooter.coord.x + 4 < 128) {
            shooter.coord.x += 4;
            shooter.moved = true;
        }
    }
}

//Create rocks at the beggining of every level,
//randomly picking top and bottom locations for
//spawn and destination
void create_rocks(int number, int speed) {
    for(int i = 0; i<number; i++) {
        vec2 spawn, dest;
        spawn.x = rand() % 124 + 0;
        spawn.y = 0;
        dest.x = rand() % 124 + 0;
        dest.y = 129;
        int steps = speed;
        Missile missile(spawn, dest, steps);
        missiles.push_back(missile);
    }
}

int main() {
    pb1.mode(PullUp);
    pc.baud(9600);
    lcd.baudrate(3000000);
    lcd.cls();
    int counter2 = 0;
    int rock_number = 5;
    
    while(1) {  
        if(lost) {
            lcd.filled_rectangle(0, 0, 128, 128, 0xFF0000);
            break;
        }
        create_rocks(rock_number, speed);

        for (int x = 0; x<128000000; x++) {           
            render();
            shooter_move();
            if(missiles.size() == 0) {
                speed -= 15;
                if(counter % 2 == 1) {
                    rock_number += 1;
                }
                counter2 += 1;
                break;
            }
            wait(.041);
        }
        wait(2.5);
    }
}