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.
main.cpp@12:b3ec47d606a5, 2019-05-09 (annotated)
- Committer:
- kocemax
- Date:
- Thu May 09 11:41:58 2019 +0000
- Revision:
- 12:b3ec47d606a5
- Parent:
- 10:da5743dfb137
Had to fix more of the comments, to improve the documentation.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
kocemax | 0:2f0362fef062 | 1 | /* |
kocemax | 0:2f0362fef062 | 2 | ELEC2645 Embedded Systems Project |
kocemax | 0:2f0362fef062 | 3 | School of Electronic & Electrical Engineering University of Leeds |
kocemax | 0:2f0362fef062 | 4 | Name: Kostadin Chakarov |
kocemax | 0:2f0362fef062 | 5 | Username: el17kec |
kocemax | 0:2f0362fef062 | 6 | Student ID Number:201171978 Date:11/03/2019 |
kocemax | 0:2f0362fef062 | 7 | */ |
kocemax | 7:cd3cafda3dd4 | 8 | |
kocemax | 12:b3ec47d606a5 | 9 | // Breakout logo sprite |
kocemax | 1:b82c4c2de9a8 | 10 | const int breakout[10][75] = { |
kocemax | 1:b82c4c2de9a8 | 11 | { 1,0,0,1,1,0,0,0,0,0,1,0,0,1,1,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,1,1,1,1,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,1,0,0,0,0 }, |
kocemax | 1:b82c4c2de9a8 | 12 | { 1,0,1,0,0,1,0,0,1,0,1,0,1,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,1,0,0,1,1,1,0,0,1,0,1,1,1,1,1,1,1,1,1 }, |
kocemax | 1:b82c4c2de9a8 | 13 | { 1,1,0,0,0,0,1,0,0,1,1,1,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,1,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,1,0,0,1,1,1,0,0,1,0,0,0,0,0,1,0,0,0,0 }, |
kocemax | 1:b82c4c2de9a8 | 14 | { 1,1,0,1,1,1,1,0,0,0,1,1,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,1,0,0,0,0 }, |
kocemax | 1:b82c4c2de9a8 | 15 | { 1,0,1,0,0,1,1,0,0,0,1,1,1,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,1,0,0,1,0,0,1,0,0,1,0 }, |
kocemax | 1:b82c4c2de9a8 | 16 | { 1,1,0,1,1,0,0,1,0,0,1,0,1,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,1,0,1,1,1,0,1,0,1,1,1 }, |
kocemax | 1:b82c4c2de9a8 | 17 | { 1,1,0,0,0,0,0,1,0,0,1,0,0,1,0,0,0,0,1,1,1,1,1,1,1,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,1,0,0,1,0,0,1,0,0,1,0 }, |
kocemax | 1:b82c4c2de9a8 | 18 | { 1,1,0,0,0,0,0,1,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,1,1,1,0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,1,1,1,1,1,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0 }, |
kocemax | 1:b82c4c2de9a8 | 19 | { 1,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,1,0,0,1,1,1,0,0,1,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0 }, |
kocemax | 1:b82c4c2de9a8 | 20 | { 1,0,0,1,1,1,0,0,0,0,1,0,0,0,0,0,1,0,1,1,1,1,1,1,1,1,0,1,0,0,0,1,0,0,0,1,0,1,0,0,0,0,0,0,1,0,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0 }, |
kocemax | 1:b82c4c2de9a8 | 21 | }; |
kocemax | 0:2f0362fef062 | 22 | |
kocemax | 1:b82c4c2de9a8 | 23 | ///////// pre-processor directives //////// |
kocemax | 0:2f0362fef062 | 24 | #include "mbed.h" |
kocemax | 1:b82c4c2de9a8 | 25 | #include "N5110.h" |
kocemax | 1:b82c4c2de9a8 | 26 | #include "Gamepad.h" |
kocemax | 8:9b77eea95088 | 27 | #include "Paddle.h" |
kocemax | 6:39bda45efeed | 28 | #include "Ball.h" |
kocemax | 6:39bda45efeed | 29 | #include "Map.h" |
kocemax | 1:b82c4c2de9a8 | 30 | |
kocemax | 10:da5743dfb137 | 31 | #define WITH_TESTING |
kocemax | 10:da5743dfb137 | 32 | #ifdef WITH_TESTING |
kocemax | 10:da5743dfb137 | 33 | #include "tests.h" |
kocemax | 10:da5743dfb137 | 34 | #endif |
kocemax | 10:da5743dfb137 | 35 | |
kocemax | 12:b3ec47d606a5 | 36 | const int fps = 20; // Sets the fps of the game, doesn't change |
kocemax | 4:0e01cbb95434 | 37 | |
kocemax | 1:b82c4c2de9a8 | 38 | /////////////// objects /////////////// |
kocemax | 12:b3ec47d606a5 | 39 | AnalogIn pot(PTB2); // Potentiometer to set contrast of screen |
kocemax | 12:b3ec47d606a5 | 40 | N5110 lcd(PTC9,PTC0,PTC7,PTD2,PTD1,PTC11); // K64F - pwr from 3V3 |
kocemax | 12:b3ec47d606a5 | 41 | Gamepad pad; // Gamepad buttons |
kocemax | 12:b3ec47d606a5 | 42 | Paddle paddle; // Paddle object |
kocemax | 12:b3ec47d606a5 | 43 | Ball ball; // Ball object |
kocemax | 12:b3ec47d606a5 | 44 | Map map; // Map object |
kocemax | 1:b82c4c2de9a8 | 45 | |
kocemax | 1:b82c4c2de9a8 | 46 | ///////////// function prototypes /////////////// |
kocemax | 12:b3ec47d606a5 | 47 | void init(); // Initialize LCD and Gamepad |
kocemax | 12:b3ec47d606a5 | 48 | void welcome(); // Simple welcome screen displayed on start-up |
kocemax | 12:b3ec47d606a5 | 49 | void render(); // Used as the game loop |
kocemax | 12:b3ec47d606a5 | 50 | void contrast(); // Allows to set contrast, if not suitable |
kocemax | 0:2f0362fef062 | 51 | |
kocemax | 1:b82c4c2de9a8 | 52 | ///////////// functions //////////////// |
kocemax | 1:b82c4c2de9a8 | 53 | int main() |
kocemax | 10:da5743dfb137 | 54 | { |
kocemax | 10:da5743dfb137 | 55 | #ifdef WITH_TESTING |
kocemax | 10:da5743dfb137 | 56 | int number_of_failures = run_tests(); |
kocemax | 10:da5743dfb137 | 57 | if(number_of_failures > 0) return number_of_failures; |
kocemax | 10:da5743dfb137 | 58 | #endif |
kocemax | 10:da5743dfb137 | 59 | |
kocemax | 12:b3ec47d606a5 | 60 | init(); // Initialize LCD and Gamepad |
kocemax | 12:b3ec47d606a5 | 61 | welcome(); // Waiting for the user to start |
kocemax | 12:b3ec47d606a5 | 62 | render(); // Game Loop |
kocemax | 1:b82c4c2de9a8 | 63 | } |
kocemax | 1:b82c4c2de9a8 | 64 | |
kocemax | 8:9b77eea95088 | 65 | |
kocemax | 1:b82c4c2de9a8 | 66 | void init() |
kocemax | 1:b82c4c2de9a8 | 67 | { |
kocemax | 12:b3ec47d606a5 | 68 | lcd.init(); // Initialize the LCD |
kocemax | 12:b3ec47d606a5 | 69 | pad.init(); // Initialize the Gamepad |
kocemax | 12:b3ec47d606a5 | 70 | lcd.setContrast(0.55); // Initially set contrast to 55% |
kocemax | 12:b3ec47d606a5 | 71 | lcd.normalMode(); // Normal color mode |
kocemax | 12:b3ec47d606a5 | 72 | lcd.setBrightness(0.5); // Puts LED backlight on 50% |
kocemax | 1:b82c4c2de9a8 | 73 | } |
kocemax | 1:b82c4c2de9a8 | 74 | |
kocemax | 8:9b77eea95088 | 75 | /** Simple welcome screen displayed on start-up */ |
kocemax | 1:b82c4c2de9a8 | 76 | void welcome() |
kocemax | 0:2f0362fef062 | 77 | { |
kocemax | 1:b82c4c2de9a8 | 78 | lcd.printString("Welcome to",12,0); |
kocemax | 8:9b77eea95088 | 79 | lcd.drawSprite(5,15,10,75,(int *)breakout); // x origin, y origin, rows, cols, sprite |
kocemax | 8:9b77eea95088 | 80 | lcd.printString("Press A ",2,4); |
kocemax | 8:9b77eea95088 | 81 | lcd.printString("for Controls ",11,5); |
kocemax | 1:b82c4c2de9a8 | 82 | lcd.refresh(); |
kocemax | 1:b82c4c2de9a8 | 83 | |
kocemax | 12:b3ec47d606a5 | 84 | // Wait to move to next menu |
kocemax | 8:9b77eea95088 | 85 | while (pad.check_event(Gamepad::A_PRESSED) == false) |
kocemax | 8:9b77eea95088 | 86 | { |
kocemax | 8:9b77eea95088 | 87 | |
kocemax | 8:9b77eea95088 | 88 | } |
kocemax | 8:9b77eea95088 | 89 | lcd.clear(); |
kocemax | 8:9b77eea95088 | 90 | lcd.printString("Use pot to ->",4,0); |
kocemax | 8:9b77eea95088 | 91 | lcd.printString("set contrast",4,1); |
kocemax | 8:9b77eea95088 | 92 | lcd.printString("Use Joystick ",6,2); |
kocemax | 8:9b77eea95088 | 93 | lcd.printString("to move paddle ",0,3); |
kocemax | 8:9b77eea95088 | 94 | lcd.printString("Press Start ",9,4); |
kocemax | 8:9b77eea95088 | 95 | lcd.printString("to begin ",16,5); |
kocemax | 8:9b77eea95088 | 96 | lcd.refresh(); |
kocemax | 12:b3ec47d606a5 | 97 | // Flash LEDs until start button is pressed |
kocemax | 1:b82c4c2de9a8 | 98 | while (pad.check_event(Gamepad::START_PRESSED) == false) |
kocemax | 1:b82c4c2de9a8 | 99 | { |
kocemax | 1:b82c4c2de9a8 | 100 | for (int i = 1; i < 7; i++) |
kocemax | 1:b82c4c2de9a8 | 101 | { |
kocemax | 5:12c179da4788 | 102 | pad.led(i,1); |
kocemax | 5:12c179da4788 | 103 | wait(0.1); |
kocemax | 5:12c179da4788 | 104 | pad.led(i,0); |
kocemax | 8:9b77eea95088 | 105 | } |
kocemax | 1:b82c4c2de9a8 | 106 | } |
kocemax | 1:b82c4c2de9a8 | 107 | } |
kocemax | 0:2f0362fef062 | 108 | |
kocemax | 8:9b77eea95088 | 109 | /** Resets everything if game is won / lost */ |
kocemax | 7:cd3cafda3dd4 | 110 | void resetGame() |
kocemax | 7:cd3cafda3dd4 | 111 | { |
kocemax | 12:b3ec47d606a5 | 112 | paddle.reset(); // Reset paddle |
kocemax | 12:b3ec47d606a5 | 113 | ball.reset(); // Reset ball |
kocemax | 12:b3ec47d606a5 | 114 | map.reset(); // Reset map |
kocemax | 12:b3ec47d606a5 | 115 | map.score = 0; // Reset score |
kocemax | 7:cd3cafda3dd4 | 116 | } |
kocemax | 7:cd3cafda3dd4 | 117 | |
kocemax | 8:9b77eea95088 | 118 | /** Checks if game is lost */ |
kocemax | 7:cd3cafda3dd4 | 119 | void checkLost() |
kocemax | 7:cd3cafda3dd4 | 120 | { |
kocemax | 8:9b77eea95088 | 121 | const Vector2D& posPad = paddle.getPos(); |
kocemax | 12:b3ec47d606a5 | 122 | // Checks if ball is below paddle, i.e. lost |
kocemax | 7:cd3cafda3dd4 | 123 | if (ball.getPos().y > posPad.y) |
kocemax | 7:cd3cafda3dd4 | 124 | { |
kocemax | 7:cd3cafda3dd4 | 125 | while (1) |
kocemax | 7:cd3cafda3dd4 | 126 | { |
kocemax | 12:b3ec47d606a5 | 127 | // Prints a simple 'lost' message and score and asks if you want to restart |
kocemax | 7:cd3cafda3dd4 | 128 | lcd.clear(); |
kocemax | 9:f720f5d87420 | 129 | char finalscore[14]; |
kocemax | 9:f720f5d87420 | 130 | sprintf(finalscore,"Score = %d",map.score); |
kocemax | 9:f720f5d87420 | 131 | lcd.printString(finalscore,0,0); |
kocemax | 7:cd3cafda3dd4 | 132 | lcd.printString("You Lost",17,2); |
kocemax | 7:cd3cafda3dd4 | 133 | lcd.printString("Press A",20,3); |
kocemax | 7:cd3cafda3dd4 | 134 | lcd.printString("to restart",12,4); |
kocemax | 7:cd3cafda3dd4 | 135 | wait(0.1); |
kocemax | 7:cd3cafda3dd4 | 136 | lcd.refresh(); |
kocemax | 12:b3ec47d606a5 | 137 | // Checks if reset button is pressed, if it is reset |
kocemax | 7:cd3cafda3dd4 | 138 | if (pad.check_event(Gamepad::A_PRESSED) == true) |
kocemax | 7:cd3cafda3dd4 | 139 | { |
kocemax | 7:cd3cafda3dd4 | 140 | resetGame(); |
kocemax | 7:cd3cafda3dd4 | 141 | break; |
kocemax | 7:cd3cafda3dd4 | 142 | } |
kocemax | 7:cd3cafda3dd4 | 143 | } |
kocemax | 7:cd3cafda3dd4 | 144 | } |
kocemax | 7:cd3cafda3dd4 | 145 | } |
kocemax | 7:cd3cafda3dd4 | 146 | |
kocemax | 8:9b77eea95088 | 147 | /** Checks if level / game is won */ |
kocemax | 8:9b77eea95088 | 148 | void checkWon() |
kocemax | 8:9b77eea95088 | 149 | { |
kocemax | 7:cd3cafda3dd4 | 150 | if (map.checkLevel()) { |
kocemax | 12:b3ec47d606a5 | 151 | // We have cleared a level |
kocemax | 12:b3ec47d606a5 | 152 | ball.reset(); // Reset ball |
kocemax | 12:b3ec47d606a5 | 153 | paddle.reset(); // Reset paddle |
kocemax | 7:cd3cafda3dd4 | 154 | |
kocemax | 7:cd3cafda3dd4 | 155 | if (map.hasWon()) { |
kocemax | 12:b3ec47d606a5 | 156 | // We have cleared all levels |
kocemax | 7:cd3cafda3dd4 | 157 | while (1) |
kocemax | 8:9b77eea95088 | 158 | { |
kocemax | 12:b3ec47d606a5 | 159 | // Prints win message and score and asks if you want to restart |
kocemax | 7:cd3cafda3dd4 | 160 | lcd.clear(); |
kocemax | 9:f720f5d87420 | 161 | char finalscore[14]; |
kocemax | 9:f720f5d87420 | 162 | sprintf(finalscore,"Score = %d",map.score); |
kocemax | 9:f720f5d87420 | 163 | lcd.printString(finalscore,0,0); |
kocemax | 7:cd3cafda3dd4 | 164 | lcd.printString("You WON!",17,2); |
kocemax | 10:da5743dfb137 | 165 | lcd.printString("Press B",20,3); |
kocemax | 7:cd3cafda3dd4 | 166 | lcd.printString("to restart",12,4); |
kocemax | 7:cd3cafda3dd4 | 167 | wait(0.1); |
kocemax | 7:cd3cafda3dd4 | 168 | lcd.refresh(); |
kocemax | 12:b3ec47d606a5 | 169 | // Checks if reset button is pressed, if it is reset |
kocemax | 10:da5743dfb137 | 170 | if (pad.check_event(Gamepad::B_PRESSED) == true) |
kocemax | 7:cd3cafda3dd4 | 171 | { |
kocemax | 7:cd3cafda3dd4 | 172 | resetGame(); |
kocemax | 7:cd3cafda3dd4 | 173 | break; |
kocemax | 7:cd3cafda3dd4 | 174 | } |
kocemax | 7:cd3cafda3dd4 | 175 | } |
kocemax | 7:cd3cafda3dd4 | 176 | } |
kocemax | 7:cd3cafda3dd4 | 177 | } |
kocemax | 7:cd3cafda3dd4 | 178 | } |
kocemax | 7:cd3cafda3dd4 | 179 | |
kocemax | 8:9b77eea95088 | 180 | /** Game loop */ |
kocemax | 6:39bda45efeed | 181 | void render() |
kocemax | 6:39bda45efeed | 182 | { |
kocemax | 8:9b77eea95088 | 183 | |
kocemax | 8:9b77eea95088 | 184 | |
kocemax | 12:b3ec47d606a5 | 185 | map.initBricks(); // Initialize the map |
kocemax | 6:39bda45efeed | 186 | |
kocemax | 4:0e01cbb95434 | 187 | while(1) |
kocemax | 8:9b77eea95088 | 188 | { |
kocemax | 8:9b77eea95088 | 189 | |
kocemax | 12:b3ec47d606a5 | 190 | // Physics, movement, control input + game logic |
kocemax | 12:b3ec47d606a5 | 191 | // Control Input |
kocemax | 8:9b77eea95088 | 192 | paddle.controlPaddle(pad); |
kocemax | 8:9b77eea95088 | 193 | |
kocemax | 12:b3ec47d606a5 | 194 | // Movement and physics |
kocemax | 6:39bda45efeed | 195 | ball.move(); |
kocemax | 8:9b77eea95088 | 196 | paddle.move(); |
kocemax | 8:9b77eea95088 | 197 | |
kocemax | 8:9b77eea95088 | 198 | map.checkCollision(ball, paddle); |
kocemax | 8:9b77eea95088 | 199 | map.update(); |
kocemax | 8:9b77eea95088 | 200 | ball.hitPad(paddle); |
kocemax | 8:9b77eea95088 | 201 | |
kocemax | 12:b3ec47d606a5 | 202 | // Rendering |
kocemax | 12:b3ec47d606a5 | 203 | lcd.clear(); // Initialize render |
kocemax | 12:b3ec47d606a5 | 204 | contrast(); // Sets contrast |
kocemax | 12:b3ec47d606a5 | 205 | map.drawMap(lcd); // Draw map objects |
kocemax | 12:b3ec47d606a5 | 206 | paddle.draw(lcd); // Draws paddle |
kocemax | 12:b3ec47d606a5 | 207 | ball.draw(lcd); // Draws ball |
kocemax | 8:9b77eea95088 | 208 | |
kocemax | 12:b3ec47d606a5 | 209 | lcd.refresh(); // Finalize render |
kocemax | 8:9b77eea95088 | 210 | |
kocemax | 12:b3ec47d606a5 | 211 | wait(1.0f/fps); // Frames per second |
kocemax | 8:9b77eea95088 | 212 | |
kocemax | 12:b3ec47d606a5 | 213 | // Check Lost/Won |
kocemax | 7:cd3cafda3dd4 | 214 | checkLost(); |
kocemax | 7:cd3cafda3dd4 | 215 | checkWon(); |
kocemax | 4:0e01cbb95434 | 216 | } |
kocemax | 8:9b77eea95088 | 217 | } |
kocemax | 8:9b77eea95088 | 218 | |
kocemax | 8:9b77eea95088 | 219 | /** Allows to set contrast, if not suitable */ |
kocemax | 8:9b77eea95088 | 220 | void contrast() |
kocemax | 8:9b77eea95088 | 221 | { |
kocemax | 12:b3ec47d606a5 | 222 | float contrast = pot.read(); // Read value from potentiometer(0-1) |
kocemax | 12:b3ec47d606a5 | 223 | lcd.setContrast(contrast); // Set that value for the contrast |
kocemax | 8:9b77eea95088 | 224 | } |
kocemax | 8:9b77eea95088 | 225 |