![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
DuckHunt game using IMU sensor and uLCD display
Dependencies: 4DGL-uLCD-SE LSM9DS1_Library_cal SDFileSystem mbed wave_player
Fork of uLCD144G2_demo by
main.cpp@10:c19a945d9dca, 2016-10-31 (annotated)
- Committer:
- jli26
- Date:
- Mon Oct 31 21:20:17 2016 +0000
- Revision:
- 10:c19a945d9dca
- Parent:
- 8:31e63caf37e2
Duck Hunt Game
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
4180_1 | 8:31e63caf37e2 | 1 | // uLCD-144-G2 demo program for uLCD-4GL LCD driver library |
4180_1 | 0:cfcf73272647 | 2 | // |
4180_1 | 0:cfcf73272647 | 3 | #include "mbed.h" |
4180_1 | 2:75727e89a717 | 4 | #include "uLCD_4DGL.h" |
jli26 | 10:c19a945d9dca | 5 | #include "LSM9DS1.h" |
jli26 | 10:c19a945d9dca | 6 | #include <math.h> |
jli26 | 10:c19a945d9dca | 7 | #include "PinDetect.h" |
jli26 | 10:c19a945d9dca | 8 | #include "SDFileSystem.h" |
jli26 | 10:c19a945d9dca | 9 | #include "wave_player.h" |
4180_1 | 0:cfcf73272647 | 10 | |
jli26 | 10:c19a945d9dca | 11 | |
jli26 | 10:c19a945d9dca | 12 | |
jli26 | 10:c19a945d9dca | 13 | #define PI 3.14159 |
jli26 | 10:c19a945d9dca | 14 | // Earth's magnetic field varies by location. Add or subtract |
jli26 | 10:c19a945d9dca | 15 | // a declination to get a more accurate heading. Calculate |
jli26 | 10:c19a945d9dca | 16 | // your's here: |
jli26 | 10:c19a945d9dca | 17 | // http://www.ngdc.noaa.gov/geomag-web/#declination |
jli26 | 10:c19a945d9dca | 18 | #define DECLINATION -4.94 // Declination (degrees) in Atlanta,GA. |
4180_1 | 0:cfcf73272647 | 19 | |
jli26 | 10:c19a945d9dca | 20 | uLCD_4DGL uLCD(p9,p10,p30); // serial tx, serial rx, reset pin; |
jli26 | 10:c19a945d9dca | 21 | DigitalOut myled(LED1); |
jli26 | 10:c19a945d9dca | 22 | Serial pc(USBTX, USBRX); |
jli26 | 10:c19a945d9dca | 23 | Serial device(p28, p27); |
jli26 | 10:c19a945d9dca | 24 | |
jli26 | 10:c19a945d9dca | 25 | PinDetect trigger(p21); |
jli26 | 10:c19a945d9dca | 26 | |
jli26 | 10:c19a945d9dca | 27 | //speaker |
jli26 | 10:c19a945d9dca | 28 | SDFileSystem sd(p5, p6, p7, p8, "sd"); //SD card |
jli26 | 10:c19a945d9dca | 29 | AnalogOut DACout(p18); |
jli26 | 10:c19a945d9dca | 30 | wave_player waver(&DACout); |
jli26 | 10:c19a945d9dca | 31 | // |
jli26 | 10:c19a945d9dca | 32 | |
jli26 | 10:c19a945d9dca | 33 | |
jli26 | 10:c19a945d9dca | 34 | |
4180_1 | 7:7bd7397ab89f | 35 | |
jli26 | 10:c19a945d9dca | 36 | //duck |
jli26 | 10:c19a945d9dca | 37 | int duckWidth = 20; |
jli26 | 10:c19a945d9dca | 38 | int duckHeight = 20; |
jli26 | 10:c19a945d9dca | 39 | int duckx = 64; |
jli26 | 10:c19a945d9dca | 40 | int ducky = 40; |
jli26 | 10:c19a945d9dca | 41 | int duckDY = 3; |
jli26 | 10:c19a945d9dca | 42 | int duckDX = 3; |
jli26 | 10:c19a945d9dca | 43 | int duckMaxSpeed = 10; |
jli26 | 10:c19a945d9dca | 44 | int duckMinSpeed = 4; |
jli26 | 10:c19a945d9dca | 45 | // |
jli26 | 10:c19a945d9dca | 46 | |
jli26 | 10:c19a945d9dca | 47 | //aimer |
jli26 | 10:c19a945d9dca | 48 | int aimerWidth = 20; |
jli26 | 10:c19a945d9dca | 49 | int aimerHeight = 20; |
jli26 | 10:c19a945d9dca | 50 | int aimerx = 64; |
jli26 | 10:c19a945d9dca | 51 | int aimery = 64; |
jli26 | 10:c19a945d9dca | 52 | // |
jli26 | 10:c19a945d9dca | 53 | |
jli26 | 10:c19a945d9dca | 54 | //trigger |
jli26 | 10:c19a945d9dca | 55 | bool hit = false; |
jli26 | 10:c19a945d9dca | 56 | |
jli26 | 10:c19a945d9dca | 57 | //duckreset |
jli26 | 10:c19a945d9dca | 58 | bool duckReset = false; |
jli26 | 10:c19a945d9dca | 59 | |
jli26 | 10:c19a945d9dca | 60 | //scoreboard |
jli26 | 10:c19a945d9dca | 61 | int scoreCount = 0; |
jli26 | 10:c19a945d9dca | 62 | bool scoreChange = false; |
jli26 | 10:c19a945d9dca | 63 | |
jli26 | 10:c19a945d9dca | 64 | // countinghits.wav |
jli26 | 10:c19a945d9dca | 65 | // duck-hunt-intro.wav |
jli26 | 10:c19a945d9dca | 66 | |
jli26 | 10:c19a945d9dca | 67 | |
jli26 | 10:c19a945d9dca | 68 | void trigger_hit_callback() { |
jli26 | 10:c19a945d9dca | 69 | device.putc(pc.printf("aimerx: %d, aimery: %d \n\r",aimerx,aimery)); |
jli26 | 10:c19a945d9dca | 70 | device.putc(pc.printf("duckx: %d, ducky: %d \n\r",duckx,ducky)); |
jli26 | 10:c19a945d9dca | 71 | device.putc(pc.printf("duckx: %d, ducky: %d \n\r",duckx + duckWidth,ducky + duckHeight)); |
jli26 | 10:c19a945d9dca | 72 | hit = true; |
jli26 | 10:c19a945d9dca | 73 | if (aimery >= duckx && aimery <= (duckx + duckWidth)){ |
jli26 | 10:c19a945d9dca | 74 | if (aimerx >= ducky && aimerx <= (ducky + duckHeight)){ |
jli26 | 10:c19a945d9dca | 75 | duckReset = true; |
jli26 | 10:c19a945d9dca | 76 | scoreCount = scoreCount + 1; |
jli26 | 10:c19a945d9dca | 77 | scoreChange = true; |
jli26 | 10:c19a945d9dca | 78 | device.putc(pc.printf("HIT \n")); |
4180_1 | 3:454d1f4c8fd7 | 79 | } |
4180_1 | 3:454d1f4c8fd7 | 80 | } |
jli26 | 10:c19a945d9dca | 81 | } |
jli26 | 10:c19a945d9dca | 82 | |
jli26 | 10:c19a945d9dca | 83 | int calcDuckXPos() |
jli26 | 10:c19a945d9dca | 84 | { |
jli26 | 10:c19a945d9dca | 85 | int newX = duckx + duckDX; |
jli26 | 10:c19a945d9dca | 86 | if (newX > 128 - duckWidth){ |
jli26 | 10:c19a945d9dca | 87 | duckDX = rand()%(duckMaxSpeed-duckMinSpeed + 1) + duckMinSpeed; |
jli26 | 10:c19a945d9dca | 88 | duckDX = -duckDX; |
jli26 | 10:c19a945d9dca | 89 | newX = duckx + duckDX; |
jli26 | 10:c19a945d9dca | 90 | } |
jli26 | 10:c19a945d9dca | 91 | if (newX < 0){ |
jli26 | 10:c19a945d9dca | 92 | duckDX = rand()%(duckMaxSpeed-duckMinSpeed + 1) + duckMinSpeed; |
jli26 | 10:c19a945d9dca | 93 | newX = duckx + duckDX; |
jli26 | 10:c19a945d9dca | 94 | } |
jli26 | 10:c19a945d9dca | 95 | return newX; |
jli26 | 10:c19a945d9dca | 96 | } |
jli26 | 10:c19a945d9dca | 97 | |
jli26 | 10:c19a945d9dca | 98 | |
jli26 | 10:c19a945d9dca | 99 | int calcDuckYPos() |
jli26 | 10:c19a945d9dca | 100 | { |
jli26 | 10:c19a945d9dca | 101 | |
jli26 | 10:c19a945d9dca | 102 | int newY = ducky + duckDY; |
jli26 | 10:c19a945d9dca | 103 | if (newY > 128 - duckHeight){ |
jli26 | 10:c19a945d9dca | 104 | duckDY = rand()%(duckMaxSpeed-duckMinSpeed + 1) + duckMinSpeed; |
jli26 | 10:c19a945d9dca | 105 | duckDY = -duckDY; |
jli26 | 10:c19a945d9dca | 106 | newY = ducky + duckDY; |
4180_1 | 7:7bd7397ab89f | 107 | } |
jli26 | 10:c19a945d9dca | 108 | if (newY < 25){ |
jli26 | 10:c19a945d9dca | 109 | duckDY = rand()%(duckMaxSpeed-duckMinSpeed + 1) + duckMinSpeed; |
jli26 | 10:c19a945d9dca | 110 | newY = ducky + duckDY; |
4180_1 | 5:a1ef40ff0f78 | 111 | } |
jli26 | 10:c19a945d9dca | 112 | return newY; |
jli26 | 10:c19a945d9dca | 113 | } |
jli26 | 10:c19a945d9dca | 114 | |
jli26 | 10:c19a945d9dca | 115 | |
jli26 | 10:c19a945d9dca | 116 | void drawDuck() |
jli26 | 10:c19a945d9dca | 117 | { |
jli26 | 10:c19a945d9dca | 118 | uLCD.display_image(duckx,ducky); |
jli26 | 10:c19a945d9dca | 119 | |
jli26 | 10:c19a945d9dca | 120 | } |
jli26 | 10:c19a945d9dca | 121 | |
jli26 | 10:c19a945d9dca | 122 | void eraseDuck() |
jli26 | 10:c19a945d9dca | 123 | { |
jli26 | 10:c19a945d9dca | 124 | uLCD.filled_rectangle(duckx, ducky, duckx + duckWidth, ducky + duckHeight, BLACK); |
jli26 | 10:c19a945d9dca | 125 | } |
jli26 | 10:c19a945d9dca | 126 | |
jli26 | 10:c19a945d9dca | 127 | void drawAimer() |
jli26 | 10:c19a945d9dca | 128 | { |
jli26 | 10:c19a945d9dca | 129 | uLCD.circle(aimery, aimerx, (aimerWidth/2) - 5, WHITE); |
jli26 | 10:c19a945d9dca | 130 | uLCD.line(aimery - aimerHeight/2, aimerx, aimery + aimerHeight/2, aimerx, WHITE); |
jli26 | 10:c19a945d9dca | 131 | uLCD.line(aimery, aimerx - aimerWidth/2, aimery,aimerx + aimerHeight/2, WHITE); |
jli26 | 10:c19a945d9dca | 132 | } |
jli26 | 10:c19a945d9dca | 133 | |
jli26 | 10:c19a945d9dca | 134 | void eraseAimer() |
jli26 | 10:c19a945d9dca | 135 | { |
jli26 | 10:c19a945d9dca | 136 | uLCD.circle(aimery, aimerx, (aimerWidth/2) - 5, BLACK); |
jli26 | 10:c19a945d9dca | 137 | uLCD.line(aimery - aimerHeight/2, aimerx, aimery + aimerHeight/2, aimerx, BLACK); |
jli26 | 10:c19a945d9dca | 138 | uLCD.line(aimery, aimerx - aimerWidth/2, aimery,aimerx + aimerHeight/2, BLACK); |
4180_1 | 6:f752accd632c | 139 | } |
4180_1 | 7:7bd7397ab89f | 140 | |
4180_1 | 7:7bd7397ab89f | 141 | |
4180_1 | 8:31e63caf37e2 | 142 | |
jli26 | 10:c19a945d9dca | 143 | int main() |
jli26 | 10:c19a945d9dca | 144 | { |
jli26 | 10:c19a945d9dca | 145 | uLCD.media_init(); |
jli26 | 10:c19a945d9dca | 146 | uLCD.set_sector_address(0x0001, 0x2B71); |
jli26 | 10:c19a945d9dca | 147 | //LSM9DS1 IMU(p9, p10, 0x6B, 0x1E); |
jli26 | 10:c19a945d9dca | 148 | |
jli26 | 10:c19a945d9dca | 149 | LSM9DS1 IMU(p28, p27, 0xD6, 0x3C); |
jli26 | 10:c19a945d9dca | 150 | IMU.begin(); |
jli26 | 10:c19a945d9dca | 151 | |
jli26 | 10:c19a945d9dca | 152 | if (!IMU.begin()) { |
jli26 | 10:c19a945d9dca | 153 | pc.printf("Failed to communicate with LSM9DS1.\n"); |
jli26 | 10:c19a945d9dca | 154 | } |
jli26 | 10:c19a945d9dca | 155 | |
jli26 | 10:c19a945d9dca | 156 | IMU.calibrate(1); |
jli26 | 10:c19a945d9dca | 157 | // IMU.calibrateMag(0); |
jli26 | 10:c19a945d9dca | 158 | |
jli26 | 10:c19a945d9dca | 159 | |
jli26 | 10:c19a945d9dca | 160 | |
jli26 | 10:c19a945d9dca | 161 | |
jli26 | 10:c19a945d9dca | 162 | //demo graphics commands |
jli26 | 10:c19a945d9dca | 163 | uLCD.background_color(BLACK); |
jli26 | 10:c19a945d9dca | 164 | uLCD.cls(); |
jli26 | 10:c19a945d9dca | 165 | trigger.mode(PullUp); |
jli26 | 10:c19a945d9dca | 166 | wait(.001); |
jli26 | 10:c19a945d9dca | 167 | trigger.attach_deasserted(&trigger_hit_callback); |
jli26 | 10:c19a945d9dca | 168 | trigger.setSampleFrequency(); |
jli26 | 10:c19a945d9dca | 169 | |
jli26 | 10:c19a945d9dca | 170 | float mult = 160.0; |
jli26 | 10:c19a945d9dca | 171 | float rawx = 0; |
jli26 | 10:c19a945d9dca | 172 | float rawy = 0; |
jli26 | 10:c19a945d9dca | 173 | |
jli26 | 10:c19a945d9dca | 174 | |
jli26 | 10:c19a945d9dca | 175 | |
jli26 | 10:c19a945d9dca | 176 | int duckResetCounter = 25; |
jli26 | 10:c19a945d9dca | 177 | |
jli26 | 10:c19a945d9dca | 178 | uLCD.set_font(FONT_7X8); |
jli26 | 10:c19a945d9dca | 179 | uLCD.text_width(1); |
jli26 | 10:c19a945d9dca | 180 | uLCD.text_height(1); |
jli26 | 10:c19a945d9dca | 181 | uLCD.locate(1,1); |
jli26 | 10:c19a945d9dca | 182 | uLCD.printf("Score: %d",scoreCount); |
jli26 | 10:c19a945d9dca | 183 | |
jli26 | 10:c19a945d9dca | 184 | while(1){ |
jli26 | 10:c19a945d9dca | 185 | |
jli26 | 10:c19a945d9dca | 186 | drawAimer(); |
jli26 | 10:c19a945d9dca | 187 | eraseAimer(); |
jli26 | 10:c19a945d9dca | 188 | |
jli26 | 10:c19a945d9dca | 189 | if (!duckReset){ |
jli26 | 10:c19a945d9dca | 190 | drawDuck(); |
jli26 | 10:c19a945d9dca | 191 | eraseDuck(); |
jli26 | 10:c19a945d9dca | 192 | } else { |
jli26 | 10:c19a945d9dca | 193 | duckResetCounter = duckResetCounter - 1; |
jli26 | 10:c19a945d9dca | 194 | if (duckResetCounter <= 0){ |
jli26 | 10:c19a945d9dca | 195 | duckResetCounter = 50; |
jli26 | 10:c19a945d9dca | 196 | duckReset = false; |
jli26 | 10:c19a945d9dca | 197 | } |
jli26 | 10:c19a945d9dca | 198 | } |
jli26 | 10:c19a945d9dca | 199 | |
jli26 | 10:c19a945d9dca | 200 | |
jli26 | 10:c19a945d9dca | 201 | |
jli26 | 10:c19a945d9dca | 202 | // if (fire){ |
jli26 | 10:c19a945d9dca | 203 | // fire = false; |
jli26 | 10:c19a945d9dca | 204 | // if (aimerx >= duckx && aimerx <= (duckx + duckWidth)){ |
jli26 | 10:c19a945d9dca | 205 | // device.putc(pc.printf("X Good")); |
jli26 | 10:c19a945d9dca | 206 | // if (aimery >= ducky && aimery <= (ducky + duckHeight)){ |
jli26 | 10:c19a945d9dca | 207 | // led = !led; |
jli26 | 10:c19a945d9dca | 208 | // device.putc(pc.printf("HIT")); |
jli26 | 10:c19a945d9dca | 209 | // } |
jli26 | 10:c19a945d9dca | 210 | // } |
jli26 | 10:c19a945d9dca | 211 | // } |
jli26 | 10:c19a945d9dca | 212 | |
jli26 | 10:c19a945d9dca | 213 | while(!IMU.accelAvailable()); |
jli26 | 10:c19a945d9dca | 214 | IMU.readAccel(); |
jli26 | 10:c19a945d9dca | 215 | while(!IMU.gyroAvailable()); |
jli26 | 10:c19a945d9dca | 216 | IMU.readGyro(); |
jli26 | 10:c19a945d9dca | 217 | |
jli26 | 10:c19a945d9dca | 218 | rawx = IMU.calcAccel(IMU.ax); |
jli26 | 10:c19a945d9dca | 219 | rawy = IMU.calcAccel(IMU.ay); |
jli26 | 10:c19a945d9dca | 220 | // device.putc(pc.printf("ax: %f, ay: %f \n\r",rawx,rawy)); |
jli26 | 10:c19a945d9dca | 221 | |
jli26 | 10:c19a945d9dca | 222 | |
jli26 | 10:c19a945d9dca | 223 | aimerx = 64 + int(rawx * mult); |
jli26 | 10:c19a945d9dca | 224 | |
jli26 | 10:c19a945d9dca | 225 | if (aimerx < 25){ |
jli26 | 10:c19a945d9dca | 226 | aimerx = 25; |
jli26 | 10:c19a945d9dca | 227 | } |
jli26 | 10:c19a945d9dca | 228 | aimery = 64 - int(rawy * mult); |
jli26 | 10:c19a945d9dca | 229 | |
jli26 | 10:c19a945d9dca | 230 | |
jli26 | 10:c19a945d9dca | 231 | duckx = calcDuckXPos(); |
jli26 | 10:c19a945d9dca | 232 | ducky = calcDuckYPos(); |
jli26 | 10:c19a945d9dca | 233 | |
jli26 | 10:c19a945d9dca | 234 | if (hit){ |
jli26 | 10:c19a945d9dca | 235 | hit = false; |
jli26 | 10:c19a945d9dca | 236 | FILE *wave_file=fopen("/sd/gunsound.wav","r"); |
jli26 | 10:c19a945d9dca | 237 | waver.play(wave_file); |
jli26 | 10:c19a945d9dca | 238 | fclose(wave_file); |
jli26 | 10:c19a945d9dca | 239 | |
jli26 | 10:c19a945d9dca | 240 | } |
jli26 | 10:c19a945d9dca | 241 | |
jli26 | 10:c19a945d9dca | 242 | if (scoreChange){ |
jli26 | 10:c19a945d9dca | 243 | scoreChange = false; |
jli26 | 10:c19a945d9dca | 244 | uLCD.set_font(FONT_7X8); |
jli26 | 10:c19a945d9dca | 245 | uLCD.text_width(1); |
jli26 | 10:c19a945d9dca | 246 | uLCD.text_height(1); |
jli26 | 10:c19a945d9dca | 247 | uLCD.locate(1,1); |
jli26 | 10:c19a945d9dca | 248 | uLCD.printf("Score: %d",scoreCount); |
jli26 | 10:c19a945d9dca | 249 | } |
jli26 | 10:c19a945d9dca | 250 | |
jli26 | 10:c19a945d9dca | 251 | } |
jli26 | 10:c19a945d9dca | 252 | |
jli26 | 10:c19a945d9dca | 253 | } |
jli26 | 10:c19a945d9dca | 254 | |
jli26 | 10:c19a945d9dca | 255 | |
jli26 | 10:c19a945d9dca | 256 |