A retro gaming programme, designed for use on a portable embedded system. Incorporates power saving techniques.

Dependencies:   ConfigFile N5110 PowerControl beep mbed

main.cpp

Committer:
el13drt
Date:
2015-04-14
Revision:
5:a0e4a67266d6
Parent:
4:c6305031f80d
Child:
6:fa2928bcec17

File content as of revision 5:a0e4a67266d6:

/**
@file main.cpp
@brief Program implementation
*/

#include "mbed.h"
#include "N5110.h"

#include <ctime>
#include <cstdlib>

// change this to alter tolerance of joystick direction
#define DIRECTION_TOLERANCE 0.05

// VCC,SCE,RST,D/C,MOSI,SCLK,LED - set pins for LCD
N5110 lcd(p7,p8,p9,p10,p11,p13,p22);

// navigation/action buttons
DigitalIn buttonA(p19);
DigitalIn buttonB(p20);

// LED indicators
AnalogOut ledR(p18);// RED LED
DigitalOut ledY(p24);// YELLOW LED

// connections for joystick
DigitalIn button(p17);
AnalogIn xPot(p15);
AnalogIn yPot(p16);

// create local file system
//LocalFileSytem local("local");

// boundary conditions
int cells [84][48];

// Globabl Variables /////////////////////////

// player's score
int score = 0;

// global variables for movement (pixelNinja)
int a1 = 22;
int a2 = 24;
int a3 = 23;
int a4 = 25;
int a5 = 20;
int a6 = 26;
int a7 = 19;
int a8 = 21;

//global variable for random X co-ordinates
int randX1;
int randX2;
int randX3;
int randX4;
int randX5;
int randX6;

// global variable for random Y co-ordinates
int randY1 = 0;
int randY2 = 0;
int randY3 = 0;
int randY4 = 0;
int randY5 = 0;
int randY6 = 0;

// timer to regularly read the joystick
Ticker pollJoystick;

// serial for debug
Serial serial(USBTX,USBRX);

// create enumerated type (0,1,2,3 etc. for direction)
// could be extended for diagonals etc.
enum DirectionName {
    UP,
    DOWN,
    LEFT,
    RIGHT,
    CENTRE,
    UNKNOWN
};

// struct for Joystick
typedef struct JoyStick Joystick;
struct JoyStick {
    float x;    // current x value
    float x0;   // 'centred' x value
    float y;    // current y value
    float y0;   // 'centred' y value
    int button; // button state (assume pull-down used, so 1 = pressed, 0 = unpressed)
    DirectionName direction;  // current direction
};

// create struct variable
Joystick joystick;

int printFlag = 0;

// function prototypes
void calibrateJoystick();
void updateJoystick();

//intro screen
void welcome()
{
    //bottom border
    lcd.drawRect(0,44,84,2,1);

    //top border
    lcd.drawRect(0,1,84,2,1);

    //print initials 'DRT'
    lcd.printChar('D',30,14);
    wait(0.6);
    lcd.printChar('R',37,14);
    wait(0.6);
    lcd.printChar('T',44,14);
    wait(0.6);

    //print 'presents...'
    lcd.printString("presents...",8,21);
    wait(1.0);

    //dramatic flashing
    lcd.inverseMode();
    wait(0.2);
    lcd.normalMode();
    wait(0.2);
    lcd.inverseMode();
    wait(0.2);
    lcd.normalMode();
    wait(1.0);

    //more dramatic flashing
    lcd.inverseMode();
    wait(0.2);
    lcd.normalMode();
    wait(0.2);
    lcd.inverseMode();
    wait(0.2);
    lcd.normalMode();
    wait(0.6);
}

//selection menu///////////////////////////////////////////
void mainMenu()
{
    //bottom border
    lcd.drawRect(0,47,84,0,1);
    //top border
    lcd.drawRect(0,0,84,2,1);

    //print 'Xtreme Tower'
    lcd.printString("Xtreme",4,25);
    lcd.printString("Tower",44,25);

    //title outline
    lcd.drawRect(3,6,77,10,0);

////castle //x, y, w, h, fill//////////////////////

    //castle main bulk
    lcd.drawRect(59,32,21,8,1);

    //left window bulk
    lcd.drawRect(59,22,2,10,1);
    //centre left window bulk
    lcd.drawRect(65,22,2,10,1);
    //centre right window bulk
    lcd.drawRect(72,22,2,10,1);
    //right window bulk
    lcd.drawRect(78,22,2,10,1);
    //central window bulk
    lcd.drawRect(68,25,3,7,1);

    //central window bulk
    lcd.drawRect(75,28,0,0,1);
    lcd.drawRect(77,28,0,0,1);
    lcd.drawRect(64,28,0,0,1);
    lcd.drawRect(62,28,0,0,1);

    //above left window bulk
    lcd.drawRect(62,25,3,2,1);
    //above right window bulk
    lcd.drawRect(75,25,2,2,1);

    //lower right line
    lcd.drawRect(71,42,9,0,1);
    //upper right line
    lcd.drawRect(70,41,10,0,1);

    //upper left line
    lcd.drawRect(59,41,10,0,1);
    //lower left line
    lcd.drawRect(59,42,9,0,1);

    //bottom left bulk
    lcd.drawRect(59,43,8,3,1);
    //bottom right bulk
    lcd.drawRect(72,43,8,3,1);

    //option arrows - lower
    lcd.drawRect(27,42,4,0,1);
    lcd.drawRect(28,43,2,0,1);
    lcd.drawRect(29,44,0,0,1);

    //option arrows - higher
    lcd.drawRect(27,29,4,0,1);
    lcd.drawRect(28,28,2,0,1);
    lcd.drawRect(29,27,0,0,1);

    //present options
    //lcd.printString("Play Game",3,4);

}

// static background
void backGround()
{
    // x, y, w, h, fill - draw ground
    lcd.drawRect(0,47,84,0,1);

    // x, y, w, h, fill - draw left wall
    lcd.drawRect(2,0,0,47,1);
    // left wall - brick line 1
    for(int x=0; x<47; x+=4)
        lcd.drawLine(1,1,1,48,2);
    // left wall - brick line 2
    for(int x=0; x<47; x+=4)
        lcd.drawLine(0,0,0,48,2);

    // x, y, w, h, fill - draw right wall
    lcd.drawRect(81,0,0,47,1);
    // right wall - brick line 1
    for(int x=0; x<WIDTH; x+=4)
        lcd.drawLine(82,0,82,48,2);
    // right wall - brick line 2
    for(int x=0; x<WIDTH; x+=4)
        lcd.drawLine(83,1,83,48,2);

    lcd.refresh();
}

//pixel ninja character
void pixelNinja()
{
    //x, y, w, h, fill - left leg
    lcd.drawRect(a1,39,0,7,1);
    //right leg
    lcd.drawRect(a2,39,0,7,1);
    //centre stick
    lcd.drawRect(a3,37,0,7,1);
    //back of the head
    lcd.drawRect(a1,33,0,4,1);
    //top of the head
    lcd.drawRect(a1,33,4,0,1);
    //jaw
    lcd.drawRect(a2,38,2,0,1);
    //right shoulder
    lcd.drawRect(a4,40,1,0,1);
    //left shoulder
    lcd.drawRect(a5,40,1,0,1);
    //left arm
    lcd.drawRect(a5,41,0,1,1);
    //right arm
    lcd.drawRect(a6,41,0,1,1);
    //right eye
    lcd.drawRect(a6,35,0,0,1);
    //mouth piece
    lcd.drawRect(a6,37,0,0,1);
    //left eye
    lcd.drawRect(a2,35,0,0,1);
    //sword handle
    lcd.drawRect(a7,36,0,0,1);
    lcd.drawRect(a5,37,0,0,1);
    lcd.drawRect(a8,38,0,0,1);

}

// resets back to initial values
void resetGame()
{
    score = 0;

    a1 = 22;
    a2 = 24;
    a3 = 23;
    a4 = 25;
    a5 = 20;
    a6 = 26;
    a7 = 19;
    a8 = 21;

    // in this case the X values are given a
    // new random variable each time the player
    // dies or exits and starts a new game
    randX1 = rand() % 74 + 5;
    randX2 = rand() % 74 + 5;
    randX3 = rand() % 74 + 5;
    randX4 = rand() % 74 + 5;
    randX5 = rand() % 74 + 5;
    randX6 = rand() % 74 + 5;

    randY1 = 0;
    randY2 = 0;
    randY3 = 0;
    randY4 = 0;
    randY5 = 0;
    randY6 = 0;
    lcd.clear();

}

// draws falling hazards
void hazards()
{
    // X, Y, radius, fill
    lcd.drawCircle(randX1,randY1,2,1);
    lcd.drawCircle(randX2,randY2,2,1);
    lcd.drawCircle(randX3,randY3,2,1);
    lcd.drawCircle(randX4,randY4,2,1);
    lcd.drawCircle(randX5,randY5,2,1);
    lcd.drawCircle(randX6,randY6,2,1);

    lcd.refresh();
}

// makes hazards fall - randomises X axis co-ordinates
void hazardFall()
{
    // increments randY1 variables
    // appearing to make them fall
    randY1 = randY1+=2;
    randY2 = randY2+=2;
    randY3 = randY3+=2;
    randY4 = randY4+=2;
    randY5 = randY5+=2;
    randY6 = randY6+=2;

    // loops the objects once they 'hit the floor'
    // this imitates a new set of objects falling

    if (randY1>=48)
        randY1=0;

    if (randY2>=48)
        randY2=0;

    if (randY3>=48)
        randY3=0;

    if (randY4>=48)
        randY4=0;

    if (randY5>=48)
        randY5=0;

    // each time the objects loop, a new pseudo random value
    // is assigned to the global variables (randX) to
    // randomise their positions

    if (randY6>=48) {
        randY6=0;

        score = score++;

        randX1 = rand() % 74 + 5;// psuedo random number
        randX2 = rand() % 74 + 5;// between 5 and 74
        randX3 = rand() % 74 + 5;
        randX4 = rand() % 74 + 5;
        randX5 = rand() % 74 + 5;
        randX6 = rand() % 74 + 5;
    }
}

// clears old pixels and keeps set pixels
void startrek()
{
    for (int i=3; i<81; i++)// loops through rows
        for (int j=0; j<47; j++)
            if (cells[i][j]) {// if there's a pixel then keep it
                lcd.setPixel(i,j);
            } else {
                lcd.clearPixel(i,j);// else remove the old ones
            }
    lcd.refresh();
}

// sound / light when buttonA is closed
void actionButton()
{
    buttonA.mode(PullDown);
    if (buttonA == 1) {
        ledY = 1;
    } else {
        ledY = 0;
    }
}

// sound / light when buttonB is closed
void backButton()
{
    buttonB.mode(PullDown);
    if (buttonA == 1) {
        ledY = 1;
    } else {
        ledY = 0;
    }
}

//// MAIN /////////////////////////////////////////////////

int main()
{
    //////// set initial values - configurate joystick /////////////////////////////////

    // Power indicator - RED LED
    ledR = 1;

    int exitFlag = 0;

    // initialize time seed for psuedo randomaisation
    srand (time(NULL));

    // generate random x co-ordinates for falling hazards
    // (initial values only)
    // value between 3 and 76
    randX1 = rand() % 74 + 5;
    randX2 = rand() % 74 + 5;
    randX3 = rand() % 74 + 5;
    randX4 = rand() % 74 + 5;
    randX5 = rand() % 74 + 5;
    randX6 = rand() % 74 + 5;

    calibrateJoystick();  // get centred values of joystick
    pollJoystick.attach(&updateJoystick,1.0/10.0);  // read joystick 10 times per second

    /////// initiate main menu //////////////////////////////////////////////////////////////

    lcd.init();//initialise screen
    welcome();//welcome screen
    lcd.clear();//clear pixels

    /////// Menu Selection Loop ////////////////////////////////////////////////////////////

    // option counters
    int mainOption = 0;//counter for main menu
    int exitOption = 0;//counter for exit menu

    // loop 1 - menu
    while(1) {

        mainMenu();
        actionButton();

        // joystick selection
        if (printFlag) {  //if flag set, clear flag and print joystick values to serial port
            printFlag = 0;
            serial.printf("x = %f y = %f button = %d ",joystick.x,joystick.y,joystick.button);

            // option up
            if (joystick.direction == UP) {
                serial.printf(" UP\n");
                mainOption = mainOption--;
                if (mainOption < 0)mainOption = 0;
            }
            // option down
            if (joystick.direction == DOWN) {
                serial.printf(" DOWN\n");
                mainOption = mainOption++;
                if (mainOption > 2)mainOption = 2;
            }
            // Centre / Unknown orientation
            if (joystick.direction == CENTRE)
                serial.printf(" CENTRE\n");
            if (joystick.direction == UNKNOWN)
                serial.printf(" Unsupported direction\n");

            // 'Play Game' option 1
            if (mainOption == 0) {
                lcd.printString("Play Game",3,4);
            }
            // 'High Scores' option 2
            if (mainOption == 1) {
                lcd.printString("  Scores ",3,4);
            }
            // 'Options' option 3
            if (mainOption == 2) {
                lcd.printString(" Options ",3,4);
            }
        }

//////////// Game Loop /////////////////////////////////////////////////////////////

        // 'Play Game' selected
        if ((mainOption == 0)&&(buttonA == 1)) {

            lcd.clear();

            actionButton();
            backButton();
            backGround();

            // loop 3 - Game loop
            while(1) {

                actionButton();
                backButton();

                pixelNinja();//set character
                hazards();//initiates hazards
                hazardFall();//increments hazards towards floor

                if (printFlag) {  //if flag set, clear flag and print joystick values to serial port
                    printFlag = 0;
                    serial.printf("x = %f y = %f button = %d \n",joystick.x,joystick.y,joystick.button);

                    // check joystick direction
                    if (joystick.direction == LEFT) {
                        serial.printf(" LEFT\n");
                        a1 = a1-=2;
                        a2 = a2-=2;
                        a3 = a3-=2;
                        a4 = a4-=2;
                        a5 = a5-=2;
                        a6 = a6-=2;
                        a7 = a7-=2;
                        a8 = a8-=2;
                    }
                    if (joystick.direction == RIGHT) {
                        serial.printf(" RIGHT\n");
                        a1 = a1+=2;
                        a2 = a2+=2;
                        a3 = a3+=2;
                        a4 = a4+=2;
                        a5 = a5+=2;
                        a6 = a6+=2;
                        a7 = a7+=2;
                        a8 = a8+=2;
                    }
                    if (joystick.direction == CENTRE)
                        serial.printf(" CENTRE\n");
                    if (joystick.direction == UNKNOWN)
                        serial.printf(" Unsupported direction\n");

                    // integer to represent character being
                    // struck by falling object
                    int contactPoint = 0;

                    // contact points
                    if(lcd.getPixel((a1+4),32))
                        contactPoint++;
                    if(lcd.getPixel((a1),32))
                        contactPoint++;
                    if(lcd.getPixel((a7),32))
                        contactPoint++;

                    // if contact point is not zero
                    // character has been hit
                    // and the game ends
                    if ( contactPoint !=0) {
                        lcd.printString("Game Over!!",8,25);
                        wait(0.5);
                        lcd.inverseMode();
                        wait(0.5);
                        lcd.normalMode();
                        wait(0.5);
                        lcd.inverseMode();
                        wait(0.5);
                        lcd.normalMode();
                        wait(0.5);
                        resetGame();
                        break;
                    }
                    startrek();//clears unset pixels, keeps set pixels

///////////////////// Exit Menu (Back button pressed)///////////////////////////////////////////

                    if(buttonB == 1) {

                        // set exit menu
                        lcd.clear();
                        lcd.drawRect(8,6,70,30,0);//title outline
                        lcd.printString("Exit Game?",10,25);
                        backGround();

                        while(1) {

                            if (printFlag) {  //if flag set, clear flag and print joystick values to serial port
                                printFlag = 0;
                                serial.printf("x = %f y = %f button = %d \n",joystick.x,joystick.y,joystick.button);

                                // check joystick direction
                                if (joystick.direction == LEFT) {
                                    serial.printf(" LEFT\n");
                                    exitOption--;
                                    if(exitOption < 0)exitOption = 0;
                                }
                                if (joystick.direction == RIGHT) {
                                    serial.printf(" RIGHT\n");
                                    exitOption++;
                                    if(exitOption > 1)exitOption = 1;
                                }
                                if (joystick.direction == CENTRE)
                                    serial.printf(" CENTRE\n");
                                if (joystick.direction == UNKNOWN)
                                    serial.printf(" Unsupported direction\n");
                            }
                            // draws option cursor
                            if(exitOption == 0) {
                                lcd.printString("YES",28,27);
                            }
                            if(exitOption == 1) {
                                lcd.printString("NO ",28,27);
                            }

                            // exits game
                            if((buttonA == 1)&&(exitOption == 0)) { //returns to menu
                                actionButton();
                                lcd.clear();//clears screen
                                resetGame();//resets scores/objects
                                exitFlag = 1;//sets exit flag
                                break;
                            }
                            // returns to game
                            if((buttonA == 1)&&(exitOption == 1)) {
                                break;
                            }
                        }
                        // GAME LOOP

                        if (exitFlag!=0) { //if exit flag set
                            exitFlag = 0;//reset flag
                            break;//break to main menu
                        }
                    }
                    serial.printf("Score: %i \n",score);
                }
            }
        }

////////// High Scores Loop //////////////////////////////////////////////////

        if((mainOption == 1)&&(buttonA == 1)) {

            actionButton();
            backButton();

            lcd.clear();//clear screen
            lcd.drawRect(3,6,77,10,0);//title outline
            backGround();//set background
            lcd.printString("High Scores",10,7);//title

            while(1) {

                actionButton();
                backButton();

                // back to menu
                if(buttonB == 1) {
                    lcd.clear();
                    break;
                }
            }
        }

////////// OPTIONS LOOP /////////////////////////////////////////////////////

        if((mainOption == 2)&&(buttonA == 1)) {

            actionButton();
            backButton();

            lcd.clear();//clear screen

            lcd.drawRect(3,6,77,10,0);//title outline
            lcd.drawRect(0,47,84,0,1);//bottom border
            lcd.drawRect(0,0,84,2,1);//top border
            lcd.printString("Options",20,7);//title
            lcd.printString("Difficulty",5,3);//difficulty menu
            lcd.printString("Sound FX",5,4);//sounf fx on / off

            while(1) {

                actionButton();
                backButton();

                // back to menu
                if(buttonB == 1) {
                    lcd.clear();
                    break;
                }
            }
        }
    }
}


// read default positions of the joystick to calibrate later readings
void calibrateJoystick()
{
    button.mode(PullDown);
    // must not move during calibration
    joystick.x0 = xPot; //initial positions in the range 0.0 to 1.0 (0.5 if centred exactly)
    joystick.y0 = yPot;
}

void updateJoystick()
{
    // read current joystick values relative to calibrated values (in range -0.5 to 0.5, 0.0 is centred)
    joystick.x = xPot - joystick.x0;
    joystick.y = yPot - joystick.y0;
    // read button state
    joystick.button = button;

    // calculate direction depending on x,y values
    // tolerance allows a little lee-way in case joystick not exactly in the stated direction
    if ( fabs(joystick.y) < DIRECTION_TOLERANCE && fabs(joystick.x) < DIRECTION_TOLERANCE) {
        joystick.direction = CENTRE;
    } else if ( joystick.y > DIRECTION_TOLERANCE && fabs(joystick.x) < DIRECTION_TOLERANCE) {
        joystick.direction = UP;
    } else if ( joystick.y < DIRECTION_TOLERANCE && fabs(joystick.x) < DIRECTION_TOLERANCE) {
        joystick.direction = DOWN;
    } else if ( joystick.x > DIRECTION_TOLERANCE && fabs(joystick.y) < DIRECTION_TOLERANCE) {
        joystick.direction = RIGHT;
    } else if ( joystick.x < DIRECTION_TOLERANCE && fabs(joystick.y) < DIRECTION_TOLERANCE) {
        joystick.direction = LEFT;
    } else {
        joystick.direction = UNKNOWN;
    }

    // set flag for printing
    printFlag = 1;
}