A simple one-level platform game. Developed as part of ELEC2645 at University of Leeds, spring 2015.

Dependencies:   N5110 PinDetect PowerControl mbed

An ARM mbed LPC1768 microcontroller have been used to develop a handheld arcade game in the style of an old-school platformer. This project is entirely my own independent work in all stages of the development; including design, defining project specifications, breadboard prototyping, schematic and PCB layout using CAD, assembly, testing and software development. Due to this being part of the ELEC2645 Embedded Systems Project module at University of Leeds, spring 2015, limitations were given on the available hardware components. Credit is due to the authors of the dependent libraries (N5110, Pin Detect, PowerControl and mbed). I would also like to thank the author of Game Programming Patterns as well as the authors of SFML Game Development for providing me with useful sources for programming design patterns.

/media/uploads/Siriagus/game_assembled.jpg

Project aims

  • Implement simple gameplay:
    • A single, fixed (no scrolling) level.
    • Player can move left to right, jump and shoot.
    • Enemies will drop from the top of the screen.
    • The player gets points for shooting enemies.
    • The player dies when it gets hits by an enemy.
  • Implement a simple menu system.
  • Enable the user to adjust the brightness of the display.
  • Output sound to enhance the user experience.

Software

The program flow is controlled by a finite state machine. The implemented design was inspired by the State design pattern from the books Game Programming Patterns and SFML Game Development. The StateManager class is responsible for updating and rendering the current selected state. It also changes the state based on request from the current state. The framework built for the state machine used in this project makes it easy to add new screens. The different main states (indicated by the background colour) and how the user interaction is shown below: /media/uploads/Siriagus/arcadegameuserinteraction.png

Hardware

Schematic:

/media/uploads/Siriagus/schematic.png

Printed circuit board (PCB):

/media/uploads/Siriagus/pcb.png

Images

A seperate program was written to convert images (png) to text-representation of the maps. Enemies and numbers on the screen are also collected from a sprite-sheet created in the same manner.

/media/uploads/Siriagus/unileeds3.png /media/uploads/Siriagus/newmap2.png

Committer:
Siriagus
Date:
Fri May 08 14:39:36 2015 +0000
Revision:
10:f2488a0ecab7
Parent:
8:9ac6a428fa26
Child:
13:7ab71c7c311b
Encapsluated PinDetect buttons in InputManager (made private)

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Siriagus 0:1f92de30d43e 1 /**
Siriagus 10:f2488a0ecab7 2 * @file main.cpp
Siriagus 10:f2488a0ecab7 3 * @brief Simple platform game developed for ELEC2645 Embedded Systems Project at University of Leeds
Siriagus 10:f2488a0ecab7 4 * @author Andreas Garmannslund
Siriagus 10:f2488a0ecab7 5 */
Siriagus 0:1f92de30d43e 6
Siriagus 0:1f92de30d43e 7 #include "mbed.h"
Siriagus 0:1f92de30d43e 8 #include "N5110.h"
Siriagus 1:0cfe2255092a 9 #include "PowerControl.h"
Siriagus 1:0cfe2255092a 10 #include "PinDetect.h"
Siriagus 4:d6661b976359 11 #include <string>
Siriagus 7:678873947b29 12 #include <sstream>
Siriagus 4:d6661b976359 13 #include <ctime>
Siriagus 1:0cfe2255092a 14
Siriagus 0:1f92de30d43e 15 #include "Joystick.h"
Siriagus 1:0cfe2255092a 16
Siriagus 5:100d960fc6d5 17 #include "StateManager.h"
Siriagus 1:0cfe2255092a 18 #include "State.h"
Siriagus 1:0cfe2255092a 19 #include "images.h"
Siriagus 4:d6661b976359 20 #include "InputManager.h"
Siriagus 1:0cfe2255092a 21
Siriagus 4:d6661b976359 22
Siriagus 0:1f92de30d43e 23
Siriagus 1:0cfe2255092a 24 // Redefine pin names for simple access.
Siriagus 1:0cfe2255092a 25 #define JOY_H p17
Siriagus 1:0cfe2255092a 26 #define JOY_V p16
Siriagus 1:0cfe2255092a 27 #define JOY_BTN p15
Siriagus 1:0cfe2255092a 28
Siriagus 1:0cfe2255092a 29 #define LED_POT p20
Siriagus 1:0cfe2255092a 30
Siriagus 2:0ae5ac8b0cac 31 #define BUTTON_A p28
Siriagus 2:0ae5ac8b0cac 32 #define BUTTON_B p27
Siriagus 1:0cfe2255092a 33 #define BUTTON_C p29
Siriagus 1:0cfe2255092a 34
Siriagus 4:d6661b976359 35 // Input and Output
Siriagus 10:f2488a0ecab7 36 N5110 *lcd; /// Display
Siriagus 4:d6661b976359 37
Siriagus 10:f2488a0ecab7 38 InputManager *input; /// Responsible for managing user input
Siriagus 4:d6661b976359 39
Siriagus 0:1f92de30d43e 40 // Brightness potentiometer
Siriagus 1:0cfe2255092a 41 AnalogIn ledPot(LED_POT);
Siriagus 0:1f92de30d43e 42
Siriagus 0:1f92de30d43e 43 // Debugging
Siriagus 0:1f92de30d43e 44 BusOut leds(LED1, LED2, LED3, LED4);
Siriagus 0:1f92de30d43e 45
Siriagus 1:0cfe2255092a 46 // @brief Clears the screen and fill it with the image in the argument.
Siriagus 1:0cfe2255092a 47 void clearAndDrawImage(const int img[BANKS][WIDTH])
Siriagus 0:1f92de30d43e 48 {
Siriagus 0:1f92de30d43e 49 for (int i = 0; i < BANKS; ++i)
Siriagus 0:1f92de30d43e 50 {
Siriagus 0:1f92de30d43e 51 for (int j = 0; j < WIDTH; ++j)
Siriagus 0:1f92de30d43e 52 {
Siriagus 1:0cfe2255092a 53 lcd->buffer[j][i] = img[i][j];
Siriagus 0:1f92de30d43e 54 }
Siriagus 0:1f92de30d43e 55 }
Siriagus 0:1f92de30d43e 56 lcd->refresh();
Siriagus 0:1f92de30d43e 57 }
Siriagus 0:1f92de30d43e 58
Siriagus 10:f2488a0ecab7 59 void init(); /// Set up initial variables
Siriagus 10:f2488a0ecab7 60 void cleanUp(); /// Frees remaining allocated memory
Siriagus 1:0cfe2255092a 61
Siriagus 5:100d960fc6d5 62 StateManager* fsm;
Siriagus 5:100d960fc6d5 63
Siriagus 1:0cfe2255092a 64 int main()
Siriagus 1:0cfe2255092a 65 {
Siriagus 1:0cfe2255092a 66 init();
Siriagus 1:0cfe2255092a 67
Siriagus 7:678873947b29 68 Timer timer;
Siriagus 7:678873947b29 69 timer.start();
Siriagus 4:d6661b976359 70
Siriagus 0:1f92de30d43e 71 while(true)
Siriagus 7:678873947b29 72 {
Siriagus 8:9ac6a428fa26 73 // We need to call Sleep() repeatedly, because periodic interrupts in InputManager will cause it to wake up every 20 ms.
Siriagus 8:9ac6a428fa26 74 while (timer.read() < 0.08)
Siriagus 8:9ac6a428fa26 75 Sleep();
Siriagus 8:9ac6a428fa26 76
Siriagus 7:678873947b29 77 // update
Siriagus 0:1f92de30d43e 78 lcd->setBrightness(1.0 - ledPot); // Update brightness of screen
Siriagus 7:678873947b29 79 fsm->update(timer.read());
Siriagus 7:678873947b29 80 input->joystick->update();
Siriagus 4:d6661b976359 81
Siriagus 4:d6661b976359 82 // render
Siriagus 5:100d960fc6d5 83 lcd->clear();
Siriagus 7:678873947b29 84 fsm->render();
Siriagus 5:100d960fc6d5 85 lcd->refresh();
Siriagus 1:0cfe2255092a 86
Siriagus 7:678873947b29 87 fsm->processRequest(); // Change the state if requested.
Siriagus 7:678873947b29 88
Siriagus 7:678873947b29 89 timer.reset();
Siriagus 0:1f92de30d43e 90 }
Siriagus 0:1f92de30d43e 91
Siriagus 10:f2488a0ecab7 92 cleanUp(); // Not really reached as the program never terminates. Added for completeness.
Siriagus 0:1f92de30d43e 93
Siriagus 0:1f92de30d43e 94 return 0;
Siriagus 3:4e3f342a135c 95 }
Siriagus 3:4e3f342a135c 96
Siriagus 3:4e3f342a135c 97 void init()
Siriagus 3:4e3f342a135c 98 {
Siriagus 3:4e3f342a135c 99 // Init LCD
Siriagus 3:4e3f342a135c 100 lcd = new N5110(p7, p8, p9, p10, p11, p13, p26);
Siriagus 3:4e3f342a135c 101 lcd->init();
Siriagus 3:4e3f342a135c 102 lcd->normalMode();
Siriagus 3:4e3f342a135c 103 lcd->setBrightness(1.0 - ledPot); // Update brightness of screen
Siriagus 3:4e3f342a135c 104
Siriagus 4:d6661b976359 105 // Input
Siriagus 8:9ac6a428fa26 106 input = new InputManager(BUTTON_A, BUTTON_B, BUTTON_C, JOY_H, JOY_V, JOY_BTN);
Siriagus 3:4e3f342a135c 107
Siriagus 8:9ac6a428fa26 108 fsm = new StateManager(lcd, input, TITLE_SCREEN);
Siriagus 3:4e3f342a135c 109 }
Siriagus 3:4e3f342a135c 110
Siriagus 3:4e3f342a135c 111 void cleanUp()
Siriagus 3:4e3f342a135c 112 {
Siriagus 3:4e3f342a135c 113 delete lcd;
Siriagus 4:d6661b976359 114 delete input;
Siriagus 1:0cfe2255092a 115 }