PVP Wireless Pong

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

Fork of ECE2036Lab2StarterCode by Joseph Lind

main.cpp

Committer:
Mpmart08
Date:
2016-04-27
Revision:
7:7f2393b8ba4a
Parent:
6:9cdde66d7502

File content as of revision 7:7f2393b8ba4a:

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

// Pushbuttons
SparkfunAnalogJoystick joystick(p16, p15, p14);
//PinDetect select(p13);
//Speaker
Speaker mySpeaker(p25);
Serial pc(USBTX, USBRX);
 
// 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);

// 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
void sd_card_thread(void const *argument) {

    while (true) {
        switch (gameState) {
        case WIN:
        case LOSE:
            
            break;
        }
    }
}
 
int main() 
{   
    // 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);

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

    botPaddle = Paddle(gameCenterX-(paddleLength/2), gameHighY, paddleLength, paddleWidth);
    botPaddle.setLimits(gameLowX, gameHighX - paddleWidth);
    botPaddle.setMaxMove(2);
    topPaddle = Paddle(gameCenterX-(paddleLength/2), gameLowY, paddleLength, paddleWidth);
    topPaddle.setLimits(gameLowX, gameHighX - paddleWidth);
    topPaddle.setMaxMove(2);
    ball = Ball(gameCenterX, gameCenterY, ballSize);
    
    ball.setVxDir(true);
    ball.setVyDir(true);
    
    while (!pc.readable()){
    
    }
    
    Thread thread1(speaker_thread);
    Thread thread2(sd_card_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, gameCenterY, 0, sqrt(5.0));
            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();
                    double newVx = topPaddle.returnAngle(fx, size);
                    double newVy = sqrt(5.0 - (newVx * 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();
                    double newVx = botPaddle.returnAngle(fx, size);
                    double newVy = sqrt(5.0 - (newVx * newVx));
                    ball.setVx(newVx);
                    ball.setVy(newVy);
                    ball.setVx(botPaddle.returnAngle(fx, size));
                    ball.setVxDir(botPaddle.returnDir(fx, size));
                }
                
                if (ball.getY() < gameLowY){
                    botScore++;
                    gameState = GAME_SETUP;
                }
                else if (ball.getY() + size > gameHighY){
                    topScore++;
                    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) {
                    botPaddle.move(botMove);
                }
                //GET OTHER PADDLE SPOT AND UPDATE topPaddle
            }
            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);
                    Thread::wait(2000);
                    gameState = GAME_SETUP;
                }
                else {
                    pc.printf("%c%c%c%c%c", 1, 0, 0, 0, 0);
                }
            }
            break;
        }
        Thread::wait(20);
    } 
}