Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of DocTest by
main.cpp
- Committer:
- 200784123
- Date:
- 2015-05-10
- Revision:
- 3:b78d65300f24
- Parent:
- 2:5446154a4028
File content as of revision 3:b78d65300f24:
/**
@file main.cpp
@brief Program implementation
*/
#include "main.h"
int main(){
///minimal amount of code in the main, see All() for more
All();
}
///all of the function that would normally reside in the main
void All(){
calibrateJoystick(); ///get the centred values of the joystick
bright=5;
while(1) {
if(screen)
lcd.inverseMode();
if(!screen)
lcd.normalMode();
lcd.refresh();
Initialise();
start();
}
}
///all of the variable, flags, tickers, and anything else that needs to set each time it's powered up
void Initialise(){
lcd.init();
Power.attach(&powerDown,1.0);///increases the power counter every second
backlight.attach(&brightness,1.0/10.0);///updates the brightness 10 times a second
pollJoystick.attach(&updateJoystick,1.0/10.0); /// read joystick 10 times per second
i=1;
j=24;
life=3;
winFlag=0;
startFlag=1;
buzzer.period(0.002);
c=1;
}
///goes into deep power down if nothing happens for a set time
void powerDown(){
power++;
if(power==55){
red1=0;
red2=0.1*bright;
red3=0;
yel=0.1*bright;
buzzer=0.4;
}
if(power==56){
red1=0.1*bright;
red2=0;
red3=0.1*bright;
yel=0;
buzzer=0.9;
}
if(power==57){
red1=0;
red2=0.1*bright;
red3=0;
yel=0.1*bright;
buzzer=0.4;
}
if(power==58){
red1=0.1*bright;
red2=0;
red3=0.1*bright;
yel=0;
buzzer=0.9;
}
if(power==59){
red1=0;
red2=0.1*bright;
red3=0;
yel=0.1*bright;
buzzer=0.4;
}
if(power>=60){
red1=0.1*bright;
red2=0;
red3=0.1*bright;
yel=0;
buzzer=0.9;
DeepPowerDown();
}
}
///the start screen, shows up at the begining and when the player runs out of lives
///links to the options menu, the highscores, the level select etc.
void start(){
power=0;
clear();
lcd.refresh();
butt.rise(&menus);
push.rise(&menus);
startFlag=1;
while(c) {
lcd.clearPixel(i,j);
lcd.printString("Click",25,2);
lcd.refresh();
}
clear();
while(startFlag) {
lcd.clearPixel(i,j);
while(joystick.direction!=CENTRE) {
lcd.clearPixel(i,j);
///do nothing, stay on current screen
lcd.printString("^ Options ^",10,0);
lcd.printString("< Score Inv. >",0,2);
lcd.printString("v Levels v",12,5);
lcd.refresh();
}
if(joystick.direction==CENTRE) {
lcd.clearPixel(i,j);
lcd.printString("^ Options ^",10,0);
lcd.printString("< Score Inv. >",0,2);
lcd.printString("v Levels v",12,5);
lcd.refresh();
///for some reason if UP is used to change the flag then it goes straight to the maze
}
if(joystick.direction==UP) {
power=0;
lcd.clearPixel(i,j);
toggle();
Options();
}
if (joystick.direction==DOWN) {
power=0;
lcd.clearPixel(i,j);
toggle();
Levels();
}
if(joystick.direction==LEFT) {
power=0;
lcd.clearPixel(i,j);
toggle();
Score();
}
if(joystick.direction==RIGHT) {
power=0;
lcd.clearPixel(i,j);
///go to the inverse function
screen=!screen;
if(screen)
lcd.inverseMode();
if(!screen)
lcd.normalMode();
lcd.refresh();
}
}
lcd.clearPixel(i,j);
clear();
}
///function called to escape back to the main menu
void menus(){
power=0;
lcd.clearPixel(i,j);
clear();
timeout.attach_us(&toggle,10);
}
///function called to toggle, clear, or set various flags
void toggle(){
power=0;
l=!l;
r=!r;
u=!u;
d=!d;
c=0;
b=!b;
startFlag=1;
}
///the options menu, links to the reset, brightness, and end game
void Options(){
power=0;
lcd.clearPixel(i,j);
clear();
while(u) {
lcd.clearPixel(i,j);
while(joystick.direction!=CENTRE) {
///do nothing, just sit on current screen
lcd.clearPixel(i,j);
lcd.printString("~~~~~~~~~~~~~~",0,0);
lcd.printString("^ Brightness ^",0,1);
lcd.printString("< Reset",10,2);
lcd.printString("End >",30,3);
lcd.printString("v Back v",15,4);
lcd.printString("~~~~~~~~~~~~~~",0,5);
lcd.refresh();
}
lcd.clearPixel(i,j);
lcd.printString("~~~~~~~~~~~~~~",0,0);
lcd.printString("^ Brightness ^",0,1);
lcd.printString("< Reset",10,2);
lcd.printString("End >",30,3);
lcd.printString("v Back v",15,4);
lcd.printString("~~~~~~~~~~~~~~",0,5);
lcd.refresh();
if(joystick.direction==DOWN) {
power=0;
lcd.clearPixel(i,j);
///escape back to the first menu
start();
}
if (joystick.direction==UP) {
power=0;
lcd.clearPixel(i,j);
///go to the brightness function
clear();
while(b) {
lcd.clearPixel(i,j);
red1=0.1*bright;
red2=0.1*bright;
red3=0.1*bright;
yel=0.1*bright;
push.rise(&Dark);
butt.rise(&Light);
lcd.printString("click joy - up",0,1);
lcd.printString("or pink - down",0,3);
lcd.printString("v Back v",15,5);
lcd.refresh();
if(joystick.direction==DOWN) {
Options();
}
}
}
if (joystick.direction==LEFT) {
power=0;
lcd.clearPixel(i,j);
toggle();
score1=0;
scoreWrite1();
score2=0;
scoreWrite2();
score3=0;
scoreWrite3();
}
if(joystick.direction==RIGHT) {
power=0;
lcd.clearPixel(i,j);
winFlag=1;
endGame();
}
}
lcd.clearPixel(i,j);
clear();
}
///debouncing code for the light() function
void Light(){
timeout.attach_us(&light,100);
}
///debouncing code for the dark() function
void Dark(){
timeout.attach_us(&dark,100);
}
///function called to increase the LED and backlight birghtness variable
void light(){
bright++;
if(bright>10)
bright=10;
}
///function called to decrease the LED and backlight brightness variable
void dark(){
bright--;
if(bright<1)
bright=1;
}
///function called to set the LCD backlight brightness from the brigtness variable
void brightness(){
lcd.setBrightness(0.1*bright);
}
///the level select menu, allows the player to choose between three levels by moveing the joystick left, down, or right
void Levels(){
power=0;
push.rise(&menus);
butt.rise(&menus);
clear();
while(d) {
lcd.clearPixel(i,j);
while(joystick.direction!=CENTRE) {
///do nothing, stay on current screen
lcd.clearPixel(i,j);
lcd.printString("~~~~~~~~~~~~~~",0,0);
lcd.printString("Left = 1",10,2);
lcd.printString("Down = 2",10,3);
lcd.printString("Right = 3",10,4);
lcd.printString("^ Back ^",15,1);
lcd.printString("~~~~~~~~~~~~~~",0,5);
lcd.refresh();
}
lcd.clearPixel(i,j);
lcd.printString("~~~~~~~~~~~~~~",0,0);
lcd.printString("Left = 1",10,2);
lcd.printString("Down = 2",10,3);
lcd.printString("Right = 3",10,4);
lcd.printString("^ Back ^",15,1);
lcd.printString("~~~~~~~~~~~~~~",0,5);
lcd.refresh();
if(joystick.direction==UP) {
power=0;
lcd.clearPixel(i,j);
///escape back to the first menu
toggle();
start();
}
if(joystick.direction==LEFT) {
power=0;
lcd.clearPixel(i,j);
///go to the preview screen for level 1
clear();
while(joystick.direction==LEFT) {
lcd.clearPixel(i,j);
lcd.printString("Level 1",15,2);
lcd.refresh();
mazeFlag=1;
}
clear();
mainGame();
}
if(joystick.direction==DOWN) {
power=0;
lcd.clearPixel(i,j);
///go to the preview screen for level 2
clear();
while(joystick.direction==DOWN) {
lcd.clearPixel(i,j);
lcd.printString("Level 2",15,2);
lcd.refresh();
mazeFlag=2;
}
clear();
mainGame();
}
if(joystick.direction==RIGHT) {
power=0;
lcd.clearPixel(i,j);
///go to the preview screen for level 3
clear();
while(joystick.direction==RIGHT) {
power=0;
lcd.clearPixel(i,j);
lcd.printString("Level 3",15,2);
lcd.refresh();
mazeFlag=3;
}
clear();
mainGame();
}
}
lcd.clearPixel(i,j);
clear();
}
///the scores menu, displays the currently saved high score for the three levels
/// moving the joystick different directions displays the scores for the different levels
void Score(){
power=0;
lcd.clearPixel(i,j);
push.rise(&menus);
butt.rise(&menus);
clear();
while(l) {
lcd.clearPixel(i,j);
while(joystick.direction!=CENTRE) {
///do nothing, stay on current screen
lcd.clearPixel(i,j);
lcd.printString("~~~~~~~~~~~~~~",0,0);
lcd.printString("High Score",10,1);
lcd.printString("> Back >",15,4);
lcd.printString("~~~~~~~~~~~~~~",0,5);
lcd.refresh();
}
lcd.clearPixel(i,j);
lcd.printString("~~~~~~~~~~~~~~",0,0);
lcd.printString("High Score",10,1);
lcd.printString("> Back >",15,4);
lcd.printString("~~~~~~~~~~~~~~",0,5);
lcd.refresh();
if(joystick.direction==RIGHT) {
power=0;
///escape back to the first menu
start();
}
if(joystick.direction==UP) {
power=0;
lcd.clearPixel(i,j);
///show the high score/fastest time for level 1
clear();
while(joystick.direction!=DOWN){
lcd.clearPixel(i,j);
lcd.printString("Level 1 best",7,1);
scoreRead1();
lcd.refresh();
}
clear();
}else if(joystick.direction==LEFT) {
power=0;
lcd.clearPixel(i,j);
///show the high score/fastest time for level 2
clear();
while(joystick.direction!=RIGHT){
lcd.clearPixel(i,j);
lcd.printString("Level 2 best",7,1);
scoreRead2();
lcd.refresh();
}
clear();
}else if(joystick.direction==DOWN) {
power=0;
lcd.clearPixel(i,j);
///show the high score/fastest time for level 3
clear();
while(joystick.direction!=UP){
lcd.clearPixel(i,j);
lcd.printString("Level 3 best",7,1);
scoreRead3();
lcd.refresh();
}
clear();
}
}
lcd.clearPixel(i,j);
clear();
}
///writes the score for the first level to file
void scoreWrite1(){
FILE *fp = fopen("/local/score1.txt","w");///opens the file score1.txt
///if the file doesn't exist it creates it, if it exists it updates
fprintf(fp,"%i",score1);///prints the integer value for the score to file
fclose(fp);
}
///reads the currently saved score for the first level
void scoreRead1(){
int Score1;///tells it that the value to be read is an integer value
FILE *fp1 = fopen("/local/score1.txt","r");///opens score1.txt
fscanf(fp1,"%i",&Score1);///searches the file for an integer
fclose(fp1);
char Points1[14];///bufer to store the points value
sprintf(Points1,"%i",Score1);///sends the score to the buffer
lcd.printString(Points1,30,3);///prints the score to the LCD
}
///writes the score for the second level to file
void scoreWrite2(){
FILE *fp2 = fopen("/local/score2.txt","w");///opens the file score2.txt
///if the file doesn't exist it creates it, if it exists it updates
fprintf(fp2,"%i",score2);///prints the integer value for the score to file
fclose(fp2);
}
///reads the currently saved score for the second level
void scoreRead2(){
int Score2;///tells it that the value to be read is an integer value
FILE *fp3 = fopen("/local/score2.txt","r");///opens score2.txt
fscanf(fp3,"%i",&Score2);///searches the file for an integer
fclose(fp3);
char Points2[14];///bufer to store the points value
sprintf(Points2,"%i",Score2);///sends the score to the buffer
lcd.printString(Points2,30,3);///prints the score to the LCD
}
///writes the score for the third level to file
void scoreWrite3(){
FILE *fp4 = fopen("/local/score3.txt","w");///opens the file score3.txt
///if the file doesn't exist it creates it, if it exists it updates
fprintf(fp4,"%i",score3);///prints the integer value for the score to file
fclose(fp4);
}
///reads the curently saved score for the third level
void scoreRead3(){
int Score3;///tells it that the value to be read is an integer value
FILE *fp5 = fopen("/local/score3.txt","r");///opens score3.txt
fscanf(fp5,"%i",&Score3);///searches the file for an integer
fclose(fp5);
char Points3[14];///bufer to store the points value
sprintf(Points3,"%i",Score3);///sends the score to the buffer
lcd.printString(Points3,30,3);///prints the score to the LCD
}
///function called to quite the game and return to the menu
///, has the same effect on the game as running out of lives while playing
void pause(){
power=0;
lcd.clearPixel(i,j);
i=1;
j=24;
winFlag=0;
life=0;
}
///all of the functions that make up the main game
void mainGame(){
count.attach(&counter,1.0);///counts every second for the lives function etc.
flash.attach(&Flash,0.25);
push.rise(&pause);
butt.rise(&pause);
life=3;
startFlag=0;
winFlag=0;
clear();
maze1();
i=1;
j=24;
while(life&&!winFlag) {
power=0;
border();
if (printFlag) {
printFlag=0;
move();
}
collide1();
winning();
lives();
if(flashFlag)
lcd.clearPixel(i,j);
if(!flashFlag||joystick.direction!=CENTRE)
lcd.setPixel(i,j);
lcd.refresh();
}
if(mazeFlag==1){
score1=mazeFlag*life*(100-countFlag);///change this equation to change how the score is set
if(screen)
score1=score1+50;///change this equation to change how the score is set
int Score1;///tells it that the value to be read is an integer value
FILE *fp1 = fopen("/local/score1.txt","r");///opens score1.txt
fscanf(fp1,"%i",&Score1);///searches the file for an integer followed by a string
fclose(fp1);
if(score1>Score1)
scoreWrite1();
}
if(mazeFlag==2){
score2=mazeFlag*life*(100-countFlag);///change this equation to change how the score is set
if(screen)
score2=score2+50;///change this equation to change how the score is set
int Score2;///tells it that the value to be read is an integer value
FILE *fp3 = fopen("/local/score2.txt","r");///opens score2.txt
fscanf(fp3,"%i",&Score2);///searches the file for an integer
fclose(fp3);
if(score2>Score2)
scoreWrite2();
}
if(mazeFlag==3){
score3=mazeFlag*life*(100-countFlag);///change this equation to change how the score is set
if(screen)
score3=score3+50;///change this equation to change how the score is set
int Score3;///tells it that the value to be read is an integer value
FILE *fp5 = fopen("/local/score3.txt","r");///opens score3.txt
fscanf(fp5,"%i",&Score3);///searches the file for an integer followed by a string
fclose(fp5);
if(score3>Score3)
scoreWrite3();
}
clear();
}
///mini game fashioned after the style of etch-a-sketch
void endGame(){
flash.attach(&Flash,0.25);
red1=0;
red2=0;
red3=0;
yel=0;
buzzer=0;
push.rise(&menus);
butt.rise(&clear);
lcd.clear();
i=42;
j=24;
while(b) {
power=0;
endBorder();
lcd.setPixel(i,j);
if(flashFlag)
lcd.clearPixel(i,j);
if(!flashFlag||joystick.direction!=CENTRE)
lcd.setPixel(i,j);
if(printFlag) {
printFlag=0;
endMove();
lcd.refresh();
}
}
lcd.clearPixel(i,j);
clear();
lcd.refresh();
i=1;
j=24;
}
///function called to clear the screen in the mini game if the external button is pressed
///and anywhere else its called
void clear(){
lcd.clearPixel(i,j);
lcd.clear();
lcd.refresh();
}
///function linked to the flash ticker
///toggles the flag between 0 and 1 and sets the pixel to flash
void Flash(){
flashFlag=!flashFlag;
lcd.setPixel(i,j);
}
///function called to check if the goal area has been reached in the time
///if not then the player is sent back to the begining of the level
///also indicates when time is running out on the buzzer and yellow LED
///added a safe zone at the start of the maze so the counter doesn't start straight away
///being in the safe zone stops the counter and flashes the yellow LED
void counter(){
buzzer=0;
if((i==0||i==1||i==2||i==3)){
yel=!yel;
countFlag=0;
}
if(!(i==0||i==1||i==2||i==3))
yel=0;
if(startFlag){
red1=0;
red2=0;
red3=0;
yel=0;
}
/////the possition of the safe zone
if(!startFlag&&!(i==0||i==1||i==2||i==3))
countFlag++;
/////if the current pixel is in the safe zone
if(mazeFlag==3){
if(!winFlag&&(countFlag==37||countFlag==38||countFlag==39)) {///change these numbers to change the warning time before the time limit
yel=0.1*bright;
buzzer=0.9;
}
if(countFlag==40) {///change this number to change the time limi for the level
countFlag=0;
yel=0;
buzzer=0;
life--;
lcd.clearPixel(i,j);
if(!winFlag) {
i=1;
j=24;
}
}
}
if(mazeFlag==2){
if(!winFlag&&(countFlag==42||countFlag==43||countFlag==44)) {///change these numbers to change the warning time before the time limit
yel=0.1*bright;
buzzer=0.9;
}
if(countFlag==45) {///change this number to change the time limi for the level
countFlag=0;
yel=0;
buzzer=0;
life--;
lcd.clearPixel(i,j);
if(!winFlag) {
i=1;
j=24;
}
}
}
if(mazeFlag==1){
if(!winFlag&&(countFlag==27||countFlag==28||countFlag==29)) {///change these numbers to change the warning time before the time limit
yel=0.1*bright;
buzzer=0.9;
}
if(countFlag==30) {///change this number to change the time limi for the level
countFlag=0;
yel=0;
buzzer=0;
life--;
lcd.clearPixel(i,j);
if(!winFlag) {
i=1;
j=24;
}
}
}
}
///displays the number of remaining level attempts, or lives, on the red LEDS
void lives(){
if(life==3) {
red1=0.1*bright;
red2=0.1*bright;
red3=0.1*bright;
} else if(life==2) {
red1=0.0;
red2=0.1*bright;
red3=0.1*bright;
} else if(life==1) {
red1=0.0;
red2=0.0;
red3=0.1*bright;
} else {
red1=0.0;
red2=0.0;
red3=0.0;
start();
}
}
///function that checks if the goal area has been reached
void winning(){
if(j==0){///if the pixel reaches the top top of the screen
lcd.clearPixel(i,j);
i=1;
j=24;
winFlag=1;
}
}
///displays the maze by opening a picture and setting the pixels accordingly
void maze1(){
for (int x = 0; x <= ny-1; x++) {
if(mazeFlag==1){
img = fopen("/local/TEST.BMP", "r");///TEST.BMP, 3x3 walls, 5x5 corridoors, if the corners are solid then the player dies when they go into one beacause the number of neighbouring pixels is the same as a collision
}
if(mazeFlag==2){
img = fopen("/local/MAZE1.BMP", "r");///MAZE1.BMP, 3x3 walls, 4x4 corridoors, if the corners are solid then the player dies when they go into one beacause the number of neighbouring pixels is the same as a collision
}
if(mazeFlag==3){
img = fopen("/local/MAZE2.BMP", "r");////MAZE2.BMP, 3x3 walls, 3x3 corridorrs, if the corners are solid then the player dies when they go into one beacause the number of neighbouring pixels is the same as a collision
}
fseek (img , 54 + (nx*x*3) , SEEK_SET);
fread(imgbuffer, (nx*3), 1, img);
fclose(img);
for (int y = 0; y <= nx-1; y++) {
int red = imgbuffer[y*3];
if (red == 0) {
lcd.setPixel(y,(ny-1)-x);
}
}
}
lcd.refresh();
}
///hardwall boundary so the player can't go off the screen
void border(){
if (i>=nx)
i=nx-1;
if (i<=0)
i=0;
if (j>=ny)
j=ny-1;
if (j<=0)
j=0;
}
///portal boundary, so the player can go from one side to another or top to bottom, used in the mini game only
void endBorder(){
if (i>=nx)
i=0;
if (i<0)
i=nx-1;
if (j>=ny)
j=0;
if (j<0)
j=ny-1;
}
///function called to check if the player is trying to move through a solid object
void collide1(){
int block=0;
if(joystick.direction==UP){
if(lcd.getPixel(i,j)&&lcd.getPixel(i,j-1)){
block++;
}
if(lcd.getPixel(i+1,j)||lcd.getPixel(i-1,j)){
block++;
}
}
if(joystick.direction==DOWN){
if(lcd.getPixel(i,j)&&lcd.getPixel(i,j+1)){
block++;
}
if(lcd.getPixel(i+1,j)||lcd.getPixel(i-1,j)){
block++;
}
}
if(joystick.direction==LEFT){
if(lcd.getPixel(i,j)&&lcd.getPixel(i-1,j)){
block++;
}
if(lcd.getPixel(i,j+1)||lcd.getPixel(i,j-1)){
block++;
}
}
if(joystick.direction==RIGHT){
if(lcd.getPixel(i,j)&&lcd.getPixel(i+1,j)){
block++;
}
if(lcd.getPixel(i,j+1)||lcd.getPixel(i,j-1)){
block++;
}
}
if(block==2){
if(!(i==0||i==1||i==2||i==3)){///outside the safe zone
lcd.clearPixel(i,j);
clear();
maze1();
life--;
i=1;
j=24;
countFlag=0;
}else{
lcd.clearPixel(i,j);
clear();
maze1();
i=1;
j=24;
countFlag=0;
}
}
}
///checks the joystick direction and alters the possition of the pixel accordingly while clearing off where the pixel just was
///used in the main game only
void move(){
if (joystick.direction == DOWN) {
j++;
lcd.clearPixel(i,j-1);
}
if (joystick.direction == UP) {
j--;
lcd.clearPixel(i,j+1);
}
if (joystick.direction == LEFT) {
i--;
lcd.clearPixel(i+1,j);
}
if (joystick.direction == RIGHT) {
i++;
lcd.clearPixel(i-1,j);
}
}
///checks the direction of the joystick and updates the position of the pixel accordingly
///keeps the path drawn unless cleared by the button, see clear()
void endMove(){
if (joystick.direction == DOWN) {
j++;
}
if (joystick.direction == UP) {
j--;
}
if (joystick.direction == LEFT) {
i--;
}
if (joystick.direction == RIGHT) {
i++;
}
}
/* Joystick
Example code of how to read a joystick
https://www.sparkfun.com/products/9032
Craig A. Evans
7 March 2015
*/
/// 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;
}
/// read current joystick values relative to calibrated values (in range -0.5 to 0.5, 0.0 is centred)
void updateJoystick(){
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 = DOWN;
} else if ( joystick.y < DIRECTION_TOLERANCE && fabs(joystick.x) < DIRECTION_TOLERANCE) {
joystick.direction = UP;
} 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;
}
/// set flag for printing
printFlag = 1;
}
