Sie sind auf Seite 1von 13

#include <FEHLCD.

h>
#include <FEHIO.h>
#include <FEHUtility.h>
#include <cstdlib>
#include <ctime>

using namespace std;

//Includes all libraries used

ButtonBoard buttons(FEHIO::Bank3); //Connects button board to third bank of


Proteus

//Declare all user defined function prototypes, in-depth descriptions are by


the function definitions
void start_game();
void instructions();
void scores();
void credits();
void start_menu();
void wait();
void generate_wall(int *wall1,int *wall2,int *wall_gap);
void scroll(int *option);

//Create a class scorekeeper that keeps track of scores


class scorekeeper
{
public:
scorekeeper(); //Constructor that initializes the high scores
void sort_hscore(int *score); //Function that sorts the high scores
void display_hscores(); //Function that displays the high scores
private:
int score1; //Highest score so far
int score2; //Second highest score and so on
int score3;
int score4;
int score5;
};

//Constructor makes all high scores 0 at first


scorekeeper::scorekeeper()
{
score1 = 0;
score2 = 0;
score3 = 0;
score4 = 0;
score5 = 0;
}

//Sort function gets passed the value of the score


void scorekeeper::sort_hscore(int *score)
{ //This also contains one of many instances of relational operators in this
program
if (*score > score1) //If the score is greater than the current highest
score, shift all scores down and make it the new highest score
{
score5 = score4;
score4 = score3;
score3 = score2;
score2 = score1;
score1 = *score;
}
else if (*score > score2) //If the score is otherwise greater than the
second highest score, shift all scores down and make it the new second
highest score
{
score5 = score4;
score4 = score3;
score3 = score2;
score2 = *score;
}
else if (*score > score3) //Continue with the same thing for third,
fourth, and fifth highest scores
{
score5 = score4;
score4 = score3;
score3 = *score;
}
else if (*score > score4)
{
score5 = score4;
score4 = *score;
}
else if (*score > score5)
{
score5 = *score;
}
}

//Display function writes the high scores to the screen


void scorekeeper::display_hscores()
{
//Proper spacing is used to position and center the scores
LCD.WriteLine("");
LCD.WriteLine("");
LCD.WriteLine("");
LCD.WriteLine("------High Scores-----");
LCD.WriteLine("");
LCD.WriteLine("");
LCD.Write(" 1. ");
LCD.WriteLine(score1);
LCD.Write(" 2. ");
LCD.WriteLine(score2);
LCD.Write(" 3. ");
LCD.WriteLine(score3);
LCD.Write(" 4. ");
LCD.WriteLine(score4);
LCD.Write(" 5. ");
LCD.WriteLine(score5);
}

//Function randomly generates one of three preset wall types


void generate_wall(int *wall1,int *wall2, int *wall_gap)
{
srand(TimeNow()); //Seeds the time so the random number generator does
not repeat in a pattern
int wall_number = rand(); //Sets the random number generated to a
variable called wall number

if (wall_number % 3 == 0) //By finding the remainder after the wall


number is divided by 3, only values of 0, 1, and 2 become possible
{
LCD.SetFontColor(GREEN); //If the remainder is 0, generate a wall
with these specifications
LCD.FillRectangle(300, 0, 20, 60); //This will generate a green wall
at position(x,y) = (300, 0) with width 20 and height 60
LCD.FillRectangle(300, 120, 20, 120); //This will generate a green
wall at position (x,y) = (300, 100) with width 20 and height 140
//All walls will have a thickness of 20. The first wall will always
start at 0.The gap between the walls is the difference between
//the y position of the second wall (100) and the height of the first
wall (60), which will always be 40.
//The second wall's height is the amount required to reach the bottom
of the screen
*wall1 = 60; //This will pass back the height of the first wall to
the function that calls it
*wall2 = 120; //This will pass back the height of the second wall to
the function that calls it
*wall_gap = 120; //This will pass back the y position of the second
wall, effectively the gap
}
else if (wall_number % 3 == 1) //If the remainder is 1, generate a wall
with these specifications
{
LCD.SetFontColor(GREEN); //This wall will be the same as the previous
one, with different wall specifications for a gap at a different location
LCD.FillRectangle(300, 0, 20, 120);
LCD.FillRectangle(300, 180, 20, 60);
*wall1 = 120;
*wall2 = 60;
*wall_gap = 180;
}
else if (wall_number % 3 == 2) //If the remainder is 2, generate a wall
with these specifications
{
LCD.SetFontColor(GREEN); //Same as the previous walls, with a
different gap
LCD.FillRectangle(300, 0, 20, 160);
LCD.FillRectangle(300, 220, 20, 20);
*wall1 = 160;
*wall2 = 20;
*wall_gap = 220;
}
}

//Function begins the game and continues until the player dies
void start_game(scorekeeper *score_obj)
{
//All variables used are initialized here
float x, y; //Used to check for touch on the screen
int score = 0, sleep_counter = 0; //Used to keep track of the score and
to modulate the time interval of the function
int bird_x = 30, bird_y = 120; //Saves the initial position values of the
bird to variables

//Only three walls will ever be present on the screen at once, so each is
initialized. With no width or height these are at first invisible
int wall1 = 0, wall2 = 0, wall_gap = 0, wall_x = 300; //Initializes the
values of the first wall
int wall1_2 = 0, wall2_2 = 0, wall_gap_2 = 0, wall_x2 = 120;
//Initializes the values of the second wall
int wall1_3 = 0, wall2_3 = 0, wall_gap_3 = 0, wall_x3 = 220;
//Initializes the values of the third wall
double start_time; //Declares the start time variable to be used for an
initial time

start_time = TimeNow(); //The current time is used as the starting time


LCD.SetBackgroundColor(BLUE); //Background color becomes blue to imitate
the sky
LCD.SetFontColor(BLACK); //Color of the bird becomes black
LCD.Clear(); //Clears the screen and begins generating the map
LCD.FillCircle(bird_x, bird_y, 10); //This generates a circle of radius
10 at positions bird_x and bird_y as the bird

do //Use a do while loop to play the game infinitely


{
//Begin generating the walls
if ((int)(TimeNow()-start_time) % 24 == 0) //This if/else structure
generates a new wall every 8 seconds and assigns it to one of the wall
variable groups
{
generate_wall(&wall1, &wall2, &wall_gap); //Calls the generate
wall function with variable locations for the first wall
wall_x = 300; //Sets the x position of the wall back to the far
right of the screen
}
else if ((int)(TimeNow()-start_time) % 24 == 8) //The same thing is
done as the previous wall
{
generate_wall(&wall1_2, &wall2_2, &wall_gap_2);
wall_x2 = 300;
}
else if ((int)(TimeNow()-start_time) % 24 == 16)
{
generate_wall(&wall1_3, &wall2_3, &wall_gap_3);
wall_x3 = 300;
}

//Scoring system settings


if (bird_x == wall_x) //If the bird's x location is the same as the x
location of any of the three walls,
{ //the player is assumed to have passed the wall
and gets a point, which will bcome 50 after 50 ticks of the do while loop
score += 1;
}
if (bird_x == wall_x2)
{
score += 1;
}
if (bird_x == wall_x3)
{
score += 1;
}

//The font color is set to black and the score is displayed and
updated on screen
LCD.SetFontColor(BLACK);
LCD.WriteRC("Score", 13, 0);
LCD.WriteRC(score, 13, 6);

//Death parameters
//This is also one of many instances of logical operators in the
program
if ((bird_x >= wall_x && bird_x <= (wall_x+20))) //If the x position
of the bird is within the width of the walls
{ //and the y position
is within the height of the walls, the loop exits and ends the game
if ((bird_y >= 0 && bird_y <= (wall1)) || (bird_y >= wall_gap &&
bird_y <= 240))
{
break;
}
}

if (bird_x >= wall_x2 && bird_x <= (wall_x2+20)) //Death function is


the same for each wall
{
if ((bird_y >= 0 && bird_y <= (wall1_2)) || (bird_y >= wall_gap_2
&& bird_y <= 240))
{
break;
}
}

if (bird_x >= wall_x3 && bird_x <= (wall_x3+20))


{
if ((bird_y >= 0 && bird_y <= (wall1_3)) || (bird_y >= wall_gap_3
&& bird_y <= 240))
{
break;
}
}

if (bird_y <= 0 || bird_y >= 240) //If the bird's y position is at


the top of the screen or the bottom of the screen, the game also ends
{
break;
}

//if (!LCD.Touch(&x, &y))


//{

//Game will sleep in 1 milisecond intervals


Sleep(10);
sleep_counter += 1; //The sleep counter is incremented by one each
time

if (sleep_counter == 50) //When the sleep counter becomes 500, which


is equivalent to half a second passing, the screen is updated
{
LCD.SetFontColor(BLUE);
LCD.FillCircle(30, bird_y, 10); //This will clear the bird at its
previous position by setting it equal to the background color

bird_y += 15; //This will increase the y position of the bird,


making it go lower on the screen
LCD.SetFontColor(BLACK);
LCD.FillCircle(30, bird_y, 10); //This will generate the new bird
at a lower location, making it "fall"

LCD.SetFontColor(BLUE);
LCD.FillRectangle(wall_x, 0, 20, wall1);
LCD.FillRectangle(wall_x, wall_gap, 20, wall2); //This will clear
the first wall at its previous position

wall_x -= 15; //Reduces the x position of the wall by 15


LCD.SetFontColor(GREEN);
LCD.FillRectangle(wall_x, 0, 20, wall1);
LCD.FillRectangle(wall_x, wall_gap, 20, wall2); //This will
generate the new wall, 15 pixels closer to the player, making it "move"
across the screen

if (TimeNow()-start_time >= 8) //After 8 seconds have passed, the


second wall can begin generating and moving
{
LCD.SetFontColor(BLUE);
LCD.FillRectangle(wall_x2, 0, 20, wall1_2);
LCD.FillRectangle(wall_x2, wall_gap_2, 20, wall2_2);

wall_x2 -= 15;
LCD.SetFontColor(GREEN);
LCD.FillRectangle(wall_x2, 0, 20, wall1_2);
LCD.FillRectangle(wall_x2, wall_gap_2, 20, wall2_2);
}

if (TimeNow()-start_time >= 16) //After 16 seconds have passed,


the third wall can begin generating and moving
{
LCD.SetFontColor(BLUE);
LCD.FillRectangle(wall_x3, 0, 20, wall1_3);
LCD.FillRectangle(wall_x3, wall_gap_3, 20, wall2_3);

wall_x3 -= 15;
LCD.SetFontColor(GREEN);
LCD.FillRectangle(wall_x3, 0, 20, wall1_3);
LCD.FillRectangle(wall_x3, wall_gap_3, 20, wall2_3);
}

if (wall_x == 0) //If any of the walls reach the right hand side,
they disappear
{
LCD.SetFontColor(BLUE);
LCD.FillRectangle(wall_x, 0, 20, wall1);
LCD.FillRectangle(wall_x, wall_gap, 20, wall2);

wall_x = 0; //The wall variables are re-initialized to 0 so


they do not continue moving
wall1 = 0;
wall2 = 0;
wall_gap = 0;
}

if (wall_x2 == 0)
{
LCD.SetFontColor(BLUE);
LCD.FillRectangle(wall_x2, 0, 20, wall1_2);
LCD.FillRectangle(wall_x2, wall_gap_2, 20, wall2_2);

wall_x2 = 0;
wall1_2 = 0;
wall2_2 = 0;
wall_gap_2 = 0;
}

if (wall_x3 == 0)
{
LCD.SetFontColor(BLUE);
LCD.FillRectangle(wall_x3, 0, 20, wall1_3);
LCD.FillRectangle(wall_x3, wall_gap_3, 20, wall2_3);

wall_x3 = 0;
wall1_3 = 0;
wall2_3 = 0;
wall_gap_3 = 0;
}

sleep_counter = 0; //Reset the sleep counter so the game


continues to operate in half second intervals
}

if (LCD.Touch(&x, &y)) //If touch is detected, and the touch is


released, this executes
{
if (!LCD.Touch(&x, &y))
{
LCD.SetFontColor(BLUE);
LCD.FillCircle(30, bird_y, 10); //This will clear the bird at
its original position

bird_y -= 30; //This will decrease the y position of the


bird, making it go higher on the screen
LCD.SetFontColor(BLACK);
LCD.FillCircle(30, bird_y, 10); //This will generate the new
bird at a higher location, making it "flap"
Sleep(100); //The game will sleep for 100 miliseconds after
the bird flaps to prevent successive flaps
}
}
} while(true); //Repeat this loop infinitely until the player dies and
exits the loop

LCD.SetBackgroundColor(BLACK); //Background is set to black again and


text as white, displaying the game over screen
LCD.SetFontColor(WHITE);
LCD.Clear();
LCD.WriteRC("Game Over", 6, 7); //Tells the player the game is over
Sleep(3.0); //Message is displayed for 3 seconds

//Creates an object for the scorekeeper class and calls the sort
function, passing it the score value
(*score_obj).sort_hscore(&score);
LCD.Clear();
(*score_obj).display_hscores(); //Screen is cleared and the display high
scores function is called

wait(); //The screen stays on high scores until the player clicks the
left button

//Instructions function prints the instructions/rules of the game to the


screen
void instructions()
{
LCD.Clear();
LCD.WriteRC("------Instructions------", 1, 1);
LCD.WriteRC("Tap the screen to", 3, 1);
LCD.WriteRC("make the bird flap!", 4, 1);
LCD.WriteRC("Avoid the walls and", 6, 1);
LCD.WriteRC("don't fly off screen!", 7, 1);
LCD.WriteRC("For every wall you pass", 9, 1);
LCD.WriteRC("you earn 50 points!", 10, 1);
LCD.WriteRC("Good Luck!", 12, 1);

wait(); //Waits for the user to left click before going back to the start
menu
}

//Scores function will display the high scores


void scores(scorekeeper *score_obj)
{
LCD.Clear(); //Clears the screen
(*score_obj).display_hscores();

wait(); //Waits for the player to left click before moving back to the
main menu
}

//Credits function displays the credits


void credits()
{
LCD.Clear(); //Clears the screen and makes the font white
LCD.SetFontColor(WHITE);
LCD.WriteRC("-------Credits-------", 3, 1);
LCD.WriteRC("Co-Creator: Brian Dong", 5, 1);
LCD.WriteRC("Co-Creator: Yiyang Huang", 7, 1);
LCD.WriteRC("Based On Game by:", 9, 1);
LCD.WriteRC(" Dong Nguyen", 11, 1);

wait(); //Waits for the player to left click before moving to page 2

LCD.Clear();
LCD.WriteRC("-------Credits-------", 3, 1);
LCD.WriteRC("Contributor: Peter Schmitz", 5, 0);
LCD.WriteRC("Contributor: Alex Jacobs", 7, 1);
LCD.WriteRC("Project Overseer:", 9, 1);
LCD.WriteRC(" Dr. Philip Schlosser", 11, 1);

wait(); //Waits for left click before moving back to main menu
}

//Wait function waits for the user to press and release the left button
void wait()
{
while (!buttons.LeftPressed()); //Game repeats an infinite loop while the
button is not pressed
//Once the button is pressed, the game
leaves the previous loop and enters the next one
while (buttons.LeftPressed()); //Game repeats an infinite loop while the
button remains pressed, and exits when the button is no longer pressed
}

//Scroll function takes an integer input and changes the font color of the
selection screen to match the user scrolling
void scroll(int *option)
{
switch (*option)
//if (*option == 1) //If the option variable is 1, make start game red
and the others white
{
case 1:
LCD.Clear();
LCD.SetFontColor(RED);
LCD.WriteRC("Start Game", 4, 9);
LCD.SetFontColor(WHITE);
LCD.WriteRC("Instructions", 6, 9);
LCD.WriteRC("Scores", 8, 9);
LCD.WriteRC("Credits", 10, 9);
break;
//}
//else if (*option == 2) //If the option variable is 2, make instructions
red and the others white
//{
case 2:
LCD.Clear();
LCD.SetFontColor(WHITE);
LCD.WriteRC("Start Game", 4, 9);
LCD.SetFontColor(RED);
LCD.WriteRC("Instructions", 6, 9);
LCD.SetFontColor(WHITE);
LCD.WriteRC("Scores", 8, 9);
LCD.WriteRC("Credits", 10, 9);
break;
//}
//else if (*option == 3) //Repeat for scores
//{
case 3:
LCD.Clear();
LCD.SetFontColor(WHITE);
LCD.WriteRC("Start Game", 4, 9);
LCD.WriteRC("Instructions", 6, 9);
LCD.SetFontColor(RED);
LCD.WriteRC("Scores", 8, 9);
LCD.SetFontColor(WHITE);
LCD.WriteRC("Credits", 10, 9);
break;
//}
//else if (*option == 4) //Repeat for credits
//{
case 4:
LCD.Clear();
LCD.SetFontColor(WHITE);
LCD.WriteRC("Start Game", 4, 9);
LCD.WriteRC("Instructions", 6, 9);
LCD.WriteRC("Scores", 8, 9);
LCD.SetFontColor(RED);
LCD.WriteRC("Credits", 10, 9);
break;
}
}

//Function generates the intro screen and the start menu and all its options
void start_menu()
{
//Create a scorekeeper object to pass to score function and start game
function
scorekeeper score_obj;

// Introduction screen to the game; Set screen to black and font to white
LCD.Clear(FEHLCD::Black);
LCD.SetFontColor(FEHLCD::White);

// Display title screen


LCD.WriteRC("|----------------------|", 3, 1);
LCD.WriteRC("| |", 4, 1);
LCD.WriteRC("| Flappy Bird |", 5, 1);
LCD.WriteRC("| |", 6, 1);
LCD.WriteRC("|----------------------|", 7, 1);
LCD.WriteRC("Gold(fish) Games Inc.", 11, 3);
Sleep(3.0); //Shows title screen for three seconds
LCD.Clear();

// Display basic navigation instructions


LCD.WriteRC("------Navigation------", 1, 1);
LCD.WriteRC("Use the left button", 3, 1);
LCD.WriteRC("to select options and", 4, 1);
LCD.WriteRC("move to the next screen", 5, 1);
LCD.WriteRC("Use the middle button", 7, 1);
LCD.WriteRC("to scroll down", 8, 1);
LCD.WriteRC("Use the right button", 10, 1);
LCD.WriteRC("to scroll up", 11, 1);

wait(); //Waits for the user to left click the button board

//This displays the game options, with start game as the default
selection in red
LCD.Clear();
LCD.SetFontColor(RED);
LCD.WriteRC("Start Game", 4, 9);
LCD.SetFontColor(WHITE);
LCD.WriteRC("Instructions", 6, 9);
LCD.WriteRC("Scores", 8, 9);
LCD.WriteRC("Credits", 10, 9);

int option = 1; //Option is initialized to start game

//while (true)
//This will execute infinitely
for (;;)
{
if (buttons.LeftPressed()) //If the left button is pressed, execute
{
if (buttons.LeftReleased()) //If the left button is released,
execute
{
//if (option == 1)
switch (option) //This switch case executes each option
depending on the value of option at this instance
{
case 1: //If the value of option is 1, the start game
function is called to start the game
start_game(&score_obj);
LCD.Clear(); //After the player dies, the screen is
cleared and restored to the selection menu with start game as default
selection
LCD.SetFontColor(RED);
LCD.WriteRC("Start Game", 4, 9);
LCD.SetFontColor(WHITE);
LCD.WriteRC("Instructions", 6, 9);
LCD.WriteRC("Scores", 8, 9);
LCD.WriteRC("Credits", 10, 9);
break;
//}
//else if (option == 2)
case 2: //If the value of option is 2, the instructions
function is called to display instructions for the game
//{
instructions();
LCD.Clear(); //After the player exits, the screen is
restored to the selection menu, with instructions still selected
LCD.SetFontColor(WHITE);
LCD.WriteRC("Start Game", 4, 9);
LCD.SetFontColor(RED);
LCD.WriteRC("Instructions", 6, 9);
LCD.SetFontColor(WHITE);
LCD.WriteRC("Scores", 8, 9);
LCD.WriteRC("Credits", 10, 9);
break;
//}
//else if (option == 3)
//{
case 3: //If the value of option is 3, the scores
function is called to display the scores
scores(&score_obj);
LCD.Clear(); //After the player exits, the screen is
restored to the selection menu, with scores still selected
LCD.SetFontColor(WHITE);
LCD.WriteRC("Start Game", 4, 9);
LCD.WriteRC("Instructions", 6, 9);
LCD.SetFontColor(RED);
LCD.WriteRC("Scores", 8, 9);
LCD.SetFontColor(WHITE);
LCD.WriteRC("Credits", 10, 9);
break;
//}
//else if (option == 4)
//{
case 4: //If the value of option is 4, the credits
function is called to display the credits
credits();
LCD.Clear(); //After the player exits, the screen is
restored to the selection menu, with credits still selected
LCD.SetFontColor(WHITE);
LCD.WriteRC("Start Game", 4, 9);
LCD.WriteRC("Instructions", 6, 9);
LCD.WriteRC("Scores", 8, 9);
LCD.SetFontColor(RED);
LCD.WriteRC("Credits", 10, 9);
break;
}
}
}
else if (buttons.MiddlePressed()) //If the middle button is pressed,
execute
{
if (buttons.MiddleReleased()) //If the middle button is released,
execute
{
if (option < 4) //If the variable option is currently less
than 4, add one to it
{
option += 1;
}
scroll(&option); //Pass the increased option value to the
scroll function, which then changes the font of the options to imitate
scrolling down
}
}
else if (buttons.RightPressed()) //If the right button is pressed,
execute
{
if (buttons.RightReleased()) //If the right button is released
execute
{
if (option > 1) //If the variable is currently greater than
1, subtract one from it
{
option -= 1;
}
scroll (&option); //Pass the decreased option value to the
scroll function, which then changes the font of the options to imitate
scrolling up
}
}
}
}

//Main function of the program, mostly to call the start menu function
int main(void)
{
start_menu(); //Calls the start menu, program will end when the proteus
is shut down
}

Das könnte Ihnen auch gefallen