DuckHunt game using IMU sensor and uLCD display

Dependencies:   4DGL-uLCD-SE LSM9DS1_Library_cal SDFileSystem mbed wave_player

Fork of uLCD144G2_demo by jim hamblen

Files at this revision

API Documentation at this revision

Comitter:
jli26
Date:
Mon Oct 31 21:20:17 2016 +0000
Parent:
9:f20983c914aa
Commit message:
Duck Hunt Game

Changed in this revision

LSM9DS1_Library_cal.lib Show annotated file Show diff for this revision Revisions of this file
SDFileSystem.lib Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
wave_player.lib Show annotated file Show diff for this revision Revisions of this file
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