DuckHunt game using IMU sensor and uLCD display
Dependencies: 4DGL-uLCD-SE LSM9DS1_Library_cal SDFileSystem mbed wave_player
Fork of uLCD144G2_demo by
Revision 10:c19a945d9dca, committed 2016-10-31
- Comitter:
- jli26
- Date:
- Mon Oct 31 21:20:17 2016 +0000
- Parent:
- 9:f20983c914aa
- Commit message:
- Duck Hunt Game
Changed in this revision
diff -r f20983c914aa -r c19a945d9dca LSM9DS1_Library_cal.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/LSM9DS1_Library_cal.lib Mon Oct 31 21:20:17 2016 +0000 @@ -0,0 +1,1 @@ +https://developer.mbed.org/users/4180_1/code/LSM9DS1_Library_cal/#36abf8e18ade
diff -r f20983c914aa -r c19a945d9dca SDFileSystem.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SDFileSystem.lib Mon Oct 31 21:20:17 2016 +0000 @@ -0,0 +1,1 @@ +https://developer.mbed.org/users/mbed_official/code/SDFileSystem/#8db0d3b02cec
diff -r f20983c914aa -r c19a945d9dca main.cpp --- a/main.cpp Wed Oct 28 15:06:56 2015 +0000 +++ b/main.cpp Mon Oct 31 21:20:17 2016 +0000 @@ -2,170 +2,255 @@ // #include "mbed.h" #include "uLCD_4DGL.h" +#include "LSM9DS1.h" +#include <math.h> +#include "PinDetect.h" +#include "SDFileSystem.h" +#include "wave_player.h" -uLCD_4DGL uLCD(p9,p10,p11); // serial tx, serial rx, reset pin; + + +#define PI 3.14159 +// Earth's magnetic field varies by location. Add or subtract +// a declination to get a more accurate heading. Calculate +// your's here: +// http://www.ngdc.noaa.gov/geomag-web/#declination +#define DECLINATION -4.94 // Declination (degrees) in Atlanta,GA. -int main() -{ - // basic printf demo = 16 by 18 characters on screen - uLCD.printf("\nHello uLCD World\n"); //Default Green on black text - uLCD.printf("\n Starting Demo..."); - uLCD.text_width(4); //4X size text - uLCD.text_height(4); - uLCD.color(RED); - for (int i=10; i>=0; --i) { - uLCD.locate(1,2); - uLCD.printf("%2D",i); - wait(.5); - } - uLCD.cls(); - uLCD.printf("Change baudrate......"); - uLCD.baudrate(3000000); //jack up baud rate to max for fast display - //if demo hangs here - try lower baud rates - // - // printf text only full screen mode demo - uLCD.background_color(BLUE); - uLCD.cls(); - uLCD.locate(0,0); - uLCD.color(WHITE); - uLCD.textbackground_color(BLUE); - uLCD.set_font(FONT_7X8); - uLCD.text_mode(OPAQUE); - int i=0; - while(i<64) { - if(i%16==0) uLCD.cls(); - uLCD.printf("TxtLine %2D Page %D\n",i%16,i/16 ); - i++; //16 lines with 18 charaters per line - } - wait(0.5); - //demo graphics commands - uLCD.background_color(BLACK); - uLCD.cls(); - uLCD.background_color(DGREY); - uLCD.filled_circle(60, 50, 30, 0xFF00FF); - uLCD.triangle(120, 100, 40, 40, 10, 100, 0x0000FF); - uLCD.line(0, 0, 80, 60, 0xFF0000); - uLCD.filled_rectangle(50, 50, 100, 90, 0x00FF00); - uLCD.pixel(60, 60, BLACK); - uLCD.read_pixel(120, 70); - uLCD.circle(120, 60, 10, BLACK); - uLCD.set_font(FONT_7X8); - uLCD.text_mode(TRANSPARENT); - uLCD.text_bold(ON); - uLCD.text_char('B', 9, 8, BLACK); - uLCD.text_char('I',10, 8, BLACK); - uLCD.text_char('G',11, 8, BLACK); - uLCD.text_italic(ON); - uLCD.text_string("This is a test of string", 1, 4, FONT_7X8, WHITE); - wait(2); +uLCD_4DGL uLCD(p9,p10,p30); // serial tx, serial rx, reset pin; +DigitalOut myled(LED1); +Serial pc(USBTX, USBRX); +Serial device(p28, p27); + +PinDetect trigger(p21); + +//speaker +SDFileSystem sd(p5, p6, p7, p8, "sd"); //SD card +AnalogOut DACout(p18); +wave_player waver(&DACout); +// + + + -//Bouncing Ball Demo - float fx=50.0,fy=21.0,vx=1.0,vy=0.4; - int x=50,y=21,radius=4; - uLCD.background_color(BLACK); - uLCD.cls(); - //draw walls - uLCD.line(0, 0, 127, 0, WHITE); - uLCD.line(127, 0, 127, 127, WHITE); - uLCD.line(127, 127, 0, 127, WHITE); - uLCD.line(0, 127, 0, 0, WHITE); - for (int i=0; i<1500; i++) { - //draw ball - uLCD.filled_circle(x, y, radius, RED); - //bounce off edge walls and slow down a bit? - if ((x<=radius+1) || (x>=126-radius)) vx = -.90*vx; - if ((y<=radius+1) || (y>=126-radius)) vy = -.90*vy; - //erase old ball location - uLCD.filled_circle(x, y, radius, BLACK); - //move ball - fx=fx+vx; - fy=fy+vy; - x=(int)fx; - y=(int)fy; - } - wait(0.5); -//draw an image pixel by pixel - int pixelcolors[50][50]; - uLCD.background_color(BLACK); - uLCD.cls(); -//compute Mandelbrot set image for display -//image size in pixels - const unsigned ImageHeight=128; - const unsigned ImageWidth=128; - //"c" region to display - double MinRe = -0.75104; - double MaxRe = -0.7408; - double MinIm = 0.10511; - double MaxIm = MinIm+(MaxRe-MinRe)*ImageHeight/ImageWidth; - double Re_factor = (MaxRe-MinRe)/(ImageWidth-1); - double Im_factor = (MaxIm-MinIm)/(ImageHeight-1); - unsigned MaxIterations = 2048; - for(unsigned y=0; y<ImageHeight; ++y) { - double c_im = MaxIm - y*Im_factor; - for(unsigned x=0; x<ImageWidth; ++x) { - double c_re = MinRe + x*Re_factor; - double Z_re = c_re, Z_im = c_im; - int niterations=0; - for(unsigned n=0; n<MaxIterations; ++n) { - double Z_re2 = Z_re*Z_re, Z_im2 = Z_im*Z_im; - if(Z_re2 + Z_im2 > 4) { - niterations = n; - break; - } - Z_im = 2*Z_re*Z_im + c_im; - Z_re = Z_re2 - Z_im2 + c_re; - } - if (niterations!=(MaxIterations-1)) - uLCD.pixel(x,y,((niterations & 0xF00)<<12)+((niterations & 0xF0)<<8)+((niterations & 0x0F)<<4) ); +//duck +int duckWidth = 20; +int duckHeight = 20; +int duckx = 64; +int ducky = 40; +int duckDY = 3; +int duckDX = 3; +int duckMaxSpeed = 10; +int duckMinSpeed = 4; +// + +//aimer +int aimerWidth = 20; +int aimerHeight = 20; +int aimerx = 64; +int aimery = 64; +// + +//trigger +bool hit = false; + +//duckreset +bool duckReset = false; + +//scoreboard +int scoreCount = 0; +bool scoreChange = false; + +// countinghits.wav +// duck-hunt-intro.wav + + +void trigger_hit_callback() { + device.putc(pc.printf("aimerx: %d, aimery: %d \n\r",aimerx,aimery)); + device.putc(pc.printf("duckx: %d, ducky: %d \n\r",duckx,ducky)); + device.putc(pc.printf("duckx: %d, ducky: %d \n\r",duckx + duckWidth,ducky + duckHeight)); + hit = true; + if (aimery >= duckx && aimery <= (duckx + duckWidth)){ + if (aimerx >= ducky && aimerx <= (ducky + duckHeight)){ + duckReset = true; + scoreCount = scoreCount + 1; + scoreChange = true; + device.putc(pc.printf("HIT \n")); } } - wait(5); -// PLASMA wave BLIT animation -//draw an image using BLIT (Block Image Transfer) fastest way to transfer pixel data - uLCD.cls(); - int num_cols=50; - int num_rows=50; - int frame=0; - double a,b,c=0.0; - while(frame<75) { - for (int k=0; k<num_cols; k++) { - b= (1+sin(3.14159*k*0.75/(num_cols-1.0)+c))*0.5; - for (int i=0; i<num_rows; i++) { - a= (1+sin(3.14159*i*0.75/(num_rows-1.0)+c))*0.5; - // a and b will be a sine wave output between 0 and 1 - // sine wave was scaled for nice effect across array - // uses a and b to compute pixel colors based on rol and col location in array - // also keeps colors at the same brightness level - if ((a+b) <.667) - pixelcolors[i][k] = (255-(int(254.0*((a+b)/0.667)))<<16) | (int(254.0*((a+b)/0.667))<<8) | 0; - else if ((a+b)<1.333) - pixelcolors[i][k] = (0 <<16) | (255-(int (254.0*((a+b-0.667)/0.667)))<<8) | int(254.0*((a+b-0.667)/0.667)); - else - pixelcolors[i][k] = (int(255*((a+b-1.333)/0.667))<<16) | (0<<8) | (255-(int (254.0*((a+b-1.333)/0.667)))); - } - } - uLCD.BLIT(39, 39, 50, 50, &pixelcolors[0][0]); - c = c + 0.0314159*3.0; - if (c > 6.2831) c = 0.0; - frame++; +} + +int calcDuckXPos() +{ + int newX = duckx + duckDX; + if (newX > 128 - duckWidth){ + duckDX = rand()%(duckMaxSpeed-duckMinSpeed + 1) + duckMinSpeed; + duckDX = -duckDX; + newX = duckx + duckDX; + } + if (newX < 0){ + duckDX = rand()%(duckMaxSpeed-duckMinSpeed + 1) + duckMinSpeed; + newX = duckx + duckDX; + } + return newX; +} + + +int calcDuckYPos() +{ + + int newY = ducky + duckDY; + if (newY > 128 - duckHeight){ + duckDY = rand()%(duckMaxSpeed-duckMinSpeed + 1) + duckMinSpeed; + duckDY = -duckDY; + newY = ducky + duckDY; } - //Load Image Demo - uLCD.cls(); - //SD card needed with image and video files for last two demos - uLCD.cls(); - uLCD.media_init(); - uLCD.printf("\n\nAn SD card is needed for image and video data"); - uLCD.set_sector_address(0x001D, 0x4C01); - uLCD.display_image(0,0); - wait(10); - //Play video demo - while(1) { - uLCD.cls(); - uLCD.media_init(); - uLCD.set_sector_address(0x001D, 0x4C42); - uLCD.display_video(0,0); + if (newY < 25){ + duckDY = rand()%(duckMaxSpeed-duckMinSpeed + 1) + duckMinSpeed; + newY = ducky + duckDY; } + return newY; +} + + +void drawDuck() +{ + uLCD.display_image(duckx,ducky); + +} + +void eraseDuck() +{ + uLCD.filled_rectangle(duckx, ducky, duckx + duckWidth, ducky + duckHeight, BLACK); +} + +void drawAimer() +{ + uLCD.circle(aimery, aimerx, (aimerWidth/2) - 5, WHITE); + uLCD.line(aimery - aimerHeight/2, aimerx, aimery + aimerHeight/2, aimerx, WHITE); + uLCD.line(aimery, aimerx - aimerWidth/2, aimery,aimerx + aimerHeight/2, WHITE); +} + +void eraseAimer() +{ + uLCD.circle(aimery, aimerx, (aimerWidth/2) - 5, BLACK); + uLCD.line(aimery - aimerHeight/2, aimerx, aimery + aimerHeight/2, aimerx, BLACK); + uLCD.line(aimery, aimerx - aimerWidth/2, aimery,aimerx + aimerHeight/2, BLACK); } +int main() +{ + uLCD.media_init(); + uLCD.set_sector_address(0x0001, 0x2B71); + //LSM9DS1 IMU(p9, p10, 0x6B, 0x1E); + + LSM9DS1 IMU(p28, p27, 0xD6, 0x3C); + IMU.begin(); + + if (!IMU.begin()) { + pc.printf("Failed to communicate with LSM9DS1.\n"); + } + + IMU.calibrate(1); +// IMU.calibrateMag(0); + + + + + //demo graphics commands + uLCD.background_color(BLACK); + uLCD.cls(); + trigger.mode(PullUp); + wait(.001); + trigger.attach_deasserted(&trigger_hit_callback); + trigger.setSampleFrequency(); + + float mult = 160.0; + float rawx = 0; + float rawy = 0; + + + + int duckResetCounter = 25; + + uLCD.set_font(FONT_7X8); + uLCD.text_width(1); + uLCD.text_height(1); + uLCD.locate(1,1); + uLCD.printf("Score: %d",scoreCount); + + while(1){ + + drawAimer(); + eraseAimer(); + + if (!duckReset){ + drawDuck(); + eraseDuck(); + } else { + duckResetCounter = duckResetCounter - 1; + if (duckResetCounter <= 0){ + duckResetCounter = 50; + duckReset = false; + } + } + + + +// if (fire){ +// fire = false; +// if (aimerx >= duckx && aimerx <= (duckx + duckWidth)){ +// device.putc(pc.printf("X Good")); +// if (aimery >= ducky && aimery <= (ducky + duckHeight)){ +// led = !led; +// device.putc(pc.printf("HIT")); +// } +// } +// } + + while(!IMU.accelAvailable()); + IMU.readAccel(); + while(!IMU.gyroAvailable()); + IMU.readGyro(); + + rawx = IMU.calcAccel(IMU.ax); + rawy = IMU.calcAccel(IMU.ay); +// device.putc(pc.printf("ax: %f, ay: %f \n\r",rawx,rawy)); + + + aimerx = 64 + int(rawx * mult); + + if (aimerx < 25){ + aimerx = 25; + } + aimery = 64 - int(rawy * mult); + + + duckx = calcDuckXPos(); + ducky = calcDuckYPos(); + + if (hit){ + hit = false; + FILE *wave_file=fopen("/sd/gunsound.wav","r"); + waver.play(wave_file); + fclose(wave_file); + + } + + if (scoreChange){ + scoreChange = false; + uLCD.set_font(FONT_7X8); + uLCD.text_width(1); + uLCD.text_height(1); + uLCD.locate(1,1); + uLCD.printf("Score: %d",scoreCount); + } + + } + +} + + +
diff -r f20983c914aa -r c19a945d9dca mbed.bld --- a/mbed.bld Wed Oct 28 15:06:56 2015 +0000 +++ b/mbed.bld Mon Oct 31 21:20:17 2016 +0000 @@ -1,1 +1,1 @@ -http://mbed.org/users/mbed_official/code/mbed/builds/34e6b704fe68 \ No newline at end of file +http://mbed.org/users/mbed_official/code/mbed/builds/9bcdf88f62b0 \ No newline at end of file
diff -r f20983c914aa -r c19a945d9dca wave_player.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wave_player.lib Mon Oct 31 21:20:17 2016 +0000 @@ -0,0 +1,1 @@ +https://developer.mbed.org/users/sravet/code/wave_player/#acc3e18e77ad