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

Dependencies:   ConfigFile N5110 PowerControl beep mbed

tower.h

Committer:
el13drt
Date:
2015-04-16
Revision:
12:eedda6554615
Child:
13:a1b3a373c5a4

File content as of revision 12:eedda6554615:


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

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

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

// player's score
int score = 0;

// difficulty - number of pixels hazards incrememnt by
int fall = 2;

// 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 Y co-ordinates
int randY1 = 0;
int randY2 = 0;
int randY3 = 0;
int randY4 = 0;
int randY5 = 0;
int randY6 = 0;

// 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();
}

//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);
}

//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);
}

// stops ninja going through walls
void ninjaBoundaries()
{
    if(a6 > 79 )
        a6 = 79;
    if(a4 > 78)
        a4 = 78;
    if(a2 > 77)
        a2 = 77;
    if(a3 > 76)
        a3 = 76;
    if(a1 > 75)
        a1 = 75;
    if(a8 > 74)
        a8 = 74;
    if(a5 > 73)
        a5 = 73;
    if(a7 > 72)
        a7 = 72;

    if(a6 < 11 )
        a6 = 11;
    if(a4 < 10)
        a4 = 10;
    if(a2 < 9)
        a2 = 9;
    if(a3 < 8)
        a3 = 8;
    if(a1 < 7)
        a1 = 7;
    if(a8 < 6)
        a8 = 6;
    if(a5 < 5)
        a5 = 5;
    if(a7 < 4)
        a7 = 4;
}

// 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 += fall;
    randY2 = randY2 += fall;
    randY3 = randY3 += fall;
    randY4 = randY4 += fall;
    randY5 = randY5 += fall;
    randY6 = randY6 += fall;

    // 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++;//increment score by 1 after each wave of hazards

        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;
    }
}

//void writeDataToFile(float data, char dataTwo[30])
//{
//    leds = 15; // turn on LEDs for feedback
//    FILE *fp = fopen("/local/datalog.csv", "a"); // open 'log.txt' for appending
//
//    time_t seconds = time(NULL); // get current time
//
//    // format time into a string (time and date)
//    strftime(dataTwo, 30 , "%R %x", localtime(&seconds));
//
//    // if the file doesn't exist it is created, if it exists, data is appended to the end
//    fprintf(fp,"%s, %.2f \n",dataTwo,data); // print string to file
//
//    fclose(fp); // close file
//    leds = 0; // turn off LEDs to signify file access has finished
//}

// 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();
}

// clears old pixels and keeps set pixels
void refreshCursor1()
{
    for (int i=70; i<80; i++)// loops through rows
        for (int j=17; j<25; 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();
}

// clears old pixels and keeps set pixels
void refreshCursor2()
{
    for (int i=70; i<80; i++)// loops through rows
        for (int j=25; j<32; 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();
}

// clears old pixels and keeps set pixels
void refreshCursor3()
{
    for (int i=70; i<80; i++)// loops through rows
        for (int j=32; j<40; 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;
        //buzzer.beep(1000,0.2);//frequeny/duration

        serial.printf("buttonA\n");//for debugging
    } else {
        ledY = 0;
    }
}

// sound / light when buttonB is closed
void backButton()
{
    buttonB.mode(PullDown);
    if (buttonB == 1) {
        ledY = 1;
        //buzzer.beep(400,0.2);//frequency/duration

        serial.printf("buttonB\n");//for debugging
    } else {
        ledY = 0;
    }
}

// presents main menu options
void mainMenu(int& mainOption)
{
    actionButton();//set audible/light for button

    // joystick selection
    if (printFlag) {  //if flag set, clear flag and print joystick values to serial port
        printFlag = 0;

        // 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);
        }
    }
}

// draws main menu
void drawMainMenu()
{
    //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);
}

// presents exit menu options
void exitMenu(int& exitOption)
{

    if (printFlag) {  //if flag set, clear flag and print joystick values to serial port
        printFlag = 0;

        // 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",29,27);
    }
    if(exitOption == 1) {
        lcd.printString(" NO",29,27);
    }
}

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

    // option arrow - right
    lcd.drawRect(55,25,0,4,1);
    lcd.drawRect(56,26,0,2,1);
    lcd.drawRect(57,27,0,0,1);

    // option arrow - left
    lcd.drawRect(27,25,0,4,1);
    lcd.drawRect(26,26,0,2,1);
    lcd.drawRect(25,27,0,0,1);
}

// presents the options
void optionsMenu(int& option)
{
    // joystick selection
    if (printFlag) {  //if flag set, clear flag and print joystick values to serial port
        printFlag = 0;

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

        // 'Difficulty' option 1
        if (option == 0) {
            lcd.drawCircle(72,27,2,1);
            refreshCursor3();
        }
        // 'Sound FX' option 2
        if (option == 1) {
            lcd.drawCircle(72,35,2,1);
            refreshCursor2();
        }
    }
}

// draws options menu
void drawOptionsMenu()
{
    lcd.clear();//clear screen
    backGround();
    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",3,9);
    lcd.printString("Sound FX",3,10);
}

// present difficulty options
void difficultyMenu(int& subOption)
{

    // joystick selection
    if (printFlag) {//if flag set, clear flag,print joystick values
        printFlag = 0;

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

        // 'Easy' option 1
        if (subOption == 0) {
            lcd.drawCircle(72,19,2,1);
            refreshCursor2();
            refreshCursor3();
            if(buttonA ==1) { //select easy
                fall = 1;
            }
        }
        // 'Normal' option 2
        if (subOption == 1) {
            lcd.drawCircle(72,27,2,1);
            refreshCursor1();
            refreshCursor3();

            if(buttonA == 1) { //select normal
                fall = 2;
            }
        }
        // 'Forget It' option 3
        if (subOption == 2) {
            lcd.drawCircle(72,35,2,1);
            refreshCursor1();
            refreshCursor2();

            if(buttonA == 1) { //select difficult
                fall = 3;
            }

        }
    }
}

// draw difficulty settings
void drawDifficultyMenu()
{
    lcd.clear();
    backGround();
    lcd.drawRect(0,47,84,0,1);//bottom border
    lcd.drawRect(0,0,84,2,1);//top border
    lcd.printString("*Difficulty*",5,7);//title
    lcd.printString("Easy",5,8);//title
    lcd.printString("Normal",5,9);//title
    lcd.printString("Forget It",5,10);//title
}

// actual game
void game(int& exitFlag, int& exitOption)
{

    actionButton();
    backButton();
    lcd.clear();//clears screen
    backGround();//draw background

    ///game///
    while(1) {
        // print score - top left of display
        char buffer[14];//create buffer for string
        int length = sprintf(buffer,"Level:%d",score);//insert buffer
        if (length <= 14)  //ensure length is smaller than screen
            lcd.printString(buffer,3,0);//display

        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;

            // 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;
                ninjaBoundaries();
            }
            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;
                ninjaBoundaries();
            }
            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",17,2);
                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) {
                drawExitMenu();//draws the exit menu

                while(1) {
                    exitMenu(exitOption);//presents exit options

                    // 'exit' option YES
                    if((buttonA == 1)&&(exitOption == 0)) { //returns to menu
                        actionButton();
                        lcd.clear();//clears screen
                        resetGame();//resets scores/objects
                        exitFlag = 1;//sets exit flag
                        break;
                    }
                    // 'exit' option NO - returns to game
                    if((buttonA == 1)&&(exitOption == 1)) {
                        break;
                    }
                }
                // if 'exit' option YES, resets
                // game values returns to main menu
                if (exitFlag!=0) { //if exit flag set
                    exitFlag = 0;//reset flag
                    break;//break to main menu
                }
            }
            serial.printf("Score: %i \n",score);
        }
    }
}

// high scores screen
void scores()
{
    actionButton();
    backButton();
    lcd.clear();//clear screen
    backGround();//set background
    lcd.printString("High Scores",10,0);//title

    // players high scores - highest first
    char highScore1[14];//create buffer for strings
    char highScore2[14];
    char highScore3[14];

    int player1 = sprintf(highScore1,"1.DRT.....99",score);//insert buffer
    int player2 = sprintf(highScore2,"2.NRG.....98",score);//insert buffer
    int player3 = sprintf(highScore3,"3.GRT.....10",score);//insert buffer

    if (player1 <= 14)  //ensure length is smaller than screen
        lcd.printString(highScore1,5,2);//display
    if (player2 <= 14)  //ensure length is smaller than screen
        lcd.printString(highScore2,5,3);//display
    if (player3 <= 14)  //ensure length is smaller than screen
        lcd.printString(highScore3,5,4);//display

    while(1) {
        actionButton();//select
        backButton();//back

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