Two player imu pong

Dependencies:   4DGL-uLCD-SE IMUfilter LSM9DS0 PinDetect mbed

main.cpp

Committer:
rrr93
Date:
2015-10-22
Revision:
0:941225f01ccc

File content as of revision 0:941225f01ccc:

#include "mbed.h"
#include "PinDetect.h"
#include "uLCD_4DGL.h"
#include "Speaker.h"
#include "paddle.h"
#include "ball.h"
#include "soundBuilder.h"
#include "LSM9DS0.h"

Serial pc(USBTX, USBRX);
//IMU
// SDO_XM and SDO_G are pulled up, so our addresses are:
#define LSM9DS0_XM_ADDR  0x1D // Would be 0x1E if SDO_XM is LOW
#define LSM9DS0_G_ADDR   0x6B // Would be 0x6A if SDO_G is LOW
LSM9DS0 imu(p9, p10, LSM9DS0_G_ADDR, LSM9DS0_XM_ADDR);
LSM9DS0 imu2(p28,p27, LSM9DS0_G_ADDR, LSM9DS0_XM_ADDR);

// Pushbuttons
PinDetect pbUp(p15); 
PinDetect pbDown(p16);
// uLCD
uLCD_4DGL uLCD(p13, p14, p29);
//Speaker
Speaker mySpeaker(p21);
 
// Global variables needed for the push button interrupts
 Paddle paddle(40, 3, 118,1);
 Paddle paddle2(40,3, 8, 1);
 Ball ball(p19, 1.6,1.2,5,50,21);
 
// State machine definitions
enum gameStateType {START, WAIT, GAME_SETUP, GAME, 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 pushbuttons can modify it)
gameStateType gameState = START;

// Pushbutton callbacks
// WARNING: Do not call to draw anything to the uLCD in these
// as this will cause the uLCD to crash sometimes. Update positions
// and draw elsewhere (like it's done here).
// Only modify the logic inside the callback functions.
void pbUp_hit_callback (void)
{
    switch (gameState)
    {
    case WAIT:
        gameState = GAME_SETUP;
        break;
    case GAME:  
        paddle.movePaddle(true);
        paddle2.movePaddle(true);
        break;
    }
}
 
void pbDown_hit_callback (void)
{
    switch (gameState)
    {
    case WAIT:
        gameState = GAME_SETUP;
        break;
    case GAME:
        paddle.movePaddle(false);
        paddle2.movePaddle(false);
        break;
    }
}
 
int main() 
{   
    
    //IMU
    uint16_t status = imu.begin();
    //Make sure communication is working
    pc.printf("LSM9DS0 WHO_AM_I's returned: 0x%X\n", status);
    pc.printf("Should be 0x49D4\n\n");
    
    uint16_t status2 = imu2.begin();
    //Make sure communication is working
    pc.printf("LSM9DS0 #2 WHO_AM_I's returned: 0x%X\n", status2);
    pc.printf("Should be 0x49D4\n\n");
    
    
    
    float IMU_offset = 0.14; //detrmined empirically
    
    // This is setting up the pushbuttons
    // Don't modify this code.
    pbUp.mode(PullUp);
    pbDown.mode(PullUp);
    wait(0.1);
    pbUp.attach_deasserted(&pbUp_hit_callback);
    pbDown.attach_deasserted(&pbDown_hit_callback);
    pbUp.setSampleFrequency();
    pbDown.setSampleFrequency();
    // Don't modify this code.
    
    uLCD.display_control(PORTRAIT);
    uLCD.cls();
    uLCD.baudrate(BAUD_3000000);
    uLCD.background_color(BLACK);

    // Initialize all your variables outside the while/switch statement
    // to avoid compiler warning/errors
    int i = 0;
    int random;
    
    //paddle stuff
    int pmoveMin = 25;
    int pmoveMax = 70;
    int pmove;
 
    while (1) 
    {   
        switch (gameState)
        {
        case START:
            uLCD.cls();
            uLCD.locate(0,0);
            uLCD.printf("Pong!!!\n\n");
            uLCD.printf("Press Key to Start");
            gameState = WAIT;
            ball.setX(50);
            ball.setY(50);
            break;
        case GAME_SETUP:
            uLCD.cls();
            uLCD.line(0, 0, 127, 0, 0xCFB53B);
            uLCD.line(127, 0, 127, 127, 0xCFB53B);
            uLCD.line(127, 127, 0, 127, 0xCFB53B);
            uLCD.line(0, 127, 0, 0, 0xCFB53B);
            ball.setBaseVx(2.0);
            ball.setBaseVy(2.0);
            random = rand() % 1;
            ball.setVxSign(-1); ball.setVySign(((float)random - 0.5)*2);
            paddle.initDraw(&uLCD);
            paddle2.initDraw(&uLCD);
            
            Note note1(4000.0, 0.7, 0.5);
            Note note2(3000.0, 0.3, 0.5);
            Note note3(2000.0, 0.3, 0.5);
            Note note4(1000.0, 0.7, 0.5);
            Note note5(2500.0, 0.3, 0.5);
            SoundBuilder sound(&mySpeaker);
            sound.addNote(note1);
            sound.addNote(note2);
            sound.addNote(note3);
            sound.addNote(note4);
            sound.addNote(note5);
            sound.playSong();
            gameState = GAME;
            break;
        case GAME:
            if(ball.CheckHit())
            {      
               Note note(1000.0, 0.03, 0.5);
               SoundBuilder sound(&mySpeaker);
               sound.addNote(note);
               sound.playSong();
            }

            if (paddle.checkHitY(ball.getFutureX(), ball.getFutureY(), ball.getRadius())) 
            {   
                
                ball.reverseYDirection();
            }
            
            if (paddle2.checkHitY(ball.getFutureX(), ball.getFutureY(), ball.getRadius())) 
            {   
                
                ball.reverseYDirection();
            }

            if (ball.CheckLose())
                {gameState = LOSE;}
            if (paddle.checkHitX(ball.getFutureX(), ball.getFutureY(), ball.getRadius(),false)) 
            {
               Note note(4000.0, 0.03, 0.5);
               SoundBuilder sound(&mySpeaker);
               sound.addNote(note);
               sound.playSong();
                
                ball.reverseXDirection();
                uLCD.locate(1,1);
            }
            
            if (paddle2.checkHitX(ball.getFutureX(), ball.getFutureY(), ball.getRadius(),true)) 
            {
               Note note(4000.0, 0.03, 0.5);
               SoundBuilder sound(&mySpeaker);
               sound.addNote(note);
               sound.playSong();
                ball.reverseXDirection();
                uLCD.locate(1,1);
            }
            
            
            ball.update(&uLCD);
            imu.readAccel();

            imu2.readAccel();

            if ( imu.ax + IMU_offset > 0.1)
            {
                paddle.movePaddle(true);
            }
            else if (imu.ax+ IMU_offset  < -0.1)
            {
               paddle.movePaddle(false); 
            }
            
            if ( imu2.ax + IMU_offset > 0.1)
            {
                paddle2.movePaddle(true);
            }
            else if (imu2.ax+ IMU_offset  < -0.1)
            {
               paddle2.movePaddle(false);    
            }
            
            // We can assume that these for loops are quick enough that the paddle will move only one interval.
            // These movements of the paddle have been optimized. Feel free to draw it out to see how it's been done.
            paddle.redraw(&uLCD);
            paddle2.redraw(&uLCD);
            break;
        case LOSE:
            uLCD.cls();
            uLCD.printf("YOU LOSE D:");
            Note note6(3000.0, 0.7, 0.5);
            Note note7(2000.0, 0.3, 0.5);
            Note note8(1000.0, 0.3, 0.5);
            Note note9(2300.0, 0.7, 0.5);
            Note note10(2500.0, 0.3, 0.5);
            SoundBuilder sound2(&mySpeaker);
            sound2.addNote(note6);
            sound2.addNote(note7);
            sound2.addNote(note8);
            sound2.addNote(note9);
            sound2.addNote(note10);
            sound2.playSong();
            paddle.resetScore();
            paddle2.resetScore();
            wait(5.0);
            gameState = START;
            break;
        case WAIT:
            // Used to seed the rand() function so we don't get the same starting position every time.
            i++; 
            break;
        }
    } 
}