![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
One player pong with seven segment display for score keeping
Dependencies: 4DGL-uLCD-SE PinDetect SDFileSystem mbed-rtos mbed wave_player
Fork of ECE2036Lab2StarterCode by
main.cpp@2:6163865f5ce3, 2014-06-20 (annotated)
- Committer:
- jlind6
- Date:
- Fri Jun 20 15:22:28 2014 +0000
- Revision:
- 2:6163865f5ce3
- Parent:
- 0:356124c0bafc
- Child:
- 3:c93d1b51785c
(Typo) On line 135, changed a vy to a vx.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
jlind6 | 0:356124c0bafc | 1 | #include "mbed.h" |
jlind6 | 0:356124c0bafc | 2 | #include "PinDetect.h" |
jlind6 | 0:356124c0bafc | 3 | #include "uLCD_4DGL.h" |
jlind6 | 0:356124c0bafc | 4 | #include "Speaker.h" |
jlind6 | 0:356124c0bafc | 5 | |
jlind6 | 0:356124c0bafc | 6 | // Pushbuttons |
jlind6 | 0:356124c0bafc | 7 | PinDetect pbUp(p15); |
jlind6 | 0:356124c0bafc | 8 | PinDetect pbDown(p16); |
jlind6 | 0:356124c0bafc | 9 | // uLCD |
jlind6 | 0:356124c0bafc | 10 | uLCD_4DGL uLCD(p28, p27, p29); |
jlind6 | 0:356124c0bafc | 11 | //Speaker |
jlind6 | 0:356124c0bafc | 12 | Speaker mySpeaker(p21); |
jlind6 | 0:356124c0bafc | 13 | |
jlind6 | 0:356124c0bafc | 14 | // Global variables needed for the push button interrupts |
jlind6 | 0:356124c0bafc | 15 | int cornerX = 118, cornerY = 1; |
jlind6 | 0:356124c0bafc | 16 | int oldCornerY = 1; |
jlind6 | 0:356124c0bafc | 17 | int paddleMove = 8; |
jlind6 | 0:356124c0bafc | 18 | int length = 40; |
jlind6 | 0:356124c0bafc | 19 | int width = 3; |
jlind6 | 0:356124c0bafc | 20 | |
jlind6 | 0:356124c0bafc | 21 | // State machine definitions |
jlind6 | 0:356124c0bafc | 22 | enum gameStateType {START, WAIT, GAME_SETUP, GAME, LOSE}; |
jlind6 | 0:356124c0bafc | 23 | /* State Definitions: |
jlind6 | 0:356124c0bafc | 24 | * START -- Creates the start screen |
jlind6 | 0:356124c0bafc | 25 | * WAIT -- After the start screen, goes into wait where mbed spins and does nothing |
jlind6 | 0:356124c0bafc | 26 | * GAME_SETUP -- Sets up one time things (like boarders, initializes beginning velocity |
jlind6 | 0:356124c0bafc | 27 | * GAME -- When the user actually gets to play |
jlind6 | 0:356124c0bafc | 28 | * LOSE -- clears the screen, prints you lose, waits, then goes back to start |
jlind6 | 0:356124c0bafc | 29 | */ |
jlind6 | 0:356124c0bafc | 30 | |
jlind6 | 0:356124c0bafc | 31 | // Global state machine variable (So that the pushbuttons can modify it) |
jlind6 | 0:356124c0bafc | 32 | gameStateType gameState = START; |
jlind6 | 0:356124c0bafc | 33 | |
jlind6 | 0:356124c0bafc | 34 | // Pushbutton callbacks |
jlind6 | 0:356124c0bafc | 35 | // WARNING: Do not call to draw anything to the uLCD in these |
jlind6 | 0:356124c0bafc | 36 | // as this will cause the uLCD to crash sometimes. Update positions |
jlind6 | 0:356124c0bafc | 37 | // and draw elsewhere (like it's done here). |
jlind6 | 0:356124c0bafc | 38 | // Only modify the logic inside the callback functions. |
jlind6 | 0:356124c0bafc | 39 | void pbUp_hit_callback (void) |
jlind6 | 0:356124c0bafc | 40 | { |
jlind6 | 0:356124c0bafc | 41 | switch (gameState) |
jlind6 | 0:356124c0bafc | 42 | { |
jlind6 | 0:356124c0bafc | 43 | case WAIT: |
jlind6 | 0:356124c0bafc | 44 | gameState = GAME_SETUP; |
jlind6 | 0:356124c0bafc | 45 | break; |
jlind6 | 0:356124c0bafc | 46 | case GAME: |
jlind6 | 0:356124c0bafc | 47 | if(cornerY > paddleMove) { |
jlind6 | 0:356124c0bafc | 48 | cornerY -= paddleMove; |
jlind6 | 0:356124c0bafc | 49 | } |
jlind6 | 0:356124c0bafc | 50 | break; |
jlind6 | 0:356124c0bafc | 51 | } |
jlind6 | 0:356124c0bafc | 52 | } |
jlind6 | 0:356124c0bafc | 53 | |
jlind6 | 0:356124c0bafc | 54 | void pbDown_hit_callback (void) |
jlind6 | 0:356124c0bafc | 55 | { |
jlind6 | 0:356124c0bafc | 56 | switch (gameState) |
jlind6 | 0:356124c0bafc | 57 | { |
jlind6 | 0:356124c0bafc | 58 | case WAIT: |
jlind6 | 0:356124c0bafc | 59 | gameState = GAME_SETUP; |
jlind6 | 0:356124c0bafc | 60 | break; |
jlind6 | 0:356124c0bafc | 61 | case GAME: |
jlind6 | 0:356124c0bafc | 62 | if(cornerY < 127 - paddleMove - length){ |
jlind6 | 0:356124c0bafc | 63 | cornerY += paddleMove; |
jlind6 | 0:356124c0bafc | 64 | } |
jlind6 | 0:356124c0bafc | 65 | break; |
jlind6 | 0:356124c0bafc | 66 | } |
jlind6 | 0:356124c0bafc | 67 | } |
jlind6 | 0:356124c0bafc | 68 | |
jlind6 | 0:356124c0bafc | 69 | int main() |
jlind6 | 0:356124c0bafc | 70 | { |
jlind6 | 0:356124c0bafc | 71 | // This is setting up the pushbuttons |
jlind6 | 0:356124c0bafc | 72 | // Don't modify this code. |
jlind6 | 0:356124c0bafc | 73 | pbUp.mode(PullUp); |
jlind6 | 0:356124c0bafc | 74 | pbDown.mode(PullUp); |
jlind6 | 0:356124c0bafc | 75 | wait(0.1); |
jlind6 | 0:356124c0bafc | 76 | pbUp.attach_deasserted(&pbUp_hit_callback); |
jlind6 | 0:356124c0bafc | 77 | pbDown.attach_deasserted(&pbDown_hit_callback); |
jlind6 | 0:356124c0bafc | 78 | pbUp.setSampleFrequency(); |
jlind6 | 0:356124c0bafc | 79 | pbDown.setSampleFrequency(); |
jlind6 | 0:356124c0bafc | 80 | // Don't modify this code. |
jlind6 | 0:356124c0bafc | 81 | |
jlind6 | 0:356124c0bafc | 82 | uLCD.display_control(PORTRAIT); |
jlind6 | 0:356124c0bafc | 83 | uLCD.cls(); |
jlind6 | 0:356124c0bafc | 84 | uLCD.baudrate(BAUD_3000000); |
jlind6 | 0:356124c0bafc | 85 | uLCD.background_color(BLACK); |
jlind6 | 0:356124c0bafc | 86 | |
jlind6 | 0:356124c0bafc | 87 | // Initialize all your variables outside the while/switch statement |
jlind6 | 0:356124c0bafc | 88 | // to avoid compiler warning/errors |
jlind6 | 0:356124c0bafc | 89 | int vxSign = 1, vySign = 1; |
jlind6 | 0:356124c0bafc | 90 | float fx=50.0,fy=21.0,vx=1.6,vy=1.2; |
jlind6 | 0:356124c0bafc | 91 | int x=50, y=21, radius=5; |
jlind6 | 0:356124c0bafc | 92 | int score = 0; |
jlind6 | 0:356124c0bafc | 93 | int i = 0; |
jlind6 | 0:356124c0bafc | 94 | int random; |
jlind6 | 0:356124c0bafc | 95 | |
jlind6 | 0:356124c0bafc | 96 | while (1) |
jlind6 | 0:356124c0bafc | 97 | { |
jlind6 | 0:356124c0bafc | 98 | switch (gameState) |
jlind6 | 0:356124c0bafc | 99 | { |
jlind6 | 0:356124c0bafc | 100 | case START: |
jlind6 | 0:356124c0bafc | 101 | uLCD.cls(); |
jlind6 | 0:356124c0bafc | 102 | uLCD.locate(0,0); |
jlind6 | 0:356124c0bafc | 103 | uLCD.printf("Pong!!!\n\n"); |
jlind6 | 0:356124c0bafc | 104 | uLCD.printf("Press Key to Start"); |
jlind6 | 0:356124c0bafc | 105 | gameState = WAIT; |
jlind6 | 0:356124c0bafc | 106 | break; |
jlind6 | 0:356124c0bafc | 107 | case GAME_SETUP: |
jlind6 | 0:356124c0bafc | 108 | uLCD.cls(); |
jlind6 | 0:356124c0bafc | 109 | uLCD.line(0, 0, 127, 0, 0xCFB53B); |
jlind6 | 0:356124c0bafc | 110 | uLCD.line(127, 0, 127, 127, 0xCFB53B); |
jlind6 | 0:356124c0bafc | 111 | uLCD.line(127, 127, 0, 127, 0xCFB53B); |
jlind6 | 0:356124c0bafc | 112 | uLCD.line(0, 127, 0, 0, 0xCFB53B); |
jlind6 | 0:356124c0bafc | 113 | vx = 1.6; |
jlind6 | 0:356124c0bafc | 114 | vy = 1.2; |
jlind6 | 0:356124c0bafc | 115 | srand(i); |
jlind6 | 0:356124c0bafc | 116 | random = (rand() % (118 - 2*radius)) + radius; |
jlind6 | 0:356124c0bafc | 117 | fx = random; |
jlind6 | 0:356124c0bafc | 118 | random = (rand() % (127 - 2*radius)) + radius; |
jlind6 | 0:356124c0bafc | 119 | fy = random; |
jlind6 | 0:356124c0bafc | 120 | x=(int)fx; y=(int)fy; |
jlind6 | 0:356124c0bafc | 121 | random = rand() % 1; |
jlind6 | 0:356124c0bafc | 122 | vxSign=-1; vySign=((float)random - 0.5)*2; |
jlind6 | 0:356124c0bafc | 123 | uLCD.filled_rectangle(cornerX, cornerY, cornerX+width, cornerY+length, BLUE); |
jlind6 | 0:356124c0bafc | 124 | gameState = GAME; |
jlind6 | 0:356124c0bafc | 125 | break; |
jlind6 | 0:356124c0bafc | 126 | case GAME: |
jlind6 | 0:356124c0bafc | 127 | if ((fx+vxSign*vx<=radius+1)) |
jlind6 | 0:356124c0bafc | 128 | { |
jlind6 | 0:356124c0bafc | 129 | vxSign = -vxSign; |
jlind6 | 0:356124c0bafc | 130 | } |
jlind6 | 0:356124c0bafc | 131 | if ((fy+vySign*vy<=radius+1) || (fy+vySign*vy>=126-radius)) |
jlind6 | 0:356124c0bafc | 132 | { |
jlind6 | 0:356124c0bafc | 133 | vySign = -vySign; |
jlind6 | 0:356124c0bafc | 134 | } |
jlind6 | 2:6163865f5ce3 | 135 | if (((fx+vxSign*vx >= cornerX) && (fx+vxSign*vx <= cornerX+3)) && |
jlind6 | 0:356124c0bafc | 136 | ((fy+vySign*vy>=cornerY) && (fy+vySign*vy<=cornerY+length))) |
jlind6 | 0:356124c0bafc | 137 | { |
jlind6 | 0:356124c0bafc | 138 | vySign = -vySign; |
jlind6 | 0:356124c0bafc | 139 | } |
jlind6 | 0:356124c0bafc | 140 | if ((fx+vxSign*vx>=126-radius)) |
jlind6 | 0:356124c0bafc | 141 | { |
jlind6 | 0:356124c0bafc | 142 | vx = 0; |
jlind6 | 0:356124c0bafc | 143 | vy = 0; |
jlind6 | 0:356124c0bafc | 144 | gameState = LOSE; |
jlind6 | 0:356124c0bafc | 145 | } |
jlind6 | 0:356124c0bafc | 146 | if ((fx+vxSign*vx>=cornerX-radius) && (fy+vySign*vy<=cornerY+length) && (fy+vySign*vy>=cornerY)) |
jlind6 | 0:356124c0bafc | 147 | { |
jlind6 | 0:356124c0bafc | 148 | vxSign = -vxSign; |
jlind6 | 0:356124c0bafc | 149 | score++; |
jlind6 | 0:356124c0bafc | 150 | uLCD.locate(1,1); |
jlind6 | 0:356124c0bafc | 151 | uLCD.printf("%d", score); |
jlind6 | 0:356124c0bafc | 152 | } |
jlind6 | 0:356124c0bafc | 153 | uLCD.circle(x, y, radius, BLACK); |
jlind6 | 0:356124c0bafc | 154 | fx=fx+(vxSign*vx); |
jlind6 | 0:356124c0bafc | 155 | fy=fy+(vySign*vy); |
jlind6 | 0:356124c0bafc | 156 | x=(int)fx; |
jlind6 | 0:356124c0bafc | 157 | y=(int)fy; |
jlind6 | 0:356124c0bafc | 158 | uLCD.circle(x, y, radius, WHITE); |
jlind6 | 0:356124c0bafc | 159 | // We can assume that these for loops are quick enough that the paddle will move only one interval. |
jlind6 | 0:356124c0bafc | 160 | // These movements of the paddle have been optimized. Feel free to draw it out to see how it's been done. |
jlind6 | 0:356124c0bafc | 161 | if(oldCornerY > cornerY) { |
jlind6 | 0:356124c0bafc | 162 | uLCD.filled_rectangle(cornerX, oldCornerY-paddleMove+1, cornerX+width, oldCornerY, BLUE); |
jlind6 | 0:356124c0bafc | 163 | uLCD.filled_rectangle(cornerX, oldCornerY+length-paddleMove+1, cornerX+width, oldCornerY+length, BLACK); |
jlind6 | 0:356124c0bafc | 164 | oldCornerY = cornerY; |
jlind6 | 0:356124c0bafc | 165 | } |
jlind6 | 0:356124c0bafc | 166 | else if(oldCornerY < cornerY) { |
jlind6 | 0:356124c0bafc | 167 | uLCD.filled_rectangle(cornerX, oldCornerY, cornerX+width, oldCornerY+paddleMove, BLACK); |
jlind6 | 0:356124c0bafc | 168 | uLCD.filled_rectangle(cornerX, oldCornerY+length, cornerX+width, oldCornerY+length+paddleMove, BLUE); |
jlind6 | 0:356124c0bafc | 169 | oldCornerY = cornerY; |
jlind6 | 0:356124c0bafc | 170 | } |
jlind6 | 0:356124c0bafc | 171 | break; |
jlind6 | 0:356124c0bafc | 172 | case LOSE: |
jlind6 | 0:356124c0bafc | 173 | uLCD.cls(); |
jlind6 | 0:356124c0bafc | 174 | uLCD.printf("YOU LOSE D:"); |
jlind6 | 0:356124c0bafc | 175 | score = 0; |
jlind6 | 0:356124c0bafc | 176 | wait(5.0); |
jlind6 | 0:356124c0bafc | 177 | gameState = START; |
jlind6 | 0:356124c0bafc | 178 | break; |
jlind6 | 0:356124c0bafc | 179 | case WAIT: |
jlind6 | 0:356124c0bafc | 180 | // Used to seed the rand() function so we don't get the same starting position every time. |
jlind6 | 0:356124c0bafc | 181 | i++; |
jlind6 | 0:356124c0bafc | 182 | break; |
jlind6 | 0:356124c0bafc | 183 | } |
jlind6 | 0:356124c0bafc | 184 | } |
jlind6 | 0:356124c0bafc | 185 | } |