
Labyrinth of the Minotaur A simple roguelike/RPG using a nokia 5110 screen
Dependencies: N5110 PowerControl mbed
Game.cpp
- Committer:
- ThomasBGill
- Date:
- 2015-05-11
- Revision:
- 33:4fc26476b2e0
- Parent:
- 32:99ca304085e6
- Child:
- 34:e58c8322884d
File content as of revision 33:4fc26476b2e0:
#include "Game.h" //Power Saving int semihost_powerdown() { uint32_t arg; return __semihost(USR_POWERDOWN, &arg); } //ISR void ActPressed() { ActFlag = 1; } void StartPressed() { StartFlag = 1; } //Joystick functions // 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 = 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; } else { joystick.direction = Unknown; } } //High score system void writeDataToFile() { FILE *fp = fopen("/local/highscore.txt", "w"); // open 'highscore.txt' for writing fprintf(fp,"%d\r\n",HScore1); // print score to file fprintf(fp,"%d\r\n",HScore2); // print score to file fprintf(fp,"%d\r\n",HScore3); // print score to file fprintf(fp,"%d\r\n",HScore4); // print score to file fclose(fp); // close file } void readDataFromFile() { FILE *fp = fopen("/local/highscore.txt", "r"); // open 'highscore.txt' for writing fscanf(fp,"%d", &HScore1); // read score from file and save to int fscanf(fp,"%d", &HScore2); // read score from file and save to int fscanf(fp,"%d", &HScore3); // read score from file and save to int fscanf(fp,"%d", &HScore4); // read score from file and save to int fclose(fp); // close file } void HighScoreCheck() { readDataFromFile(); if(score >= HScore1) { HScore4 = HScore3; HScore3 = HScore2; HScore2 = HScore1; HScore1 = score; } else if(score >= HScore2) { HScore4 = HScore3; HScore3 = HScore2; HScore2 = score; } else if(score >= HScore3) { HScore4 = HScore3; HScore3 = score; } else if(score > HScore4) { HScore4 = score; } writeDataToFile(); } //Graphic functions void DrawGraphic(int p, int y, int x) { for(int i = 0; i < 38; i++) { for(int j = 0; j < 38; j++) { if(p == 0 ) { if(HugeRat[i][j] == 1) { lcd.setPixel(y+i, x+j); } } else if(p == 1 ) { if(Goblin[i][j] == 1) { lcd.setPixel(y+i, x+j); } } else if(p == 2 ) { if(Skeleton[i][j] == 1) { lcd.setPixel(y+i, x+j); } } else if(p == 3 ) { if(Wraith[i][j] == 1) { lcd.setPixel(y+i, x+j); } if(rand()%4 == 1) { lcd.setPixel(y+i, x+j); } } else if(p == 4 ) { if(Ogre[i][j] == 1) { lcd.setPixel(y+i, x+j); } } else if(p == 5 ) { if(Minotaur[i][j] == 1) { lcd.setPixel(y+i, x+j); } } } } } void FlashScreen(int n) { for (int i = 0; i<n; i++) { lcd.inverseMode(); lcd.refresh(); wait(0.2); lcd.normalMode(); lcd.refresh(); wait(0.2); } } //Game functions void Intro() { lcd.clear(); lcd.printString("Labyrinth", 15, 1); lcd.printString("of the", 24, 2); lcd.printString("Minotaur", 18, 3); lcd.refresh(); wait(1.0); } void Initilize() { score = -100; level = 0; //Player Health ph = PH_MAX; //Player weapon pw = 0; //0 to 4 //Player armour pa = 5; //5 to 9 } void MainMenu() { Initilize(); int menu = 0; while (1) { ActFlag = 0; lcd.clear(); if (menu == 0) { lcd.printString("New Game <", 6, 1); lcd.printString("High Scores", 6, 2); lcd.printString("Options", 6, 3); lcd.refresh(); } else if (menu == 1) { lcd.printString("New Game", 6, 1); lcd.printString("High Scores <", 6, 2); lcd.printString("Options", 6, 3); lcd.refresh(); } else { lcd.printString("New Game", 6, 1); lcd.printString("High Scores", 6, 2); lcd.printString("Options <", 6, 3); lcd.refresh(); } Sleep(); if (joystick.direction == Up) { if(menu > 0) { menu--; } } if(joystick.direction == Down) { if(menu < 3) { menu++; } } if (ActFlag) { ActFlag = 0; if (menu == 0) { GameLoop(); } else if (menu == 1) { HighScoreScreen(); } else { Options(); } } } } void Options() { bool bright = 1; lcd.clear(); while(1) { if(bright == 1) { lcd.printString("Backlight ON", 6, 2); } else { lcd.printString("Backlight OFF", 6, 2); } lcd.refresh(); if (joystick.direction != Centre) { bright = !bright; lcd.setBrightness(bright); lcd.clear(); } if (ActFlag) { ActFlag = 0; bright = !bright; lcd.setBrightness(bright); lcd.clear(); } if(StartFlag) { StartFlag = 0; MainMenu(); } } } void LevelScreen() { char buffer[14]; int write = sprintf(buffer, "Level %d", level); // print formatted data to buffer lcd.clear(); lcd.printString(buffer, 20, 2); lcd.refresh(); wait(1.0); } void GameLoop() { while (1) { level++; score = score + 100; World(); LevelScreen(); //RevealMap(); //Uncomment for debugging to view map srand(Noise * 1000000); PlayerCamera(); while (1) { ActFlag = 0; StartFlag = 0; if (map[px][py] == CHEST) { Chest(); } if (px == exx && py == exy) { if(level%5 == 0) { BossFight = true; Fight(); } break; } Sleep(); if (joystick.direction != Centre) { PlayerMove(); if (rand() % 40 == 0) { if (ph < PH_MAX) { ph++; } } if (rand() % 50 == 0) { Fight(); } PlayerCamera(); } if (StartFlag) { StartFlag = 0; StartMenu(); PlayerCamera(); } if (ActFlag) { ActFlag = 0; } } } } void PlayerCamera() { lcd.clear(); int tile; for (int i = 0; i < 14; i++) { for (int j = 0; j < 6; j++) { if (i == 6 && j == 2) { lcd.printString("@", (6 * i) + 1, j); } else { int diffx = i - 6; int diffy = j - 2; if (px + diffx < 84 && px + diffx > 0 && py + diffy < 48 && py + diffy > 0) { tile = map[px + diffx][py + diffy]; } else { tile = WALL; } lcd.printChar(TileList[tile].Symbol, (6 * i) + 1, j); if (map[px + diffx][py + diffy] == FLOOR) { map[px + diffx][py + diffy] = FLOOR_SEEN; } } } } lcd.refresh(); } void PlayerMove() { if (joystick.direction == Up) { int tile = map[px][py - 1]; if (TileList[tile].Passable) { py--; } } if (joystick.direction == Down) { int tile = map[px][py + 1]; if (TileList[tile].Passable) { py++; } } if (joystick.direction == Right) { int tile = map[px + 1][py]; if (TileList[tile].Passable) { px++; } } if (joystick.direction == Left) { int tile = map[px - 1][py]; if (TileList[tile].Passable) { px--; } } } void Fight() { int m; lcd.clear(); if(BossFight) { BossFight = false; m = 5; //Monster is a minotaur lcd.printString("BOSS!", 30, 2); } else { int mr = level + 1; if (mr > 5) { mr = 5; } lcd.printString("FIGHT!", 24, 2); m = rand() % mr; } int mh = EnemyList[m].EHealth; FlashScreen(5); char buffer1[14]; int write = sprintf(buffer1, "%d/%d", mh, EnemyList[m].EHealth); // print formatted data to buffer lcd.clear(); lcd.printString(EnemyList[m].EName, 0, 0); lcd.printString(buffer1, 54, 0); DrawGraphic(m, 23, 7); lcd.refresh(); wait(2.0); bool menu = 1; while (1) { ActFlag = 0; StartFlag = 0; lcd.clear(); lcd.printString(EnemyList[m].EName, 0, 0); write = sprintf(buffer1, "%d/%d", mh, EnemyList[m].EHealth); // print formatted data to buffer lcd.printString(buffer1, 54, 0); lcd.printString("You", 0, 2); char buffer2[14]; int phm = PH_MAX; write = sprintf(buffer2, "%d/%d", ph, phm); // print formatted data to buffer lcd.printString(buffer2, 54, 2); if (menu) { lcd.printString("Fight <", 0, 4); lcd.printString("Run", 0, 5); } else { lcd.printString("Fight", 0, 4); lcd.printString("Run <", 0, 5); } lcd.refresh(); Sleep(); if (joystick.direction != Centre) { menu = !menu; } if (ActFlag) { ActFlag = 0; if (menu) { //Fight //Hit monster if (rand() % 100 + 1 > EnemyList[m].EDodge) { //If monster doesn't dodge int damage = ItemList[pw].ItemValue - EnemyList[m].EArmour + rand() % 3 - rand() % 3; //Calculate damage if (damage < 0) { damage = 0; } mh = mh - damage; //Apply damage and calculate the monster's health char damBuffer[14]; write = sprintf(damBuffer,"-%d", damage); lcd.clear(); DrawGraphic(m, 23, 7); lcd.printString(damBuffer, 62, 2); FlashScreen(3); char buffer3[14]; write = sprintf(buffer3, "for %d damage", damage); // print formatted data to buffer lcd.clear(); lcd.printString("You hit the", 0, 1); lcd.printString(EnemyList[m].EName, 0, 2); lcd.printString(buffer3, 0, 3); lcd.refresh(); wait(1.0); Sleep(); } else { //Monster dodges lcd.clear(); lcd.printString(EnemyList[m].EName, 0, 1); lcd.printString("dodges your", 0, 2); lcd.printString("attack", 0, 3); lcd.refresh(); wait(1.0); Sleep(); } if (mh <= 0) { //Check if monster is dead score = score + EnemyList[m].EPoints; lcd.clear(); lcd.printString("You win!", 18, 2); lcd.refresh(); wait(1.0); Sleep(); break; } MonsterAttack(m); } else { //Run away score = score - 2; int b = rand() % 5; if (b == 0) { //Monster blocks the path lcd.clear(); lcd.printString("You try to run", 0, 0); lcd.printString("away but the", 0, 1); lcd.printString("monster blocks", 0, 2); lcd.printString("the path", 0, 3); lcd.refresh(); wait(1.0); Sleep(); MonsterAttack(m); } else { int s = rand() % 100 + 1; if (s > EnemyList[m].ESpd) { //If you outspeed monster lcd.clear(); lcd.printString("You run away", 6, 2); lcd.refresh(); wait(1.0); Sleep(); break; } else { lcd.clear(); lcd.printString("You try to run", 0, 0); lcd.printString("away but the", 0, 1); lcd.printString("monster", 0, 2); lcd.printString("catches up to", 0, 3); lcd.printString("you", 0, 4); lcd.refresh(); wait(1.0); Sleep(); MonsterAttack(m); } } } } } } void MonsterAttack(int m) { if (rand() % 100 + 1 < EnemyList[m].EHit) { //If monster hits and isn't dead int damage = EnemyList[m].EDamage - ItemList[pa].ItemValue + rand() % 3 - rand() % 3; //Calculate damage if (damage < 0) { damage = 0; } ph = ph - damage; //Apply damage and calculate the monster's health char buffer[14]; int write = sprintf(buffer, "%d damage", damage); // print formatted data to buffer lcd.clear(); lcd.printString(EnemyList[m].EName, 0, 1); lcd.printString("hits you for", 0, 2); lcd.printString(buffer, 0, 3); lcd.refresh(); wait(1.0); Sleep(); } else { //You dodge lcd.clear(); lcd.printString("You dodge the", 0, 1); lcd.printString("monster's", 0, 2); lcd.printString("attack", 0, 3); lcd.refresh(); wait(1.0); Sleep(); } if (ph <= 0) { //Check if player is dead GameOver(); } } void StartMenu() { int menu = 0; char buffer[14]; int phm = PH_MAX; int write = sprintf(buffer, "Health %d/%d", ph, phm); // print formatted data to buffer while (1) { if (menu == 0) { lcd.clear(); lcd.printString(buffer, 0, 0); lcd.printString("Map <", 0, 2); lcd.printString("Map Legend", 0, 3); lcd.printString("Inventory", 0, 4); lcd.printString("Continue", 0, 5); lcd.refresh(); Sleep(); } else if (menu == 1) { lcd.clear(); lcd.printString(buffer, 0, 0); lcd.printString("Map", 0, 2); lcd.printString("Map Legend <", 0, 3); lcd.printString("Inventory", 0, 4); lcd.printString("Continue", 0, 5); lcd.refresh(); Sleep(); } else if (menu == 2) { lcd.clear(); lcd.printString(buffer, 0, 0); lcd.printString("Map", 0, 2); lcd.printString("Map Legend", 0, 3); lcd.printString("Inventory <", 0, 4); lcd.printString("Continue", 0, 5); lcd.refresh(); Sleep(); } else if (menu == 3) { lcd.clear(); lcd.printString(buffer, 0, 0); lcd.printString("Map", 0, 2); lcd.printString("Map Legend", 0, 3); lcd.printString("Inventory", 0, 4); lcd.printString("Continue <", 0, 5); lcd.refresh(); Sleep(); } if (joystick.direction != Centre) { if ((joystick.direction == Down || joystick.direction == Right) && menu < 3) { menu++; } else if ((joystick.direction == Up || joystick.direction == Left) && menu > 0) menu--; } if (ActFlag) { ActFlag = 0; if (menu == 0) { Map(); } else if (menu == 1) { MapLegend(); } else if (menu == 2) { Inventory(); } else { break; } } if (StartFlag) { StartFlag = 0; } } } void Map() { lcd.clear(); DrawMap(); while (!StartFlag) { FlashPlayerLocation(); } StartFlag = 0; ActFlag = 0; } void DrawMap() { //Draw map on screen for (int i = 0; i<84; i++) { for (int j = 0; j<48; j++) { if (map[i][j] == FLOOR_SEEN || map[i][j] == CHEST_OPENED) { lcd.clearPixel(i, j); } else { lcd.setPixel(i, j); } } } lcd.refresh(); } void FlashPlayerLocation() { lcd.setPixel(px, py); lcd.refresh(); wait(0.5); lcd.clearPixel(px, py); lcd.refresh(); wait(0.5); } void MapLegend() { lcd.clear(); lcd.printString("@ Player", 0, 0); lcd.printString("# Wall", 0, 1); lcd.printString(". Floor", 0, 2); lcd.printString("= Chest", 0, 3); lcd.printString("/ Open Chest", 0, 4); while (1) { Sleep(); if (ActFlag) { ActFlag = 0; } if (StartFlag) { StartFlag = 0; break; } } } void Inventory() { lcd.clear(); lcd.printString("Armour:", 0, 0); lcd.printString(ItemList[pa].ItemName, 0, 1); char buffer1[14]; int write = sprintf(buffer1, "+%d Armour", ItemList[pa].ItemValue); // print formatted data to buffer lcd.printString(buffer1, 0, 2); lcd.printString("Weapon:", 0, 3); lcd.printString(ItemList[pw].ItemName, 0, 4); char buffer2[14]; write = sprintf(buffer2, "+%d Damage", ItemList[pw].ItemValue); // print formatted data to buffer lcd.printString(buffer2, 0, 5); lcd.refresh(); while (1) { Sleep(); if (ActFlag) { ActFlag = 0; } if (StartFlag) { StartFlag = 0; break; } } } void Chest() { score = score + 10; int c = rand() % 4; //0- Item, 1- Booby trap, 2- Map, Else- Potion if (c == 0) { getItem(); } else if (c == 1) { BoobyTrap(); } else if (c == 2) { RevealMap(); } else { Potion(); } map[px][py] = CHEST_OPENED; } void getItem() { int r = rand() % 10; lcd.clear(); lcd.printString("Do you want to", 0, 1); lcd.printString("take the", 0, 2); lcd.printString(ItemList[r].ItemName, 0, 3); lcd.printString("-Yes (Action)", 0, 4); lcd.printString("-No (Start)", 0, 5); lcd.refresh(); wait(1.0); while(1) { Sleep(); if (ActFlag) { ActFlag = 0; if (r > 5) { pa = r; } else { pw = r; } lcd.clear(); lcd.printString("You take the", 0, 1); lcd.printString(ItemList[r].ItemName, 0, 2); lcd.refresh(); wait(1.0); Sleep(); } if(StartFlag) { StartFlag = 0; lcd.clear(); lcd.printString("You leave the", 0, 1); lcd.printString(ItemList[r].ItemName, 0, 2); lcd.refresh(); wait(1.0); Sleep(); } } } void BoobyTrap() { int damage = rand() % 5; if (damage != 0) { ph = ph - damage; char buffer[15]; int write = sprintf(buffer, "You recive %d", damage); lcd.clear(); lcd.printString("The chest is", 0, 0); lcd.printString("booby trapped!", 0, 1); lcd.printString(buffer, 0, 3); lcd.printString("damage", 0, 4); lcd.refresh(); wait(1.0); Sleep(); //Check if player is dead if (ph < 0) { GameOver(); } } else { lcd.clear(); lcd.printString("The chest is", 0, 0); lcd.printString("booby trapped", 0, 1); lcd.printString("but the trap", 0, 2); lcd.printString("fails", 0, 3); lcd.refresh(); wait(1.0); Sleep(); } } void RevealMap() { for (int i = 0; i < 84; i++) { for (int j = 0; j < 48; j++) { if (map[i][j] == FLOOR) { map[i][j] = FLOOR_SEEN; } } } lcd.clear(); lcd.printString("You find a map", 0, 0); lcd.printString("of the current", 0, 1); lcd.printString("level inside", 0, 2); lcd.printString("the chest", 0, 3); lcd.refresh(); wait(1.0); Sleep(); } void Potion() { int p = rand() % 5; //0- Poison, 1- Teleport, Else- Full heal lcd.clear(); lcd.printString("You find a", 0, 0); lcd.printString("potion inside", 0, 1); lcd.printString("the chest", 0, 2); lcd.printString("Drink (Action)", 0, 4); lcd.printString("Leave (Start)", 0, 5); lcd.refresh(); wait(1.0); Sleep(); if (ActFlag) { //Potion drunk ActFlag = 0; if (p == 0) { //Poison int damage = rand() % 4 + 1; ph = ph - damage; char buffer[15]; int write = sprintf(buffer, "%d damage", damage); lcd.clear(); lcd.printString("You drink the", 0, 0); lcd.printString("potion and", 0, 1); lcd.printString("suddenly feel", 0, 2); lcd.printString("ill.", 0, 3); lcd.printString("You take", 0, 4); lcd.printString(buffer, 0, 5); lcd.refresh(); wait(1.0); Sleep(); //Check if player is dead if (ph < 0) { GameOver(); } } else if (p == 1) { //Teleport lcd.clear(); lcd.printString("You drink the", 0, 0); lcd.printString("potion and", 0, 1); lcd.printString("suddenly feel", 0, 2); lcd.printString("your body", 0, 3); lcd.printString("being", 0, 4); lcd.printString("transported", 0, 5); lcd.refresh(); wait(1.0); Sleep(); GameLoop(); } else { //Full heal ph = PH_MAX; lcd.clear(); lcd.printString("You drink the", 0, 0); lcd.printString("potion and", 0, 1); lcd.printString("suddenly feel", 0, 2); lcd.printString("all your", 0, 3); lcd.printString("wounds heal", 0, 4); lcd.refresh(); wait(1.0); Sleep(); } } if(StartFlag) { //Leave the potion StartFlag = 0; lcd.clear(); lcd.printString("You walk away", 0, 0); lcd.printString("and leave the", 0, 1); lcd.printString("potion", 0, 2); lcd.refresh(); wait(1.0); Sleep(); } } void GameOver() { lcd.inverseMode(); lcd.clear(); lcd.printString("GAME OVER", 12, 2); lcd.refresh(); wait(1.0); Sleep(); lcd.normalMode(); ScoreScreen(); } void ScoreScreen() { char buffer[14]; int write = sprintf(buffer, "%d points", score); lcd.clear(); lcd.printString("You scored", 6, 1); lcd.printString(buffer, 6, 2); lcd.refresh(); wait(1.0); Sleep(); HighScoreScreen(); } void HighScoreScreen() { HighScoreCheck(); //readDataFromFile(); char buffer1[14]; int write = sprintf(buffer1, "1. %d", HScore1); char buffer2[14]; write = sprintf(buffer2, "2. %d", HScore2); char buffer3[14]; write = sprintf(buffer3, "3. %d", HScore3); char buffer4[14]; write = sprintf(buffer4, "4. %d", HScore4); lcd.clear(); lcd.printString("High Scores", 6, 0); lcd.printString(buffer1, 6, 2); lcd.printString(buffer2, 6, 3); lcd.printString(buffer3, 6, 4); lcd.printString(buffer4, 6, 5); lcd.refresh(); wait(1.0); while(1) { Sleep(); if(StartFlag) { StartFlag = 0; MainMenu(); } if(ActFlag) { ActFlag = 0; } } } int main() { calibrateJoystick(); // get centred values of joystick pollJoystick.attach(&updateJoystick,1.0/10.0); // read joystick 10 times per second //Power Saving PHY_PowerDown(); int result = semihost_powerdown(); Start.mode(PullDown); Act.mode(PullDown); Start.fall(&StartPressed); Act.fall(&ActPressed); Start.mode(PullDown); Act.mode(PullDown); //Generate random seed srand(Noise * 1000000); //Initilize screen lcd.init(); Intro(); MainMenu(); }