This is a ball on the Mbed.

Dependencies:   4DGL-uLCD-SE IMUfilter ITG3200 Music mbed-rtos mbed

main_legacy.cpp

Committer:
Strikewolf
Date:
2014-03-14
Revision:
0:680348a938f8

File content as of revision 0:680348a938f8:

#include "mbed.h"
#include "uLCD_4DGL.h"
#include "rtos.h"
#include "Music.h"
#include "IMU_RPY.h"

DigitalOut myled(LED1);
AnalogIn xpot(p19);
AnalogIn ypot(p20);
uLCD_4DGL uLCD(p9,p10,p11);
music ms(p21);

Mutex xmutex,ymutex;
char mazearr[128][128];
char ballx, bally;
char ballx_old, bally_old;
float ballxvel, ballyvel, ballvel;
enum LEVELSELECT {LEVEL1, LEVEL2, LEVEL3};
LEVELSELECT gamestate = LEVEL1;

//Sound bytes
char s1[] = "E4:8; E4:8; R:8; E4:8; R:8; C4:8; E4:4; G4:4; R:4; G3:4; R:4;";
int s1_len = 61;
char wallbeep[] = "C4:48;";
int wallbeep_len = 6;
char victory[] = "A4:12; R:32; A4:12; R:32; A4:12; R:32; A4:4; R:8; F4:4; R:8; G4:4; R:8; A4:4; R:16; G4:20; R:32; A4:4;";
int victory_len = 102;
double tempo = 180;

void displayTitle();
void displayMaze();
void updateVelocity();
void updateBall();
void loadLevel();
void displayVictory();

//xthread and ythread act as the physics engine, simulating velocity and wall detection
void xthread(void const *args)
{
    while(1)
    {
        xmutex.lock();
        ymutex.lock();
        if(ballxvel > 0)
        {
            if(mazearr[ballx+1][bally] != 1)
            {
                ballx++;
            }
            else
            {
                ballxvel = -ballxvel;
                
                ms.play(wallbeep,tempo,wallbeep_len);
            }
        }
        else if (ballxvel < 0)
        {
            if(mazearr[ballx-1][bally] != 1)
            {
                ballx--;
            }
            else
            {
                ms.play(wallbeep,tempo,wallbeep_len);
                ballxvel = -ballxvel;
            }
        }
        xmutex.unlock();
        ymutex.unlock();
        Thread::wait(100-98*abs(ballxvel));
    }
} 
void ythread(void const *args)
{
    while(1)
    {
        xmutex.lock();
        ymutex.lock();
        if(ballyvel > 0)
        {
            if(mazearr[ballx][bally+1] != 1)
            {
                bally++;
            }
            else
            {
                ballyvel = -ballyvel;
                ms.play(wallbeep,tempo,wallbeep_len);
            }
        }
        else if (ballyvel < 0)
        {
            if(mazearr[ballx][bally-1] != 1)
            {
                bally--;
            }
            else
            {
                ballyvel = -ballyvel;
                ms.play(wallbeep,tempo,wallbeep_len);
            }
        }
        xmutex.unlock();
        ymutex.unlock();
        Thread::wait(100-98*abs(ballyvel));
    }
}

int main() {
    //Overclock uLCD
    uLCD.baudrate(3000000);
    
    //Title Screen
    //displayTitle();
    
    //Display Maze
    loadLevel();
    displayMaze();
    
    //Music init
    ms.freq(240);
    ms.play(s1,tempo,s1_len);
    //ms.play(victory, tempo, victory_len);
    
    //Start physics engine threads
    Thread t1(xthread);
    Thread t2(ythread);
    
    //Initial velocity
    ballxvel = 0.5;
    ballyvel = -1;
        
    //Execution Loop
    while(1) {
        
        updateVelocity();
        updateBall();
        
    }
}

//This will be where the gyro values are used to accelerate/decelerate the ball
void updateVelocity()
{
    xmutex.lock();
    ymutex.lock();
    //These should be 0.0 - 1.0 values
    //ballxvel = 0.25;
    //ballyvel = -0.25;    //Note: positive yvel will send the ball DOWN due to the uLCD coordinate system
    xmutex.unlock();
    ymutex.unlock();
}

//Move the ball around and draw to the screen
void updateBall()
{
    xmutex.lock();
    ymutex.lock();
    
    uLCD.pixel(ballx_old,bally_old,BLACK);  //Wipe the old ball
    uLCD.pixel(ballx,bally,0xFFFF00);   //Out with the old in with the new!
    ballx_old = ballx;
    bally_old = bally;
    
    xmutex.unlock();
    ymutex.unlock();
    
    //Draw start/end zones
    uLCD.filled_rectangle(2,2,22,22,GREEN);
    uLCD.filled_rectangle(106,106,126,126,0xFFFF00);
    
    //Check victory condition
    if(ballx > 106 && bally > 106)
    {
        displayVictory();   
    }
}

//Take whats in the mazearr and write it
void displayMaze()
{
    //Clear previous maze
    uLCD.filled_rectangle(0, 0, 128, 128, BLACK);
    
    //Write in new maze
    for(int i = 0; i < 128; i++)
    {
        for(int j = 0; j < 128; j++)
        {
            if(mazearr[i][j] == 1)
            {
                uLCD.pixel(i,j,RED);
            }
        }
    }
}

//This function will load a different map into the mazearray depending on the level selected
void loadLevel()
{
    //Load ball into starting zone
    ballx = 12;
    bally = 12;
    
    //Zero out the previous maze
    for(int i = 0; i < 128; i++)
    {
        for(int j = 0; j < 128; j++)
        {
            mazearr[i][j] = 0;
        }
    }
    
    //Load in test maze
    switch(gamestate)
    {
        case LEVEL1:
            //Load a test maze
            for(int i = 0; i <= 127; i++)
            {
                mazearr[i][0] = 1;
               mazearr[i][127] = 1;
               mazearr[0][i] = 1;
                mazearr[127][i] = 1;
            }
            for(int i = 0; i <= 100; i++)
            {
               mazearr[i][50] = 1;
            }
            for(int i = 0; i <= 75; i++) {
               mazearr[i][95] = 1;
            }
            for(int i = 50; i <= 75; i++) {
                mazearr[50][i] = 1;
            }    
            break;
        
         case LEVEL2:
            //Load a test maze
            for(int i = 0; i <= 127; i++)
            {
                mazearr[i][0] = 1;
               mazearr[i][127] = 1;
               mazearr[0][i] = 1;
                mazearr[127][i] = 1;
            }
            for(int i = 0; i <= 100; i++)
            {
               mazearr[i][24] = 1;
            }
            for(int i = 100; i <= 125; i++) {
               mazearr[i][95] = 1;
            }
            for(int i = 100; i <= 125; i++) {
                mazearr[95][i] = 1;
            }      
            for(int i = 40; i <= 65; i++) {
                mazearr[i][i] = 1;
            }      
             for(int i = 80; i <= 95; i++) {
                mazearr[i][i] = 1;
            } 
            break;
        
    }    
}

//Victory screen - 5 sec delay and then next level
void displayVictory()
{
    //Lock out physics engine (hacky way to stop ball movement)
    xmutex.lock();
    ymutex.lock();
    
    ms.play(victory, tempo, victory_len);
            
    //Move ball to start zone
    ballx = 12;
    bally = 12;
    
    while(1)
    {
        uLCD.text_width(2);
        uLCD.text_height(2);
        uLCD.locate(1,3);
        uLCD.printf("VICTORY!");
        wait(5);
        if (gamestate == LEVEL1)
        {
            gamestate = LEVEL2;
            loadLevel();
            displayMaze();
            wait(1);
            break;
        }
    } 
    xmutex.unlock();
    ymutex.unlock();
}

//Game title screen
void displayTitle()
{
    while(1)
    {
        uLCD.text_width(2);
        uLCD.text_height(2);
        uLCD.locate(0,0);
        uLCD.printf("SuperMbed");        
        uLCD.text_width(2);
        uLCD.text_height(3);
        uLCD.locate(2,1);
        uLCD.printf("Ball!");
    }
}