player 1

Dependencies:   4DGL-uLCD-SE PinDetect SparkfunAnalogJoystick mbed-rtos mbed SDFileSystem

Fork of 4180FinalLab by Rishi Bhargava

Wireless 2 Player Pong game

main.cpp

Committer:
Mpmart08
Date:
2016-04-29
Revision:
10:b57b3fbf8266
Parent:
9:aa967c554d10

File content as of revision 10:b57b3fbf8266:

#include "mbed.h"
#include "rtos.h"
#include "PinDetect.h"
#include "Speaker.h"
#include "soundBuilder.h"
#include "SparkfunAnalogJoystick.h"
#include "paddle.h"
#include "ball.h"
#include "huzzah.h"
#include "SDFileSystem.h"

// Pushbuttons
SparkfunAnalogJoystick joystick(p16, p15, p14);
//PinDetect select(p13);
//Speaker
Speaker mySpeaker(p25);
Serial pc(USBTX, USBRX);
Serial xbee(p9, p10);

//Wifi
Serial esp(p28,p27);
Huzzah huzzah("fese","12345678", &esp);
DigitalOut  reset(p26);
int player1score,player2score;

//SD Card Storage
SDFileSystem sd(p5, p6, p7, p8, "sd");
 
// State machine definitions
enum gameStateType {START, WAIT, GAME_SETUP, GAME, WIN, LOSE};
/* State Definitions:
 * START -- Creates the start screen
 * WAIT -- After the start screen, goes into wait where mbed spins and does nothing
 * GAME_SETUP -- Sets up one time things (like boarders, initializes beginning velocity
 * GAME -- When the user actually gets to play
 * LOSE -- clears the screen, prints you lose, waits, then goes back to start
 */
 
// Global state machine variable (So that the select can modify it)
gameStateType gameState = START;
bool ready = false;

Paddle botPaddle(0, 0, 0, 0);
Paddle topPaddle(0, 0, 0, 0);
Ball ball(0, 0, 0);

uint8_t gameLowX = 10, gameHighX = 190, gameLowY = 5, gameHighY = 245, gameX = 200, gameY = 250;
uint8_t gameCenterX = gameX/2, gameCenterY = gameY/2;
uint8_t ballSize=10;
uint8_t paddleWidth = 5, paddleLength = 40;
float botMove = joystick.yAxis();
uint8_t botScore = 0;
uint8_t topScore = 0;
int i = 0;

// thread that plays game sounds through the speaker
void speaker_thread(void const *argument) {

    Speaker *player = &mySpeaker;

    // Start Song
    float sFreq[] = {550,750,550,750};
    float sDur[] = {.3,.3,.3,.3};
    float sVol[] = {.01,.01,.01,.01};
    SoundBuilder startSong(sFreq, sDur, sVol, sizeof(sFreq)/sizeof(*sFreq), player);
    
    // End Song
    float eFreq[] = {300,200,250,225,200,150,150,100};
    float eDur[] = {.3,.3,.3,.3,.3,.3,.3,.3};
    float eVol[] = {.01,.01,.01,.01,.01,.01,.01,.01};
    SoundBuilder endSong(eFreq, eDur, eVol, sizeof(eFreq)/sizeof(*eFreq), player);

    while (true) {
        switch (gameState) {
        case GAME: // if game is running and user dodges a pipe, play a note
            if (topPaddle.checkHit(ball.getFutureX(), ball.getFutureY(), ball.getSize())
            || botPaddle.checkHit(ball.getFutureX(), ball.getFutureY(), ball.getSize())
            || ball.getFutureX() <= 10
            || ball.getFutureX() + ball.getSize() >= 190) {
                mySpeaker.PlayNote(440, 0.1, 0.01);
            }
            
            if (ball.getY() < 5){
                mySpeaker.PlayNote(440, 0.1, 0.01);
                mySpeaker.PlayNote(880, 0.1, 0.01);
            }
            else if (ball.getY() + ball.getSize() > 245){
                mySpeaker.PlayNote(880, 0.1, 0.01);
                mySpeaker.PlayNote(440, 0.1, 0.01);
            }
            
            break;
        case START: // play a song at the start of the game
            startSong.playSong();
            Thread::wait(5000);
            break;
        case WIN:  // play a song when the player wins the game
        case LOSE: // play a song when the player loses the game
            endSong.playSong();
            Thread::wait(5000);
            break;
        }
    }
}

// thread that writes to the sd card and loads highscores to website
void sd_card_thread(void const *argument) {

    FILE *fp = NULL;
    fp = fopen("/sd/highscore.txt", "r");
    fscanf(fp, "%i\n%i", &player1score, &player2score);
    fclose(fp);
    
    huzzah.config();
    huzzah.sendwebpage(player1score, player2score);
    
    while (true) {
        
        switch (gameState) {
        case WIN:
            // overwrite previous high score
            player1score++;
            fp = fopen("/sd/highscore.txt", "w");
            fprintf(fp, "%i\n%i", player1score, player2score);
            fclose(fp);
            huzzah.config();
            huzzah.sendwebpage(player1score, player2score);
            break;
        case LOSE:
            // overwrite previous high score
            player2score++;
            fp = fopen("/sd/highscore.txt", "w");
            fprintf(fp, "%i\n%i", player1score, player2score);
            fclose(fp);
            huzzah.config();
            huzzah.sendwebpage(player1score, player2score);
            break;
        }
    }
} 

void xbee_thread(void const *argument) {
 
    while (true) {
        switch (gameState) {
        case WAIT:
            if (ready && xbee.writeable()) {
                xbee.putc(1);
            }
            if (ready && xbee.readable()) {
                char c = xbee.getc();
                if (c == 1) {
                    gameState = GAME_SETUP;
                }
            }
            break;
        case GAME:
            if (xbee.writeable()) {
                xbee.putc(botPaddle.getX());
            }
            if (xbee.readable()) {
                char c = xbee.getc();
                uint8_t top = 200 - paddleLength - ((uint8_t) c);
                topPaddle.setX(top);
            }
            break;
        }
    }
}
 
int main() 
{   
    //WifiServer Configuration and set-up
    reset=0; //hardware reset for 8266
    //Thread::wait(500);
    reset=1;
    esp.baud(9600);
    //huzzah.config();
    //huzzah.sendwebpage(highscore1,highscore2);
  
    // This is setting up the joystick select as a pushbutton
    //joystick.set_callback(&select_hit_callback);
    
    pc.format(8, SerialBase::None, 1);
    pc.baud(115200);

    botPaddle = Paddle(gameCenterX-(paddleLength/2), gameHighY, paddleLength, paddleWidth);
    botPaddle.setLimits(gameLowX, gameHighX);
    botPaddle.setMaxMove(3);
    topPaddle = Paddle(gameCenterX-(paddleLength/2), gameLowY, paddleLength, paddleWidth);
    topPaddle.setLimits(gameLowX, gameHighX);
    topPaddle.setMaxMove(3);
    ball = Ball(gameCenterX, gameCenterY, ballSize);
    
    ball.setVxDir(true);
    ball.setVyDir(true);
    
    while (!pc.readable()){
    
    }
    
    Thread thread1(speaker_thread);
    Thread thread2(sd_card_thread);
    Thread thread3(xbee_thread);
    
    while (1) 
    {
        switch (gameState)
        {
        case START:
            if (pc.writeable()){
                pc.printf("%c%c%c%c%c", 0, 0, 0, 0, 0);
                ball.setVxDir(true);
                ball.setVyDir(true);
                gameState = WAIT;
            }
            break;
        case GAME_SETUP:
            ball.reset(gameCenterX-(ballSize/2), gameCenterY-(ballSize/2), 0, 6);
            botPaddle.reset(gameCenterX-(paddleLength/2), gameHighY);
            topPaddle.reset(gameCenterX-(paddleLength/2), gameLowY);
            if (pc.writeable()){
                pc.printf("%c%c%c%c%c", 3, botScore, topScore, 0, 0);
                ready = false;
                srand(i);
                gameState = GAME;
                Thread::wait(2000);
            }
            break;
        case GAME:
            if (pc.writeable()) {
                pc.printf("%c%c%c%c%c", 4, botPaddle.getX(), topPaddle.getX(), ball.getX(), ball.getY());
                
                uint8_t size = ball.getSize(); //stored in a temp variable because used a lot
                
                if (ball.getFutureX() <= gameLowX){
                    ball.reverseXDirection();
                }
                else if (ball.getFutureX() + size >= gameHighX){
                    ball.reverseXDirection();
                }
                
                if (topPaddle.checkHit(ball.getFutureX(), ball.getFutureY(), size)) {
                    ball.reverseYDirection();
                    uint8_t fx = ball.getFutureX();
                    uint8_t newVx = topPaddle.returnAngle(fx, size);
                    uint8_t newVy = 6 - newVx;
                    ball.setVx(newVx);
                    ball.setVy(newVy);
                    ball.setVxDir(topPaddle.returnDir(fx, size));
                }
                else if (botPaddle.checkHit(ball.getFutureX(), ball.getFutureY(), size)) {
                    ball.reverseYDirection();
                    uint8_t fx = ball.getFutureX();
                    uint8_t newVx = botPaddle.returnAngle(fx, size);
                    uint8_t newVy = 6 - newVx;
                    ball.setVx(newVx);
                    ball.setVy(newVy);
                    ball.setVxDir(botPaddle.returnDir(fx, size));
                }
                
                if (ball.getY() < gameLowY){
                    botScore++;
                    ball.setVyDir(false);
                    gameState = GAME_SETUP;
                }
                else if (ball.getY() + size > gameHighY){
                    topScore++;
                    ball.setVyDir(true);
                    gameState = GAME_SETUP;
                }
                
                if (botScore >= 5) {
                    gameState = WIN;
                }
                else if (topScore >= 5) {
                    gameState = LOSE;   
                }
                
                ball.update();
                botMove = -joystick.yAxis();
                if ((botMove < -0.1 || botMove > 0.1) && ball.getY() < gameHighY - 50) {
                    botPaddle.move(botMove);
                }
            }
            break;
        case LOSE:
            if (pc.writeable()){
                pc.printf("%c%c%c%c%c", 5, 0, 0, 0, 0);
                botScore = 0;
                topScore = 0;
                Thread::wait(5000);
                gameState = START;
            }
            break;
        case WIN:
            if (pc.writeable()){
                pc.printf("%c%c%c%c%c", 6, 0, 0, 0, 0);
                botScore = 0;
                topScore = 0;
                Thread::wait(5000);
                gameState = START;
            }
            break;
        case WAIT:
            if (pc.writeable()){
                // Used to seed the rand() function so the ball has a random starting direction
                i++;
                if (joystick.button())
                    ready = true;
                if (ready){
                    pc.printf("%c%c%c%c%c", 2, 0, 0, 0, 0);
                }
                else {
                    pc.printf("%c%c%c%c%c", 1, 0, 0, 0, 0);
                }
            }
            break;
        }
        Thread::wait(20);
    } 
}