Whack-A-Mole game created using the mbed, capacitive touchpad, and a vibration motor.

Dependencies:   4DGL-uLCD-SE mbed

Committer:
richsua
Date:
Wed Oct 21 18:41:01 2015 +0000
Revision:
0:12260ef28a24
Final Version

Who changed what in which revision?

UserRevisionLine numberNew contents of line
richsua 0:12260ef28a24 1 //Whack-a-mole with LCD and touch keypad
richsua 0:12260ef28a24 2
richsua 0:12260ef28a24 3 #include "mbed.h"
richsua 0:12260ef28a24 4 #include "uLCD_4DGL.h" /*LCD*/
richsua 0:12260ef28a24 5 #include <mpr121.h> /*touch keypad*/
richsua 0:12260ef28a24 6
richsua 0:12260ef28a24 7 #include <stdio.h> /* printf, scanf, puts, NULL */
richsua 0:12260ef28a24 8 #include <stdlib.h> /* srand, rand */
richsua 0:12260ef28a24 9 #include <time.h> /* time */
richsua 0:12260ef28a24 10 #include <math.h> /* log2 */
richsua 0:12260ef28a24 11
richsua 0:12260ef28a24 12
richsua 0:12260ef28a24 13
richsua 0:12260ef28a24 14 #define REFRESH_TIME_MS 2000
richsua 0:12260ef28a24 15
richsua 0:12260ef28a24 16 //Mole locations
richsua 0:12260ef28a24 17 #define X1 1
richsua 0:12260ef28a24 18 #define X2 43
richsua 0:12260ef28a24 19 #define X3 85
richsua 0:12260ef28a24 20 #define Y1 0
richsua 0:12260ef28a24 21 #define Y2 30
richsua 0:12260ef28a24 22 #define Y3 60
richsua 0:12260ef28a24 23 #define Y4 90
richsua 0:12260ef28a24 24
richsua 0:12260ef28a24 25 PwmOut vib(p21); //vibration motor
richsua 0:12260ef28a24 26 Serial pc(USBTX, USBRX);
richsua 0:12260ef28a24 27 uLCD_4DGL lcd(p28, p27, p30);
richsua 0:12260ef28a24 28
richsua 0:12260ef28a24 29 AnalogIn random_analog(A0);
richsua 0:12260ef28a24 30
richsua 0:12260ef28a24 31 // Create the interrupt receiver object on pin 26 -->> for keypad
richsua 0:12260ef28a24 32 InterruptIn interrupt(p26);
richsua 0:12260ef28a24 33
richsua 0:12260ef28a24 34 // Setup the i2c bus on pins 28 and 27 -->> for keypad
richsua 0:12260ef28a24 35 I2C i2c(p9, p10);
richsua 0:12260ef28a24 36
richsua 0:12260ef28a24 37 // Setup the Mpr121:
richsua 0:12260ef28a24 38 // constructor(i2c object, i2c address of the mpr121) -->> for keypad
richsua 0:12260ef28a24 39 Mpr121 mpr121(&i2c, Mpr121::ADD_VSS);
richsua 0:12260ef28a24 40
richsua 0:12260ef28a24 41 //Timer
richsua 0:12260ef28a24 42 Timer t; //for function use
richsua 0:12260ef28a24 43 Timer gametime; //for int main() use
richsua 0:12260ef28a24 44 Timer again; //for restart countdown
richsua 0:12260ef28a24 45
richsua 0:12260ef28a24 46 //global variables accessable to all functions
richsua 0:12260ef28a24 47 //mole locations
richsua 0:12260ef28a24 48 int hole = 0; //hole number
richsua 0:12260ef28a24 49 int x = 0; //coordinate values (not actual pixel values)
richsua 0:12260ef28a24 50 int y = 0;
richsua 0:12260ef28a24 51 //score
richsua 0:12260ef28a24 52 int value = 0;
richsua 0:12260ef28a24 53 int keynum = 0;
richsua 0:12260ef28a24 54 int hit = 0;
richsua 0:12260ef28a24 55 int miss = 0;
richsua 0:12260ef28a24 56 int highest = 0;
richsua 0:12260ef28a24 57
richsua 0:12260ef28a24 58 bool isMoleAlive = 0;
richsua 0:12260ef28a24 59
richsua 0:12260ef28a24 60
richsua 0:12260ef28a24 61 // initializes screen with 12 empty mole holes
richsua 0:12260ef28a24 62 void allempty()
richsua 0:12260ef28a24 63 {
richsua 0:12260ef28a24 64 lcd.cls();
richsua 0:12260ef28a24 65
richsua 0:12260ef28a24 66 //choose empty mole hole picture and intialize variables for while function
richsua 0:12260ef28a24 67 lcd.set_sector_address(0x0000, 0x0000);
richsua 0:12260ef28a24 68 int i = 0;
richsua 0:12260ef28a24 69 int k = 1;
richsua 0:12260ef28a24 70 int x = 0;
richsua 0:12260ef28a24 71 int y = 1;
richsua 0:12260ef28a24 72
richsua 0:12260ef28a24 73 //print 12 empty mole holes
richsua 0:12260ef28a24 74 while(i < 12)
richsua 0:12260ef28a24 75 {
richsua 0:12260ef28a24 76 lcd.locate(0,15);
richsua 0:12260ef28a24 77 lcd.display_image(x, y);
richsua 0:12260ef28a24 78 if ( k < 3 )
richsua 0:12260ef28a24 79 { x += 42;
richsua 0:12260ef28a24 80 k++; }
richsua 0:12260ef28a24 81 else
richsua 0:12260ef28a24 82 { k = 1;
richsua 0:12260ef28a24 83 x = 0;
richsua 0:12260ef28a24 84 y += 30; }
richsua 0:12260ef28a24 85 i++;
richsua 0:12260ef28a24 86 }
richsua 0:12260ef28a24 87
richsua 0:12260ef28a24 88 //count down to start of game
richsua 0:12260ef28a24 89 int z = 3;
richsua 0:12260ef28a24 90 lcd.locate(4, 15);
richsua 0:12260ef28a24 91 lcd.printf("Get Ready!");
richsua 0:12260ef28a24 92 wait(1);
richsua 0:12260ef28a24 93 while (z > 0)
richsua 0:12260ef28a24 94 {
richsua 0:12260ef28a24 95 lcd.locate(4, 15);
richsua 0:12260ef28a24 96 lcd.printf(" %d ", z);
richsua 0:12260ef28a24 97 wait(1);
richsua 0:12260ef28a24 98 z--;
richsua 0:12260ef28a24 99 }
richsua 0:12260ef28a24 100 lcd.locate(5, 15);
richsua 0:12260ef28a24 101 lcd.printf(" Go! ");
richsua 0:12260ef28a24 102 wait(0.5);
richsua 0:12260ef28a24 103 }
richsua 0:12260ef28a24 104
richsua 0:12260ef28a24 105 //revised modulus operator created to work correctly with negative modulus
richsua 0:12260ef28a24 106 int mod (int x1, int x2)
richsua 0:12260ef28a24 107 {
richsua 0:12260ef28a24 108 if(x1 < 0) { return (x1 % x2)+x2; }
richsua 0:12260ef28a24 109 else { return x1 % x2; }
richsua 0:12260ef28a24 110 }
richsua 0:12260ef28a24 111
richsua 0:12260ef28a24 112 //pop / show the mole
richsua 0:12260ef28a24 113 void popup()
richsua 0:12260ef28a24 114 {
richsua 0:12260ef28a24 115 isMoleAlive = 1;
richsua 0:12260ef28a24 116
richsua 0:12260ef28a24 117 //generate random int 0 to 11
richsua 0:12260ef28a24 118 hole = rand() % 12;
richsua 0:12260ef28a24 119
richsua 0:12260ef28a24 120 //use random number to match x and y coordinate of touchpad
richsua 0:12260ef28a24 121 if (hole < 4) { x = 0;}
richsua 0:12260ef28a24 122 else if (hole < 8) { x = 1;}
richsua 0:12260ef28a24 123 else { x = 2;}
richsua 0:12260ef28a24 124 y = mod(4-(1+mod(hole, 4)), 4);
richsua 0:12260ef28a24 125
richsua 0:12260ef28a24 126 //pop up mole corresponding to that hole number
richsua 0:12260ef28a24 127 lcd.set_sector_address(0x0000, 0x0005);
richsua 0:12260ef28a24 128 lcd.display_image(x*42, y*30);
richsua 0:12260ef28a24 129
richsua 0:12260ef28a24 130 //testing purposes only
richsua 0:12260ef28a24 131 //lcd.locate(0,15);
richsua 0:12260ef28a24 132 //lcd.printf("r:%d, x:%d, y:%d\n", hole, x, y);
richsua 0:12260ef28a24 133
richsua 0:12260ef28a24 134 highest++; //highest possible number of hits
richsua 0:12260ef28a24 135
richsua 0:12260ef28a24 136 lcd.locate(0,15);
richsua 0:12260ef28a24 137 //lcd.printf("H:%d Hit:%d, Miss:%d", keynum, hit, miss);
richsua 0:12260ef28a24 138 }
richsua 0:12260ef28a24 139
richsua 0:12260ef28a24 140 //hide a mole
richsua 0:12260ef28a24 141 void hide()
richsua 0:12260ef28a24 142 {
richsua 0:12260ef28a24 143 isMoleAlive = 0;
richsua 0:12260ef28a24 144 vib = 0;
richsua 0:12260ef28a24 145 //reseting the mole hole to empty hole
richsua 0:12260ef28a24 146 lcd.set_sector_address(0x0000, 0x0000);
richsua 0:12260ef28a24 147 lcd.display_image(x*42, y*30);
richsua 0:12260ef28a24 148 }
richsua 0:12260ef28a24 149
richsua 0:12260ef28a24 150 //to convert keypad
richsua 0:12260ef28a24 151 int mylog2(int arg)
richsua 0:12260ef28a24 152 {
richsua 0:12260ef28a24 153 //creating log 2
richsua 0:12260ef28a24 154 int squared = 1;
richsua 0:12260ef28a24 155 int tmp = 0; //log 2 value
richsua 0:12260ef28a24 156 for ( ; squared < arg; ) //( squared != arg )
richsua 0:12260ef28a24 157 {
richsua 0:12260ef28a24 158 squared = squared * 2;
richsua 0:12260ef28a24 159 tmp++;
richsua 0:12260ef28a24 160 }
richsua 0:12260ef28a24 161 if (squared == arg)
richsua 0:12260ef28a24 162 {
richsua 0:12260ef28a24 163 return tmp; //keynum = tmp;
richsua 0:12260ef28a24 164 }
richsua 0:12260ef28a24 165 return keynum; //return same in case more than one pad is touched.
richsua 0:12260ef28a24 166 }
richsua 0:12260ef28a24 167
richsua 0:12260ef28a24 168 void keyInterrupt() {
richsua 0:12260ef28a24 169
richsua 0:12260ef28a24 170 value=mpr121.read(0x00);
richsua 0:12260ef28a24 171 value +=mpr121.read(0x01)<<8;
richsua 0:12260ef28a24 172 // LED demo mod by J. Hamblen
richsua 0:12260ef28a24 173 pc.printf("MPR value: %d \r\n", value);
richsua 0:12260ef28a24 174
richsua 0:12260ef28a24 175
richsua 0:12260ef28a24 176 //Did the hammer hit the mole?
richsua 0:12260ef28a24 177 if (value != 0) //ignore the release
richsua 0:12260ef28a24 178 {
richsua 0:12260ef28a24 179 //Converting to keynum
richsua 0:12260ef28a24 180 keynum = mylog2(value);
richsua 0:12260ef28a24 181
richsua 0:12260ef28a24 182 //hit or miss
richsua 0:12260ef28a24 183 if ( keynum == hole && isMoleAlive ) //If the hammer hit the mole
richsua 0:12260ef28a24 184 {
richsua 0:12260ef28a24 185 hit++;
richsua 0:12260ef28a24 186 vib = 1;
richsua 0:12260ef28a24 187 lcd.set_sector_address(0x0000, 0x000A);
richsua 0:12260ef28a24 188 lcd.display_image(x*42, y*30);
richsua 0:12260ef28a24 189 isMoleAlive = 0;
richsua 0:12260ef28a24 190 }
richsua 0:12260ef28a24 191 else
richsua 0:12260ef28a24 192 {
richsua 0:12260ef28a24 193 miss++;
richsua 0:12260ef28a24 194 }
richsua 0:12260ef28a24 195
richsua 0:12260ef28a24 196
richsua 0:12260ef28a24 197 }
richsua 0:12260ef28a24 198
richsua 0:12260ef28a24 199 }
richsua 0:12260ef28a24 200
richsua 0:12260ef28a24 201
richsua 0:12260ef28a24 202
richsua 0:12260ef28a24 203 //initialize lcd screen
richsua 0:12260ef28a24 204 void setup()
richsua 0:12260ef28a24 205 {
richsua 0:12260ef28a24 206 interrupt.fall(&keyInterrupt);
richsua 0:12260ef28a24 207 interrupt.mode(PullUp);
richsua 0:12260ef28a24 208
richsua 0:12260ef28a24 209 srand (random_analog * 100000);
richsua 0:12260ef28a24 210
richsua 0:12260ef28a24 211 lcd.baudrate(3000000);
richsua 0:12260ef28a24 212 lcd.background_color(0x029142);
richsua 0:12260ef28a24 213 lcd.textbackground_color(0x029142);
richsua 0:12260ef28a24 214 lcd.cls();
richsua 0:12260ef28a24 215 lcd.media_init();
richsua 0:12260ef28a24 216 lcd.color(WHITE);
richsua 0:12260ef28a24 217 lcd.set_font(FONT_7X8);
richsua 0:12260ef28a24 218 lcd.text_bold(ON);
richsua 0:12260ef28a24 219 }
richsua 0:12260ef28a24 220
richsua 0:12260ef28a24 221 //printing score
richsua 0:12260ef28a24 222 void printScore()
richsua 0:12260ef28a24 223 {
richsua 0:12260ef28a24 224 lcd.locate(0,15);
richsua 0:12260ef28a24 225 lcd.printf("->%d ", keynum);
richsua 0:12260ef28a24 226 lcd.locate(8,15);
richsua 0:12260ef28a24 227 lcd.printf("+%d ", hit);
richsua 0:12260ef28a24 228 lcd.locate(15,15);
richsua 0:12260ef28a24 229 lcd.printf("-%d ", miss);
richsua 0:12260ef28a24 230 }
richsua 0:12260ef28a24 231
richsua 0:12260ef28a24 232 //function to endgame and print final score
richsua 0:12260ef28a24 233 void endgame()
richsua 0:12260ef28a24 234 {
richsua 0:12260ef28a24 235 //displaying final score
richsua 0:12260ef28a24 236 lcd.cls();
richsua 0:12260ef28a24 237 lcd.text_width(1.5);
richsua 0:12260ef28a24 238 lcd.text_height(1.5);
richsua 0:12260ef28a24 239 lcd.color(WHITE);
richsua 0:12260ef28a24 240 lcd.locate(0,1);
richsua 0:12260ef28a24 241 lcd.printf(" FINAL SCORE\n");
richsua 0:12260ef28a24 242 lcd.printf("------------------\n");
richsua 0:12260ef28a24 243 lcd.locate(1,4);
richsua 0:12260ef28a24 244 lcd.printf("%d HITS", hit);
richsua 0:12260ef28a24 245 lcd.locate(1,7);
richsua 0:12260ef28a24 246 lcd.printf("%d MISSES \n\n------------------", miss);
richsua 0:12260ef28a24 247
richsua 0:12260ef28a24 248 //print a commentary based on player's score
richsua 0:12260ef28a24 249 double grade = 100*(hit-(0.25*miss))/highest;
richsua 0:12260ef28a24 250 lcd.locate(0,12);
richsua 0:12260ef28a24 251 if (grade < 20) {lcd.printf(" WOW.. YOU SUCK");}
richsua 0:12260ef28a24 252 else if (grade < 50) {lcd.printf(" TRY HARDER");}
richsua 0:12260ef28a24 253 else if (grade < 80) {lcd.printf(" YOU DID OKAY");}
richsua 0:12260ef28a24 254 else if (grade < 90) {lcd.printf(" NICE JOB!!");}
richsua 0:12260ef28a24 255 else if (grade < 100) {lcd.printf(" GRRRREAT!!");}
richsua 0:12260ef28a24 256 else if (grade == 100)
richsua 0:12260ef28a24 257 {
richsua 0:12260ef28a24 258 lcd.locate(0, 11);
richsua 0:12260ef28a24 259 lcd.printf(" /\\/\\/\\/\\/\\ \n");
richsua 0:12260ef28a24 260 lcd.printf(" | |\n");
richsua 0:12260ef28a24 261 lcd.printf(" | MOLE GOD |\n");
richsua 0:12260ef28a24 262 lcd.printf(" |__________|\n");
richsua 0:12260ef28a24 263 }
richsua 0:12260ef28a24 264 }
richsua 0:12260ef28a24 265
richsua 0:12260ef28a24 266 //function to restart another game
richsua 0:12260ef28a24 267 bool restart()
richsua 0:12260ef28a24 268 {
richsua 0:12260ef28a24 269
richsua 0:12260ef28a24 270 bool replay = false;
richsua 0:12260ef28a24 271
richsua 0:12260ef28a24 272 //reset score
richsua 0:12260ef28a24 273 hit = miss = highest = 0;
richsua 0:12260ef28a24 274
richsua 0:12260ef28a24 275 //clear screen for restart prompt
richsua 0:12260ef28a24 276 lcd.cls();
richsua 0:12260ef28a24 277 lcd.locate(0,1);
richsua 0:12260ef28a24 278 lcd.text_height(2);
richsua 0:12260ef28a24 279 lcd.text_width(2);
richsua 0:12260ef28a24 280 lcd.printf(" ANOTHER GAME? \nPRESS ANY KEY \n");
richsua 0:12260ef28a24 281
richsua 0:12260ef28a24 282 again.start();
richsua 0:12260ef28a24 283 int countdown;
richsua 0:12260ef28a24 284 //waiting for key press
richsua 0:12260ef28a24 285 while(again.read() < 10 && replay == false)
richsua 0:12260ef28a24 286 {
richsua 0:12260ef28a24 287 countdown = 10 - (int)again.read();
richsua 0:12260ef28a24 288 //countdown: user has 10 seconds to replay
richsua 0:12260ef28a24 289 lcd.locate(0,7);
richsua 0:12260ef28a24 290 lcd.printf(" %d ", countdown);
richsua 0:12260ef28a24 291
richsua 0:12260ef28a24 292 //check for key press
richsua 0:12260ef28a24 293 if(value != 0)
richsua 0:12260ef28a24 294 {
richsua 0:12260ef28a24 295 //user has pressed a key and wants to play again!
richsua 0:12260ef28a24 296 replay = true;
richsua 0:12260ef28a24 297 break;
richsua 0:12260ef28a24 298 }
richsua 0:12260ef28a24 299
richsua 0:12260ef28a24 300 }
richsua 0:12260ef28a24 301
richsua 0:12260ef28a24 302 again.stop();
richsua 0:12260ef28a24 303 again.reset();
richsua 0:12260ef28a24 304 return replay;
richsua 0:12260ef28a24 305 }
richsua 0:12260ef28a24 306
richsua 0:12260ef28a24 307
richsua 0:12260ef28a24 308 //////////////////////////////////////////////////
richsua 0:12260ef28a24 309 ////////////####main####//////////////
richsua 0:12260ef28a24 310 int main()
richsua 0:12260ef28a24 311 {
richsua 0:12260ef28a24 312 bool keepplaying = 1;
richsua 0:12260ef28a24 313
richsua 0:12260ef28a24 314 //initializing...
richsua 0:12260ef28a24 315 setup();
richsua 0:12260ef28a24 316
richsua 0:12260ef28a24 317 while(keepplaying == true)
richsua 0:12260ef28a24 318 { //starting the game - 30 seconds for testing
richsua 0:12260ef28a24 319 allempty();
richsua 0:12260ef28a24 320 gametime.reset();
richsua 0:12260ef28a24 321 gametime.start();
richsua 0:12260ef28a24 322 float timelimit;
richsua 0:12260ef28a24 323 float overalltime = 20;
richsua 0:12260ef28a24 324
richsua 0:12260ef28a24 325 while (gametime.read() < overalltime)
richsua 0:12260ef28a24 326 {
richsua 0:12260ef28a24 327 popup();
richsua 0:12260ef28a24 328
richsua 0:12260ef28a24 329 //reduce time limit as game progresses
richsua 0:12260ef28a24 330 if (gametime.read() < overalltime/3) { timelimit = 2; }
richsua 0:12260ef28a24 331 else if (gametime.read() < overalltime/2) { timelimit = 1.6; }
richsua 0:12260ef28a24 332 else if (gametime.read() < overalltime/1.5) { timelimit = 1.2; }
richsua 0:12260ef28a24 333 else if (gametime.read() < overalltime/1.3) { timelimit = 1; }
richsua 0:12260ef28a24 334 else if (gametime.read() < overalltime/1.1) { timelimit = 0.8; }
richsua 0:12260ef28a24 335 else if (gametime.read() < overalltime) { timelimit = 0.65;}
richsua 0:12260ef28a24 336
richsua 0:12260ef28a24 337 wait(timelimit);
richsua 0:12260ef28a24 338
richsua 0:12260ef28a24 339 if (isMoleAlive == 1)
richsua 0:12260ef28a24 340 {
richsua 0:12260ef28a24 341 miss++;
richsua 0:12260ef28a24 342 }
richsua 0:12260ef28a24 343
richsua 0:12260ef28a24 344 hide();
richsua 0:12260ef28a24 345 printScore();
richsua 0:12260ef28a24 346
richsua 0:12260ef28a24 347 }
richsua 0:12260ef28a24 348
richsua 0:12260ef28a24 349 gametime.stop();
richsua 0:12260ef28a24 350 endgame();
richsua 0:12260ef28a24 351 wait(3);
richsua 0:12260ef28a24 352 keepplaying = restart();
richsua 0:12260ef28a24 353
richsua 0:12260ef28a24 354
richsua 0:12260ef28a24 355 }
richsua 0:12260ef28a24 356
richsua 0:12260ef28a24 357 lcd.cls();
richsua 0:12260ef28a24 358 lcd.locate(0,2);
richsua 0:12260ef28a24 359 lcd.text_height(2);
richsua 0:12260ef28a24 360 lcd.text_width(2);
richsua 0:12260ef28a24 361 lcd.printf(" THANKS\n");
richsua 0:12260ef28a24 362 lcd.printf(" FOR\n\n");
richsua 0:12260ef28a24 363 lcd.printf(" PLAYING\n");
richsua 0:12260ef28a24 364
richsua 0:12260ef28a24 365 }
richsua 0:12260ef28a24 366
richsua 0:12260ef28a24 367
richsua 0:12260ef28a24 368
richsua 0:12260ef28a24 369