Christopher Doel
/
el17cd
Cube Dodger A 3D 'endless runner' game
Game/Game.cpp
- Committer:
- el17cd
- Date:
- 2019-05-08
- Revision:
- 46:824ec81ff578
- Parent:
- 39:41dcf1604fdf
File content as of revision 46:824ec81ff578:
#include "Game.h" SDFileSystem sd(PTE3, PTE1, PTE2, PTE4, "sd"); // MOSI, MISO, SCK, CS Serial pc(USBTX, USBRX); // tx, rx Game::Game(){ noOfCubes = 25; //How many cubes are in the scene menuSelections.homeMenuSelection = 0; //default selection for the home screen gamepad.init(); renderer.init(); resetScene(); helpScreenNumber = -1; //Set help screen to inactive (-1) input.x = 0; //Set joystick input to 0 input.bCooldown = input.yCooldown = input.aCooldown = false; //Allow buttons to be pressed menuSelections.deathMenuSelection = 0; //Set death menu to highlight restart option highScore = readHighScore(); } void Game::resetScene(){ for(int i = 0; i < noOfCubes; i++){ //Set initial position of all cubes cubeArray[i].translate(rand()%250-125, 0, 10 + i*5); //Position will be based on random integers } } int Game::readHighScore(){ int highScore = 0; filePointer = fopen("/sd/el17cdHighScore.txt", "r"); if (filePointer != NULL) { fscanf(filePointer, "%d", &highScore); //read integer from sd card file fclose(filePointer); } return highScore;; } void Game::writeHighScore(int score){ filePointer = fopen("/sd/el17cdHighScore.txt", "w"); if (filePointer != NULL) { fprintf(filePointer, "%d", score); //write integer to sd card file fclose(filePointer); } } void Game::run(){ inHomeMenu = true; //Start at home screen score = 0; playing = true; //set game state to playing and death screen selection to 'restart' while(true) { processInput(); //process user input and store values in input struct renderer.clear(); if(helpScreenNumber > -1){ helpScreen(); //Show the help screen if the help screen number is above -1 } else if(inHomeMenu){ homeScreen(); } else{ play(); } renderer.refresh(); //refresh lcd } } void Game::play(){ renderer.drawHorizon(input.x/15); //draw the horizon line for (int c = 0; c< noOfCubes; c++){ moveCubes(&cubeArray[c]); //translate cubes depending on joystick location and score cubeToBeRendered(&cubeArray[c], c); //add all cube faces to array to later be rendered checkDespawn(&cubeArray[c]); //check if any cubes are behind the perspective, then respawn them checkDeath(&cubeArray[c]); //check if any cubes are too close to user } renderer.drawAllFaces(faceArray, noOfCubes, input.x); //draw all faces added to the face array displayDeathMenu(); //display death menu if cube is too close to user addScore(); renderer.printScore(score, 0, 0); //print score on top left of screen } void Game::checkDespawn(Cube *cube){ //checks if the cube is behind the perspective if (cube->despawn()){ cube->resetPos(); //reset position to origin cube->translate(rand()%250-125,0,140); //translate cube to new far away position } } void Game::checkDeath(Cube *cube){ //Check whether the user has hit a cube if (cube->tooClose()){ playing = false; //set state of game to not playing cube->resetPos(); cube->translate(rand()%250-125,0,140); //reset and translate cube to back position } } void Game::cubeToBeRendered(Cube *cube, int cubeIndex){ //Adds all faces within the cube to an array of faces to be rendered for (int i = 0; i < 6; i++){ faceArray[cubeIndex*6 + i] = cube->getFace(i); } } void Game::moveCubes(Cube *cube){ //animate cubes if(playing){ if(score < 6000) cube->translate(-input.x*1.4f,0,-1-(float)score/1000); //move cubes closer to user and in x axis depending on joystick pos else{ cube->translate(-input.x*1.4f,0,-3); //once max speed reached maintain constant z speed } } else{ input.x = 0; //if not playing (dead) prevent joystick moving anything } } void Game::displayDeathMenu() { //display restart or back to home menu if(!playing){ if(score > highScore) { highScore = score; writeHighScore(highScore); } renderer.drawDeathScreen(menuSelections.deathMenuSelection, highScore); //draw death screen if game over deathButtonSelections(); //select menu option } } void Game::addScore(){ //increment score by 1 each frame if(playing){ score++; //add score if still playing } } void Game::resetScore(){ //reset score to 0 score = 0; } void Game::deathButtonSelections(){ //determine selection on death screen if(input.yButton){ //if y pressed highlight top option (restart) menuSelections.deathMenuSelection = 0; } else if(input.aButton){ //if a pressed highlight bottom option (home menu) menuSelections.deathMenuSelection = 1; } if (menuSelections.deathMenuSelection == 0 && input.bButton){ //if top option highlighted and b pressed then restart game playing = true; score = 0; resetScore(); resetScene(); } else if(menuSelections.deathMenuSelection == 1 && input.bButton){ //if bottom option highlighted and b pressed then go to home screen resetScore(); inHomeMenu = true; } } void Game::homeButtonSelections(){ //determine selection on home screen if(input.yButton && menuSelections.homeMenuSelection > 0){ //if top option isnt highlighted and y pressed then move highlight up menuSelections.homeMenuSelection--; } else if(input.aButton && menuSelections.homeMenuSelection < 2){ //if bottom option isnt highlighted and a pressed then move highlight down menuSelections.homeMenuSelection++; } if (input.bButton && menuSelections.homeMenuSelection == 0){ //if top highlighted and b pressed then start game inHomeMenu = false; playing = true; } else if(input.bButton && menuSelections.homeMenuSelection == 1){ //if bottom highlighted and b pressed then exit game helpScreenNumber = 1; } else if(input.bButton && menuSelections.homeMenuSelection == 2){ //if bottom highlighted and b pressed then exit game renderer.turnOff(); exit(0); } } void Game::homeScreen(){//draw home screen homeButtonSelections(); //determine selection on home screen renderer.drawHomeScreen(menuSelections.homeMenuSelection); } void Game::helpScreen(){ //Show help screen depending on help screen number if (helpScreenNumber == 1) { renderer.drawHelpScreen1(); checkNextHelpScreen(); } else if (helpScreenNumber == 2) { renderer.drawHelpScreen2(); checkNextHelpScreen(); } else if (helpScreenNumber == 3) { renderer.drawHelpScreen3(); checkNextHelpScreen(); } else if (helpScreenNumber == 4) { renderer.drawHelpScreen4(); checkNextHelpScreen(); } else if (helpScreenNumber == 5) { //if past last screen then set help screen number to disabled (-1) helpScreenNumber = -1; } } void Game::checkNextHelpScreen(){ //if a button pressed then advance help screen if(input.bButton){ helpScreenNumber ++; } } void Game::processInput(){ //Obtain user inputs and store in input struct renderer.setContrast(gamepad.read_pot()); //Set the contrast of the screen based on the pot input.x = gamepad.get_coord().x; //Get value of joystick x axis bool y = gamepad.check_event(Gamepad::Y_PRESSED); //Get Y, A, B button states bool a = gamepad.check_event(Gamepad::A_PRESSED); bool b = gamepad.check_event(Gamepad::B_PRESSED); disableYButton(y); disableAButton(a); disableBButton(b); } void Game::disableYButton(bool y){ //Set y button to disabled, call function to reenable in 0.2 seconds if(!input.yCooldown && y){ input.yCooldown = true; disableY.attach(callback(this, &Game::enableY), 0.2); //attach function to ticker to renable y button input.yButton = true; } else{ input.yButton = false; } } void Game::disableAButton(bool a){ //Set a button to disabled, call function to reenable in 0.2 seconds if(!input.aCooldown && a){ input.aCooldown = true; disableA.attach(callback(this, &Game::enableA), 0.2); //attach function to ticker to renable a button input.aButton = true; } else{ input.aButton = false; } } void Game::disableBButton(bool b){ //Set b button to disabled, call function to reenable in 0.2 seconds if(!input.bCooldown && b){ input.bCooldown = true; disableB.attach(callback(this, &Game::enableB), 0.2); //attach function to ticker to renable b button input.bButton = true; } else{ input.bButton = false; } } void Game::enableY(){ //reenable y button disableY.detach(); //detach ticker so function only runs once input.yCooldown = false; } void Game::enableA(){ //reenable a button disableA.detach(); //detach ticker so function only runs once input.aCooldown = false; } void Game::enableB(){ //reenable b button disableB.detach(); //detach ticker so function only runs once input.bCooldown = false; }