
A note hitting game for the mbed LPC 1768. User uses a joystick to hit notes as they come down the screen in 3 different lanes.
Dependencies: 4DGL-uLCD-SE SDFileSystem mbed-rtos mbed wave_player
Revision 1:94b1ec213686, committed 2016-03-17
- Comitter:
- jmpin
- Date:
- Thu Mar 17 21:12:59 2016 +0000
- Parent:
- 0:1340139c5758
- Commit message:
- Game is pretty much finished, minus the sound coming from .wav files from the SD card
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Nav_Switch.cpp Thu Mar 17 21:12:59 2016 +0000 @@ -0,0 +1,38 @@ +#include "mbed.h" +#include "Nav_Switch.h" + + +Nav_Switch::Nav_Switch (PinName up,PinName down,PinName left,PinName right,PinName fire): + _pins(up, down, left, right, fire) +{ + _pins.mode(PullUp); //needed if pullups not on board or a bare nav switch is used - delete otherwise + wait(0.001); //delays just a bit for pullups to pull inputs high +} +inline bool Nav_Switch::up() +{ + return !(_pins[0]); +} +inline bool Nav_Switch::down() +{ + return !(_pins[1]); +} +inline bool Nav_Switch::left() +{ + return !(_pins[2]); +} +inline bool Nav_Switch::right() +{ + return !(_pins[3]); +} +bool Nav_Switch::fire() +{ + return !(_pins[4]); +} +int Nav_Switch::read() +{ + return _pins.read(); +} +Nav_Switch::operator int() +{ + return _pins.read(); +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Nav_Switch.h Thu Mar 17 21:12:59 2016 +0000 @@ -0,0 +1,23 @@ +#include "mbed.h" + +class Nav_Switch +{ + public: + Nav_Switch(PinName up,PinName down,PinName left,PinName right,PinName fire); + int read(); +//boolean functions to test each switch + bool up(); + bool down(); + bool left(); + bool right(); + bool fire(); +//automatic read on RHS + operator int (); +//index to any switch array style + bool operator[](int index) { + return _pins[index]; + }; +private: + BusIn _pins; + +}; \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SongPlayer.h Thu Mar 17 21:12:59 2016 +0000 @@ -0,0 +1,41 @@ +#include "mbed.h" +// new class to play a note on Speaker based on PwmOut class +class SongPlayer +{ +public: + SongPlayer(PinName pin) : _pin(pin) { +// _pin(pin) means pass pin to the constructor + } +// class method to play a note based on PwmOut class + void PlaySong(float frequency[], float duration[], float volume=1.0) { + vol = volume; + notecount = 0; + _pin.period(1.0/frequency[notecount]); + _pin = volume/2.0; + noteduration.attach(this,&SongPlayer::nextnote, duration[notecount]); + // setup timer to interrupt for next note to play + frequencyptr = frequency; + durationptr = duration; + //returns after first note starts to play + } + void nextnote(); +private: + Timeout noteduration; + PwmOut _pin; + int notecount; + float vol; + float * frequencyptr; + float * durationptr; +}; +//Interrupt Routine to play next note +void SongPlayer::nextnote() +{ + _pin = 0.0; + notecount++; //setup next note in song + if (durationptr[notecount]!=0.0) { + _pin.period(1.0/frequencyptr[notecount]); + noteduration.attach(this,&SongPlayer::nextnote, durationptr[notecount]); + _pin = vol/2.0; + } else + _pin = 0.0; //turn off on last note +} \ No newline at end of file
--- a/main.cpp Sun Mar 13 17:00:12 2016 +0000 +++ b/main.cpp Thu Mar 17 21:12:59 2016 +0000 @@ -3,133 +3,132 @@ #include "SDFileSystem.h" #include "uLCD_4DGL.h" #include "wave_player.h" +#include "SongPlayer.h" +#include "note_public.h" +#include "player.h" +#include "Nav_Switch.h" #include <stdlib.h> #include <time.h> -#include <mpr121.h> #include <string> #include <list> -// Create the interrupt receiver object on pin 23 -InterruptIn interrupt(p23); -// Setup the i2c bus on pins 9 and 10 -I2C i2c(p9, p10); -// Setup the Mpr121: -// constructor(i2c object, i2c address of the mpr121) -Mpr121 mpr121(&i2c, Mpr121::ADD_VSS); - AnalogOut DACout(p18); // used to play sound on speaker //wave player plays a *.wav file to D/A and a PWM wave_player waver(&DACout); +SongPlayer mySpeaker(p21); uLCD_4DGL uLCD(p13,p14,p11); // serial tx, serial rx, reset pin; -Serial pc(USBTX, USBRX); - +Serial pc(USBTX, USBRX); // for debugging + SDFileSystem sd(p5, p6, p7, p8, "sd"); //SD card setup -Mutex mtx; +Mutex mtx; // for rtos -DigitalOut led1(LED1); -DigitalOut led2(LED2); -DigitalOut led3(LED3); -DigitalOut led4(LED4); +Nav_Switch myNav( p26, p29, p28, p30, p27); //pin order on Sparkfun breakout; this is for joystick -// Key hit/release interrupt routine -void fallInterrupt() { - pc.printf("Interrupt routine triggered"); - int key_code=0; - int i=0; - int value=mpr121.read(0x00); - value +=mpr121.read(0x01)<<8; - // LED demo mod - i=0; - // puts key number out to LEDs for demo - - for (i=0; i<12; i++) { - if (((value>>i)&0x01)==1) key_code=i+1; - } - pc.printf("key_code value: %i\n",key_code); - // USE KEY_CODE HERE TO DETERMINE WHAT TO DO WHEN CERTAIN BUTTONS ARE PRESSED - /* - while(key_code==1) - { - //LEFT NOTE - pc.printf("Left button pressed\n\r"); - mtx.lock(); - uLCD.filled_circle(105,15,4,BLUE); - mtx.unlock(); - break; - } - while (key_code == 5) - { - //MIDDLE NOTE - pc.printf("Middle button pressed\n\r"); - mtx.lock(); - uLCD.filled_circle(65,15,4,BLUE); - mtx.unlock(); - break; - } - while(key_code == 9) - { - //RIGHT NOTE - pc.printf("Right button pressed\n\r"); - mtx.lock(); - uLCD.filled_circle(25,15,4,BLUE); - mtx.unlock(); - break; - } - */ - -} - -void graphics_thread(void const *argument) -{ - // GRAPHICS IMPLEMENTATION GOES HERE - uLCD.locate(0,0); - uLCD.line(0,35,128,35,GREEN); - uLCD.line(43,0,43,128,GREEN); - uLCD.line(86,0,86,128,GREEN); - //while(1){ - // - // } - - } +volatile int currentDirection; // current direction of the joystick void controls_thread(void const *argument) { - // CONTROLS CHECKING (JOYSTICK AND TOUCHPAD) GO HERE, PROBABLY SOUND TOO - //interrupt.fall(&fallInterrupt); - //interrupt.mode(PullUp); + // CONTROLS CHECKING (JOYSTICK) GO HERE + + while(1) { + if((myNav & 0x0F) == 14){ + // Up on joystick + currentDirection = 1; + } + else if((myNav & 0x0F) == 13){ + // Down on joystick + currentDirection = 2; + } + else if((myNav & 0x0F) == 11){ + // Left on joystick + currentDirection = 3; + } + else if((myNav & 0x0F)== 7){ + // Right on joystick + currentDirection = 4; + } + else + currentDirection = 0; + //pc.printf("Value of (myNav & 0x0F) is %i\n\r",(myNav & 0x0F)); FOR DEBUGGING PURPOSES + //pc.printf("Value of currentDirection is %i\n\r",currentDirection); FOR DEBUGGING PURPOSES + Thread::wait(100); // ADJUST THIS TO SET HOW FAST INPUTS FROM JOYSTICK ARE 'CLOCKED' IN + } } int main() { - double lives = 20; - // IF MISS NOTE - 2 lives - // IF HIT NOTE + 1.2 lives - uLCD.locate(0,0); - uLCD.line(0,35,128,35,GREEN); - uLCD.line(43,0,43,128,GREEN); - uLCD.line(86,0,86,128,GREEN); - uLCD.circle(108,15,10,WHITE); //LEFT - uLCD.filled_circle(108,15,4,WHITE); - uLCD.circle(65,15,10,WHITE); //MIDDLE - uLCD.filled_circle(65,15,4,WHITE); - uLCD.circle(22,15,10,WHITE); //RIGHT - uLCD.filled_circle(22,15,4,WHITE); - for(int i = 5;i<10;i++) - { - uLCD.circle(108,15,i,GREEN); - uLCD.circle(65,15,i,RED); - uLCD.circle(22,15,i,0xFFFF00); - } - interrupt.fall(&fallInterrupt); - interrupt.mode(PullUp); - while (1) { - //Thread thread1(graphics_thread); - //Thread thread2(controls_thread); - pc.printf("Program is running...\n\r"); - wait(5); + //FILE *greenNote; + //FILE *yellowNote; + //FILE *redNote; + //greenNote=fopen("/sd/wavfiles/bassDrum.wav","r"); + //redNote=fopen("/sd/wavfiles/highHat.wav","r"); + //yellowNote=fopen("/sd/wavfiles/snareDrum.wav","r"); + + //INITIALIZE IMPORTANT VARIABLES + float greenNote[2]= {440.0,0.0}; // Tone played when green direction is pressed on joystick + float redNote[2] = {261.626,0.0}; // Tone played when red direction is pressed on joystick + float yellowNote[2] = {196,0.0}; // Tone played when yellow direction is pressed on joystick + float duration[2]= {0.1, 0.0}; // Duration of tone (set to .1 seconds) + bool gameOver = false; // Ends game when this is true + Thread thread1(controls_thread); // Thread handling controls (joystick) + + + //INITIALIZE THE PLAYER + player_init(); + //INITIALIZE THE GUI + gui_init(); + + while (gameOver==false) { // Main game loop + + + + + + //START THE NOTE GENERATOR AND KEEP TRACK OF NOTES + note_generator(); + detect_note_miss(); + if(currentDirection==4) //LEFT ON JOYSTICK + { + mtx.lock(); + uLCD.filled_circle(108,128-15,4,BLUE); //Make center of note area light up blue momentarily to show you are trying to hit a note there + mySpeaker.PlaySong(greenNote,duration); //Play tone when you try to hit a note + detect_note_hit(2); // Detect note hit in this lane + //uLCD.filled_circle(108,128-15,4,WHITE); + //pc.printf("detect_note_hit function called on button 1\n\r"); FOR DEBUGGING PURPOSES + mtx.unlock(); + } + else if(currentDirection==1) //UP ON JOYSTICK + { + mtx.lock(); + uLCD.filled_circle(65,128-15,4,BLUE); //Make center of note area light up blue momentarily to show you are trying to hit a note there + mySpeaker.PlaySong(redNote,duration); //Play tone when you try to hit a note + detect_note_hit(1); // Detect note hit in this lane + //uLCD.filled_circle(65,128-15,4,WHITE); + //pc.printf("detect_note_hit function called on button 2\n\r"); FOR DEBUGGING PURPOSES + mtx.unlock(); + } + else if(currentDirection==3) //RIGHT ON JOYSTICK + { + mtx.lock(); + uLCD.filled_circle(22,128-15,4,BLUE); //Make center of note area light up blue momentarily to show you are trying to hit a note there + mySpeaker.PlaySong(yellowNote,duration); //Play tone when you try to hit a note + detect_note_hit(0); // Detect note hit in this lane + //uLCD.filled_circle(22,128-15,4,WHITE); + //pc.printf("detect_note_hit function called on button 3\n\r"); FOR DEBUGGING PURPOSES + mtx.unlock(); + } + else if(currentDirection==0) //FINGER COMING OFF KEY + { + uLCD.filled_circle(22,128-15,4,WHITE); + uLCD.filled_circle(65,128-15,4,WHITE); + uLCD.filled_circle(108,128-15,4,WHITE); + } + gameOver = detect_lose_conditions(); } + uLCD.printf("\n\n\n\n\n Game Over\n\n"); //Displays the game over screen + uLCD.printf(" Your Score: %i",get_player_score()); //Displays the score of the player once they have lost } \ No newline at end of file
--- a/mpr121.cpp Sun Mar 13 17:00:12 2016 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,221 +0,0 @@ -/* -Copyright (c) 2011 Anthony Buckton (abuckton [at] blackink [dot} net {dot} au) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -#include <mbed.h> -#include <sstream> -#include <string> -#include <list> - -#include <mpr121.h> - -Mpr121::Mpr121(I2C *i2c, Address i2cAddress) -{ - this->i2c = i2c; - - address = i2cAddress; - - // Configure the MPR121 settings to default - this->configureSettings(); -} - - -void Mpr121::configureSettings() -{ - // Put the MPR into setup mode - this->write(ELE_CFG,0x00); - - // Electrode filters for when data is > baseline - unsigned char gtBaseline[] = { - 0x01, //MHD_R - 0x01, //NHD_R - 0x00, //NCL_R - 0x00 //FDL_R - }; - - writeMany(MHD_R,gtBaseline,4); - - // Electrode filters for when data is < baseline - unsigned char ltBaseline[] = { - 0x01, //MHD_F - 0x01, //NHD_F - 0xFF, //NCL_F - 0x02 //FDL_F - }; - - writeMany(MHD_F,ltBaseline,4); - - // Electrode touch and release thresholds - unsigned char electrodeThresholds[] = { - E_THR_T, // Touch Threshhold - E_THR_R // Release Threshold - }; - - for(int i=0; i<12; i++){ - int result = writeMany((ELE0_T+(i*2)),electrodeThresholds,2); - } - - // Proximity Settings - unsigned char proximitySettings[] = { - 0xff, //MHD_Prox_R - 0xff, //NHD_Prox_R - 0x00, //NCL_Prox_R - 0x00, //FDL_Prox_R - 0x01, //MHD_Prox_F - 0x01, //NHD_Prox_F - 0xFF, //NCL_Prox_F - 0xff, //FDL_Prox_F - 0x00, //NHD_Prox_T - 0x00, //NCL_Prox_T - 0x00 //NFD_Prox_T - }; - writeMany(MHDPROXR,proximitySettings,11); - - unsigned char proxThresh[] = { - PROX_THR_T, // Touch Threshold - PROX_THR_R // Release Threshold - }; - writeMany(EPROXTTH,proxThresh,2); - - this->write(FIL_CFG,0x04); - - // Set the electrode config to transition to active mode - this->write(ELE_CFG,0x0c); -} - -void Mpr121::setElectrodeThreshold(int electrode, unsigned char touch, unsigned char release){ - - if(electrode > 11) return; - - // Get the current mode - unsigned char mode = this->read(ELE_CFG); - - // Put the MPR into setup mode - this->write(ELE_CFG,0x00); - - // Write the new threshold - this->write((ELE0_T+(electrode*2)), touch); - this->write((ELE0_T+(electrode*2)+1), release); - - //Restore the operating mode - this->write(ELE_CFG, mode); -} - - -unsigned char Mpr121::read(int key){ - - unsigned char data[2]; - - //Start the command - i2c->start(); - - // Address the target (Write mode) - int ack1= i2c->write(address); - - // Set the register key to read - int ack2 = i2c->write(key); - - // Re-start for read of data - i2c->start(); - - // Re-send the target address in read mode - int ack3 = i2c->write(address+1); - - // Read in the result - data[0] = i2c->read(0); - - // Reset the bus - i2c->stop(); - - return data[0]; -} - - -int Mpr121::write(int key, unsigned char value){ - - //Start the command - i2c->start(); - - // Address the target (Write mode) - int ack1= i2c->write(address); - - // Set the register key to write - int ack2 = i2c->write(key); - - // Read in the result - int ack3 = i2c->write(value); - - // Reset the bus - i2c->stop(); - - return (ack1+ack2+ack3)-3; -} - - -int Mpr121::writeMany(int start, unsigned char* dataSet, int length){ - //Start the command - i2c->start(); - - // Address the target (Write mode) - int ack= i2c->write(address); - if(ack!=1){ - return -1; - } - - // Set the register key to write - ack = i2c->write(start); - if(ack!=1){ - return -1; - } - - // Write the date set - int count = 0; - while(ack==1 && (count < length)){ - ack = i2c->write(dataSet[count]); - count++; - } - // Stop the cmd - i2c->stop(); - - return count; -} - - -bool Mpr121::getProximityMode(){ - if(this->read(ELE_CFG) > 0x0c) - return true; - else - return false; -} - -void Mpr121::setProximityMode(bool mode){ - this->write(ELE_CFG,0x00); - if(mode){ - this->write(ELE_CFG,0x30); //Sense proximity from ALL pads - } else { - this->write(ELE_CFG,0x0c); //Sense touch, all 12 pads active. - } -} - - -int Mpr121::readTouchData(){ - return this->read(0x00); -} \ No newline at end of file
--- a/mpr121.h Sun Mar 13 17:00:12 2016 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,157 +0,0 @@ -/* -Copyright (c) 2011 Anthony Buckton (abuckton [at] blackink [dot} net {dot} au) - - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - Parts written by Jim Lindblom of Sparkfun - Ported to mbed by A.Buckton, Feb 2011 -*/ - -#ifndef MPR121_H -#define MPR121_H - -//using namespace std; - -class Mpr121 -{ - -public: - // i2c Addresses, bit-shifted - enum Address { ADD_VSS = 0xb4,// ADD->VSS = 0x5a <-wiring on Sparkfun board - ADD_VDD = 0xb6,// ADD->VDD = 0x5b - ADD_SCL = 0xb8,// ADD->SDA = 0x5c - ADD_SDA = 0xba // ADD->SCL = 0x5d - }; - - // Real initialiser, takes the i2c address of the device. - Mpr121(I2C *i2c, Address i2cAddress); - - bool getProximityMode(); - - void setProximityMode(bool mode); - - int readTouchData(); - - unsigned char read(int key); - - int write(int address, unsigned char value); - int writeMany(int start, unsigned char* dataSet, int length); - - void setElectrodeThreshold(int electrodeId, unsigned char touchThreshold, unsigned char releaseThreshold); - -protected: - // Configures the MPR with standard settings. This is permitted to be overwritten by sub-classes. - void configureSettings(); - -private: - // The I2C bus instance. - I2C *i2c; - - // i2c address of this mpr121 - Address address; -}; - - -// MPR121 Register Defines -#define MHD_R 0x2B -#define NHD_R 0x2C -#define NCL_R 0x2D -#define FDL_R 0x2E -#define MHD_F 0x2F -#define NHD_F 0x30 -#define NCL_F 0x31 -#define FDL_F 0x32 -#define NHDT 0x33 -#define NCLT 0x34 -#define FDLT 0x35 -// Proximity sensing controls -#define MHDPROXR 0x36 -#define NHDPROXR 0x37 -#define NCLPROXR 0x38 -#define FDLPROXR 0x39 -#define MHDPROXF 0x3A -#define NHDPROXF 0x3B -#define NCLPROXF 0x3C -#define FDLPROXF 0x3D -#define NHDPROXT 0x3E -#define NCLPROXT 0x3F -#define FDLPROXT 0x40 -// Electrode Touch/Release thresholds -#define ELE0_T 0x41 -#define ELE0_R 0x42 -#define ELE1_T 0x43 -#define ELE1_R 0x44 -#define ELE2_T 0x45 -#define ELE2_R 0x46 -#define ELE3_T 0x47 -#define ELE3_R 0x48 -#define ELE4_T 0x49 -#define ELE4_R 0x4A -#define ELE5_T 0x4B -#define ELE5_R 0x4C -#define ELE6_T 0x4D -#define ELE6_R 0x4E -#define ELE7_T 0x4F -#define ELE7_R 0x50 -#define ELE8_T 0x51 -#define ELE8_R 0x52 -#define ELE9_T 0x53 -#define ELE9_R 0x54 -#define ELE10_T 0x55 -#define ELE10_R 0x56 -#define ELE11_T 0x57 -#define ELE11_R 0x58 -// Proximity Touch/Release thresholds -#define EPROXTTH 0x59 -#define EPROXRTH 0x5A -// Debounce configuration -#define DEB_CFG 0x5B -// AFE- Analogue Front End configuration -#define AFE_CFG 0x5C -// Filter configuration -#define FIL_CFG 0x5D -// Electrode configuration - transistions to "active mode" -#define ELE_CFG 0x5E - -#define GPIO_CTRL0 0x73 -#define GPIO_CTRL1 0x74 -#define GPIO_DATA 0x75 -#define GPIO_DIR 0x76 -#define GPIO_EN 0x77 -#define GPIO_SET 0x78 -#define GPIO_CLEAR 0x79 -#define GPIO_TOGGLE 0x7A -// Auto configration registers -#define AUTO_CFG_0 0x7B -#define AUTO_CFG_U 0x7D -#define AUTO_CFG_L 0x7E -#define AUTO_CFG_T 0x7F - -// Threshold defaults -// Electrode touch threshold -#define E_THR_T 0x0F -// Electrode release threshold -#define E_THR_R 0x0A -// Prox touch threshold -#define PROX_THR_T 0x02 -// Prox release threshold -#define PROX_THR_R 0x02 - -#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/note.cpp Thu Mar 17 21:12:59 2016 +0000 @@ -0,0 +1,141 @@ +#include "note_private.h" +extern Serial pc; + +NOTE note_record[MAX_NUM_NOTE]; +int note_tick=0; // Internal note tick, used to make the note move at the appropriate speed +int note_interval = 25; // The interval on which notes are created. Higher number is more frequent +int note_speed = 4; // The speed at which the notes travel + +// See the comments in note_public.h +void note_generator(void){ + note_tick++; + // only create the notes at certain ticks + if((note_tick % note_interval)==0 || note_tick==0){ + note_create(); + } + + // update the notes and draw them + note_update_position(); +} + +// set note speed (default speed is 4) +void set_note_speed(int speed){ + if(speed>=1 && speed<=8){ + note_speed = speed; + } +} + +// set note interval (default interval is 25) +void set_note_interval(int interval){ + if(interval>=1 && interval<=100){ + note_interval = interval; + } +} + +// See the comments in note_public.h +NOTE note_get_info(int index){ + return note_record[index]; +} + +// See the comments in note_public.h +void note_set_played(int index){ + note_record[index].status = NOTE_PLAYED; + //pc.printf("Note %i has been changed to played",index); FOR DEBUGGING PURPOSES +} + +// See the comments in note_public.h +void note_set_missed(int index){ + note_record[index].status = NOTE_MISSED; + //pc.printf("Note %i has been changed to missed",index); FOR DEBUGGING PURPOSES +} + +// See the comments in hote_public.h +void set_note_color(int index, int color){ + note_record[index].color = color; +} + +/** This function finds an empty slot of note_record, and actives it. +*/ +void note_create(void){ + int i,laneIndex; + int startingPoints[3] = {22,65,108}; // The three possibilities for the X coordinate of the center of the note + int colors[3] = {0xFFFF00,RED,GREEN}; // The three possibilities for the color of the note + for(i=0;i<MAX_NUM_NOTE;i++){ + if(note_record[i].status == NOTE_DEACTIVE){ // Only create new notes in a space where there is a deactive note + laneIndex = (rand() % 3); // Randomly choose which lane to put the note in + note_record[i].y = 0; // Initialize the note's Y value + //each note has its own tick + note_record[i].tick = 0; + //set a random source for the note + note_record[i].source_x = startingPoints[laneIndex]; + note_record[i].lane = laneIndex; + //pc.printf("Note %i is in lane %i \n\r",i,laneIndex); FOR DEBUGGING PURPOSES + //set appropriate color for note + note_record[i].color = colors[laneIndex]; + //the note starts at its source + note_record[i].x = note_record[i].source_x; + //the note must be set to active + note_record[i].status = NOTE_ACTIVE; + break; + } + } +} + +/** This function update the position of all notes and draws them +*/ +void note_update_position(void){ + int i; + double delta_y; + //controls how fast the note will move + int rate = note_speed * 25; + for(i=0;i<MAX_NUM_NOTE;i++){ + if(note_record[i].status == NOTE_ACTIVE){ + // update note position + delta_y = 200/rate; + note_draw(note_record[i], BLACK); // Draw over old location of note + note_record[i].y = (int)((delta_y*(note_record[i].tick%rate))); // Update the Y value of the note + //pc.printf("Note %i has a y value of %i \n\r",i,note_record[i].y); FOR DEBUGGING PURPOSES + note_draw(note_record[i], note_record[i].color); // Draw note in its new location + //update note's internal tick + note_record[i].tick++; + } + else if((note_record[i].status == NOTE_PLAYED) || (note_record[i].status == NOTE_MISSED)){ // If the status of the note is not active + // clear the note off the screen + note_draw(note_record[i], BLACK); + // we are done with this note, mark as deactive + note_record[i].status = NOTE_DEACTIVE; + //resets the note's internal tick + note_record[i].tick = 0; + //resets the note's y position + note_record[i].y = 128; + } + + } +} + +/** This function draws a note. + @param note The note to be drawn + @param color The color of the note +*/ +void note_draw(NOTE note, int color){ + int current_x,current_y; + current_x = note.x; + current_y = note.y; + if(color != BLACK) // If we arent erasing a note + { + uLCD.filled_circle(current_x, current_y,4, WHITE); + uLCD.circle(current_x, current_y,10,WHITE); + for(int i = 5;i<10;i++) + { + uLCD.circle(current_x,current_y,i,color); + } + } + else + { + uLCD.filled_circle(current_x,current_y,10,BLACK); + + } +} + + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/note_private.h Thu Mar 17 21:12:59 2016 +0000 @@ -0,0 +1,41 @@ +/* Gatech ECE2035 2014 FALL missile command + * Copyright (c) 2014 Gatech ECE2035 + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef NOTE_PRIVATE_H +#define NOTE_PRIVATE_H + +#include "mbed.h" +#include "uLCD_4DGL.h" +#include "note_public.h" +extern uLCD_4DGL uLCD; + +//==== [private settings] ==== + +//==== [private type] ==== + + +//==== [private function] ==== +void note_create(void); +void note_draw(NOTE note, int color); + +#endif //NOTE_PRIVATE_H + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/note_public.h Thu Mar 17 21:12:59 2016 +0000 @@ -0,0 +1,66 @@ +#ifndef NOTE_PUBLIC_H +#define NOTE_PUBLIC_H + +//The note status +typedef enum { + NOTE_MISSED=3, //note has been missed + NOTE_PLAYED=2,//note has been played + NOTE_ACTIVE=1,//note is active + NOTE_DEACTIVE=0//note is no longer active +} NOTE_STATUS; + +// The structure to store the information of a note +typedef struct { + int x; // The x-coordinate of note's current position + int y; // The y-coordinate of note's current position + double source_x; // The x-coordinate of the note's origin + int tick; // The note's internal tick + int color; // The note's color + int lane; // Which lane is the note in + NOTE_STATUS status; // The note status, see NOTE_STATUS +} NOTE; + +#define MAX_NUM_NOTE 5 + +/** This function draws the notes onto the screen + Call note_generator() repeatedly in game-loop +*/ +void note_generator(void); + +/** The function set the status of note to be NOTE_PLAYED + @param index The index in note_record. It must be smaller than MAX_NUM_NOTE. +*/ +void note_set_played(int index); + +/** The function sets the status of note to be NOTE_MISSED + @param index The index in note_record. It must be smaller than MAX_NUM_NOTE. +*/ + +void note_set_missed(int index); + +/** Get the information of a note + @param index The index in note_record. It must be smaller than MAX_NUM_NOTE. + @return The structure of note information +*/ + +NOTE note_get_info(int index); + +/** Set the speed of notes, Speed has range of 1-8 with 1 being fastest and 8 being slowest +*/ +void set_note_speed(int speed); + +/** Set the interval that the notes occur, interval has range of 1-100 with 1 being created in + very quick succession and 100 being created very slowly after one another +*/ +void set_note_interval(int interval); + +/** The function set the color of note to be color + @param color The color in note_record. +*/ + +void set_note_color(int index, int color); + +//The function updates the position of the notes on the board +void note_update_position(void); + +#endif //NOTE_PUBLIC_H \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/player.cpp Thu Mar 17 21:12:59 2016 +0000 @@ -0,0 +1,128 @@ +#include "mbed.h" +#include "uLCD_4DGL.h" +#include "player.h" +#include "note_public.h" +#include <math.h> + +extern int note_speed; // Note speed +extern int note_interval; // Interval on which notes are created +extern uLCD_4DGL uLCD; // LCD display +extern Serial pc; // For debugging + +PLAYER CURRENT_PLAYER; // Player object +NOTE note_array[MAX_NUM_NOTE]; // Structure containing the Note objects + +void player_init() { // Initializes the player object with default values + CURRENT_PLAYER.score = 0; + CURRENT_PLAYER.lives = 20; + CURRENT_PLAYER.status = ALIVE; +} + +void gui_init() { // Draws the GUI on the LCD + uLCD.locate(0,0); + uLCD.line(43,0,43,128,GREEN); //Lines separating the lanes + uLCD.line(86,0,86,128,GREEN); //Lines separating the lanes + uLCD.circle(108,128-15,10,WHITE); //Left note + uLCD.filled_circle(108,128-15,4,WHITE); //Left note + uLCD.circle(65,128-15,10,WHITE); //Middle note + uLCD.filled_circle(65,128-15,4,WHITE); //Middle note + uLCD.circle(22,128-15,10,WHITE); //Right note + uLCD.filled_circle(22,128-15,4,WHITE); //Right note + for(int i = 5;i<10;i++) //Loop used to fill in the notes with appropriate color + { + uLCD.circle(108,128-15,i,GREEN); + uLCD.circle(65,128-15,i,RED); + uLCD.circle(22,128-15,i,0xFFFF00); + } +} + +double get_player_lives() { // Gets number of lives player has remaining + + return(CURRENT_PLAYER.lives); +} + +int get_player_score() { // Gets score of player + pc.printf("Player's Score: %i\n\r",CURRENT_PLAYER.score); + return(CURRENT_PLAYER.score); + } + +void update_values(){ // Updates the structure containing the Note object data + for(int index=0;index<MAX_NUM_NOTE;index++) + { + note_array[index]=note_get_info(index); + //pc.printf("The y value of note %i is %d\n\r",index,note_array[index].y); FOR DEBUGGING PURPOSES + } +} + +bool detect_lose_conditions(){ // Detects when the game is over by checking the player's lives + bool game_over = false; + if(CURRENT_PLAYER.lives <= 0){ + game_over=true; + } + return(game_over); +} + +float get_distance(int index){ // Detects distance between notes in the lane and the note registration zone + float distance = 0; + int y2 = note_array[index].y; + distance = abs(y2-(128.0-15.0)); // 113.0 is the location of the center of the registration zone in the y direction + //pc.printf("The Y value for note %i is %i \n\r",index,y2); FOR DEBUGGING PURPOSES + //pc.printf("The distance between the note and the checkpoint is: %f\n\r",distance); FOR DEBUGGING PURPOSES + return (distance); + } + +bool detect_note_miss(){ // Detects when notes go past the checkpoint, also will check to see if player has lost all their lives + bool gameOver = false; // Assume the player has not lost the game yet + update_values(); // Make sure the location data for all notes is current + for(int index=0;index<5;index++){ + if((note_array[index].y >=(128-10)) && (note_array[index].y != 128)) // If the note has passed the registration/checkpoint zone + { + note_set_missed(index); // Set note as missed + note_update_position(); // Update its status + gui_init(); // Redraw the GUI + CURRENT_PLAYER.lives -= 2; // Lose 2 lives for a missed note + gameOver = detect_lose_conditions(); // Determine if this has lost the player the game + //pc.printf("Note went past registration zone!\n\r"); // FOR DEBUGGING PURPOSES + //break; + } + } + return(gameOver); +} + +bool detect_note_hit(int lane){ // Detects when a note is hit, is called whenever a direction is input on the joystick + bool gameOver = false; // Assume player has not lost the game yet + update_values(); // Make sure the location data for all notes is current + int minDistance = 128; // We only want to look at the closest note in the lane we care about + int indexToCheck; // We only need to look at one note per function call + for(int i=0;i<5;i++) + { + //pc.printf("Checking note %i, current lane: %i \n\r",i,note_array[i].lane); FOR DEBUGGING PURPOSES + if(note_array[i].lane+1 == (lane+1)) + { + if(get_distance(i) < minDistance) + { + minDistance = get_distance(i); // Make sure we get the note with the least distance to the checkpoint + indexToCheck=i; // This is the note we want to check if we hit + } + } + } + //pc.printf("Found a match!"); FOR DEBUGGING PURPOSES + double distance = get_distance(indexToCheck); // Check distance of selected note from checkpoint zone + if(distance <= 4.0){ // If note is close enough, proceed + note_set_played(indexToCheck); // Set note status to NOTE_PLAYED + note_update_position(); // Update note position + gui_init(); // Redraw the GUI + CURRENT_PLAYER.lives += 1.2; // Player gets 1.2 lives back for each note hit + CURRENT_PLAYER.score += 1.0; // Player gets 1 point for every note hit + //pc.printf("Note hit!\n\r"); FOR DEBUGGING PURPOSES + } + else if(distance > 4) // If note is not close enough, proceed with miss protocol + { + CURRENT_PLAYER.lives -=1.0; // If a note is missed in this manner, player loses 1 life + gameOver = detect_lose_conditions();// Check to see if this has caused the player to lose all their lives and the game + //pc.printf("Note missed...\n\r"); DEBUGGING PURPOSES + } + return(gameOver); +} + + \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/player.h Thu Mar 17 21:12:59 2016 +0000 @@ -0,0 +1,50 @@ + +// Template of player header file +#ifndef PLAYER_H +#define PLAYER_H + +typedef enum { + ALIVE=1, // The game screen will be shown + DEAD=0 // The game screen will not be shown +} PLAYER_STATUS; + +typedef struct { + int score; // Score of the player + double lives; // Number of remaining lives + PLAYER_STATUS status; // See enum PLAYER_STATUS +} PLAYER; + +#define MAX_NUM_PLAYER 1 // There can only be a single player + +// The function returns the number of lives the player has remaining +double get_player_lives(); + +// The function returns the score of the player +int get_player_score(); + +// Initializes the player object +void player_init(); + +// Initializes/Draws the GUI on the LCD +void gui_init(); + +/** The function gets the distance from the checkpoint/registration zone to the nearest note in the lane specified by index + @param index The index in the structure containing the note objects of the note to be checked +*/ +float get_distance(int index); + +// Function to make sure all the Note objects in the structure containing the notes is up to date +void update_values(); + +// The function returns a boolean stating whether the player has lost the game or not. Function also checks to see if a note has passed the registration zone +bool detect_note_miss(); + +/** The function detects whether a note is close enough to the checkpoint to be a hit or not. Returns a boolean to determine if the player has lost all their lives as well. + @param index The lane in which the notes are to be looked for. +*/ +bool detect_note_hit(int index); + +// The function determines whether or not the player has lost all their lives or not. Returns a boolean which describes whether the player has lost or not. +bool detect_lose_conditions(); + +#endif //PLAYER_H \ No newline at end of file