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

main.cpp

Committer:
jli26
Date:
2016-10-31
Revision:
10:c19a945d9dca
Parent:
8:31e63caf37e2

File content as of revision 10:c19a945d9dca:

// uLCD-144-G2 demo program for uLCD-4GL LCD driver library
//
#include "mbed.h"
#include "uLCD_4DGL.h"
#include "LSM9DS1.h"
#include <math.h>
#include "PinDetect.h"
#include "SDFileSystem.h"
#include "wave_player.h"



#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.

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);
//




//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"));
        }
    }
}

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;
    }
    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);
        }

    }

}