The present code implements a single player squash game, using joystick to move paddle right or left. And checks the current temperature inside the device.

Dependencies:   2645_I2C_TMP102 2645_Physics_Engine_Example Paddle mbed

main.cpp

Committer:
bonnyngangu
Date:
2016-05-06
Revision:
0:61128d697217
Child:
1:fe4ac8f10309

File content as of revision 0:61128d697217:

#include "mbed.h"
#include "N5110.h"
#include "Joystick.h"
#include "SDFileSystem.h"

#define BALLRADIUS 2


//          VCC,    SCE,  RST,    D/C,   MOSI,  SCLK,   LED
N5110 lcd (PTE26 , PTA0 , PTC4 , PTD0 , PTD2 , PTD1 , PTC3);
// Can also power (VCC) directly from VOUT (3.3 V) -
// Can give better performance due to current limitation from GPIO pin

InterruptIn interrupt_button(PTB18); // interrupt in button.
PwmOut buzzer(PTA2); // buzzer connection to PwmOut.

// Connections to SD card holder on K64F (SPI interface)
SDFileSystem sd(PTE3, PTE1, PTE2, PTE4, "sd"); // MOSI, MISO, SCK, CS

void delete_file(char filename[]);

// function prototypes
void init_ball();
void game_timer_isr();
void BallMove();
void redraw_screen();
void update_physics_engine();
void check_collisions();
void Squash_Court();
void getPaddle();
void PaddleMove();
void updateJoystick();

//bool wall = false;

// Can give better performance due to current limitation from GPIO pin
Ticker game_timer;

// struct used to store 2D vectors
typedef struct vector_t vector_t;
struct vector_t {
    float x;
    float y;
};

vector_t pos;  // ball position
vector_t vel;  // ball velocity
vector_t acc;  // ball acceleration

float refresh_rate = 25.0;  // how often to update display (Hz)
float g_dt = 2.0F/refresh_rate;  // global to store time step (F makes it a float, gets rid of compiler warning)
volatile int g_timer_flag = 0;

int scoring = 0;// setting the value of starting score.
int Lhand = 0;// value of the left hand side on y axis.
int Rhand = 0;// value of the right hand side on y axis.
int m = 42 ;
int a;
int width;// left hand side width.
int width2;/// right hand side width.


int main()
{
     
    wait(1.0);  // short delay for power settling
    lcd.init(); // initialising the display
      
    lcd.printString(" SQUASH!",15,2);
        lcd.inverseMode(); // invert colours
        lcd.drawLine(41,0,0,23,1);
        lcd.drawLine(41,0,83,23,1);
        lcd.drawLine(0,23,41,47,1);
        lcd.drawLine(83,23,41,47,1);
        lcd.refresh(); 
        wait(5.0);
        lcd.clear();
        lcd.printString("Game starting",5,2);
        lcd.normalMode();      // normal colour mode
        lcd.setBrightness(0.5); // put LED backlight on 50%
        
        buzzer.period_ms(2.0);
        buzzer.pulsewidth_ms(1.9);
        getPaddle();
        wait(3.0);
         
    calibrateJoystick();  // get centred values of joystick
    pollJoystick.attach(&updateJoystick,1.0/10.0);  // read joystick 10 times per second
    
    init_ball();
    // setup ticker
    game_timer.attach(&game_timer_isr,g_dt);

    redraw_screen();  // draw initial screen
        
    while (1) {
                      
        Squash_Court();
        BallMove();
        PaddleMove();  
    }
}

void getPaddle() // setting paddle moving
{   
    int m = 42 ; // set paddle into origin 42 on X axis.
    
    // drawing the paddle.
    lcd.drawLine(m-6,45,m+6,45,1);
    lcd.refresh();
}


void PaddleMove()
{      
    // setting the joystick control.
    if (joystick.direction == RIGHT && m > 4) {
        //scoring + = 1;// one pixel move for 1 score.
        lcd.drawLine(m-6,45,m+6,45,1);
        m-=1;// moving a pixel a time.       
        lcd.refresh();
    }
            
    if (joystick.direction == LEFT && m < 78) {
        //scoring + = 1;// one pixel move for 1 score.
        lcd.drawLine(m-6,45,m+6,45,1);
        m+=1;// moving a pixel a time.

        lcd.drawLine(m-6,45,m+6,45,1);
        lcd.refresh();
    }          
}

void Squash_Court()
{
          
    lcd.drawRect(0,0,83,47,0);    // transparent, just outline
    lcd.refresh();   // need to refresh screen after drawing rects
                         
    for (int i = 0; i < 84; i++) {
    
    lcd.setPixel(i,24);// at y = 24 pixels (centre)
    }
            
    for (int i = 0; i < 84; i++) {
    
    lcd.setPixel(i,16);// // at y = 14 pixels 
    }
            
    // need to refresh display after setting pixels
    lcd.refresh();
    
}

int SD_card()
{
    serial.baud(115200);  // full-speed!
    serial.printf("#### SD Card Example #####\n");
    FILE *fp; // this is our file pointer
    wait(1);

    // open file for writing ('w') - creates file if it doesn't exist and overwrites
    // if it does. If you wish to add a score onto a list, then you can
    // append instead 'a'. This will open the file if it exists and start
    // writing at the end. It will create the file if it doesn't exist.
    fp = fopen("/sd/topscore.txt", "w");
    int top_score = 56;  // random example

    if (fp == NULL) {  // if it can't open the file then print error message
        serial.printf("Error! Unable to open file!\n");
    } else {  // opened file so can write
        serial.printf("Writing to file....");
        fprintf(fp, "%d",top_score); // ensure data type matches
        serial.printf("Done.\n");
        fclose(fp);  // ensure you close the file after writing
    }

    // now open file for reading
    fp = fopen("/sd/topscore.txt", "r");
    int stored_top_score = -1;  // -1 to demonstrate it has changed after reading

    if (fp == NULL) {  // if it can't open the file then print error message
        serial.printf("Error! Unable to open file!\n");
    } else {  // opened file so can write
        fscanf(fp, "%d",&stored_top_score); // ensure data type matches - note address operator (&)
        serial.printf("Read %d from file.\n",stored_top_score);
        fclose(fp);  // ensure you close the file after reading
    }
  
    // for this example, I'll create some numbers to write to file in a big list
    // a data logger for example will usually append to a file - at a reading
    // at the end rather than creating a new file
    fp = fopen("/sd/test.txt", "a");

    if (fp == NULL) {  // if it can't open the file then print error message
        serial.printf("Error! Unable to open file!\n");
    } else {  // opened file so can write
        serial.printf("Writing to file....");
        for(int i = 1; i <= 50; i++) {
            float dummy = 1000.0F/i;  // dummy variable
            fprintf(fp, "%d,%f\n",i,dummy);  // print formatted string to file (CSV)
        }
        serial.printf("Done.\n");
        fclose(fp);  // ensure you close the file after writing
    }
    
    // you can comment out the writing example to check that the writing has
    // worked - when you run it after commenting, it should still open the
    // file that exists on the SD card - assuming you didn't delete it!

    // now open file for reading...note the 'r'
    fp = fopen("/sd/test.txt", "r");
    if (fp == NULL) {  // if it can't open the file then print error message
        serial.printf("Error! Unable to open file!\n");
    } else {
        serial.printf("Reading file....\n");
        int i;    // create suitable variables to store the data in the file
        float value;

        // in this example, we keep reading (using fscanf) until we reach
        // the 'end of file'. Note we use the address operator & to write
        // to the variables. Also the format of the string must match what
        // is in the file
        while (fscanf(fp, "%d,%f", &i, &value) != EOF) {
            serial.printf("%d,%f\n",i,value);
        }
        serial.printf("Done.\n");
        fclose(fp);  // ensure you close the file after reading
    }

    // the previous example just read the values into variables and printed to
    // serial, we'll now read files into an array.

    // now open file for reading...note the 'r'
    fp = fopen("/sd/test.txt", "r");

    int n=0;  // going to store the number of lines in the file
    int *index_array;  // pointers to create dynamic arrays later
    float *value_array; // note memory will be in heap rather than on the stack

    if (fp == NULL) {  // if it can't open the file then print error message
        serial.printf("Error! Unable to open file!\n");
    } else {
        serial.printf("Counting lines in file....\n");
        //Since we may not know the
        // number of lines in the files ahead of time, we'll first count them
        // * means scan but don't save
        while (fscanf(fp, "%*d,%*f") != EOF) {
            n++;  // increment counter when read a line
        }


        serial.printf("Read %d lines\n",n);
        serial.printf("Creating dynamic arrays...\n");
        // calloc creates an array and initilises to 0
        // malloc returns unitialised array - diffrent syntax
        index_array = (int *)calloc(n, sizeof (int));
        value_array = (float *)calloc(n, sizeof (float));

        int i=0;
        rewind(fp); // 'scrolled' to end of file, so go back to beginning
        serial.printf("Reading into arrays...\n");
        while (fscanf(fp, "%d,%f",&index_array[i],&value_array[i]) != EOF) {
            i++;  // read data into array and increment index
        }
        serial.printf("Done.\n");
        fclose(fp);  // ensure you close the file after reading
    }
    
    // we should now have the data in the arrays, will print to serial to check
    for(int i=0; i<n ; i++) {
        serial.printf("[%d] %d,%f\n",i,index_array[i],value_array[i]);
    } 

    serial.printf("End of SD card example\n");
    
    return 0;
    
}

void delete_file(char filename[])
{
    serial.printf("Deleting file '%s'...",filename);
    FILE *fp = fopen(filename, "r");  // try and open file
    if (fp != NULL) {  // if it does open...
        fclose(fp);    // close it
        remove(filename);  // and then delete
        serial.printf("Done!\n");
    }
    // if we can't open it, it doesn't exist and so we can't delete it
}

void BallMove()
{
      if ( g_timer_flag ) {  // ticker interrupt
          g_timer_flag = 0;  // clear flag
            update_physics_engine();
            check_collisions();
            redraw_screen();
        }
}

void redraw_screen()
{
    lcd.clear();
    lcd.drawCircle(pos.x,pos.y,BALLRADIUS,1);  // x,y,radius,black fill
    lcd.refresh();  // update display
}

void check_collisions()
{
    // see if ball has hit the floor (subtract the radius since the position is the centre of the ball)
    if ( pos.y >= 47 - BALLRADIUS ) {
        pos.y = 47 - BALLRADIUS;  // need to force this or else ball can end up going 'underground'
        vel.y = -1.0 * vel.y;  // y velocity is reflected and dampened 
        // y accleration is still gravity
    }
   
    else if ( pos.y >= 45 - BALLRADIUS) {
        pos.y = 45 - BALLRADIUS;  // need to force this or else ball can end up going 'underground'
        vel.y = -4.0 * vel.y;  // y velocity is reflected and dampened 
        // y accleration is still gravity
    } 
      
    // has ball gone off the right-hand side?
    if ( pos.x >= 83 - BALLRADIUS ) {
        pos.x = 83 - BALLRADIUS;  // need to force this or else ball can end up going off screen
        vel.x = -1.5 * vel.x;  // reflect and damp velocity
        acc.x = -acc.x;  // reflect accleration
    }
    
    // what about the left?
    if ( pos.x <= BALLRADIUS ) {
        pos.x = BALLRADIUS;  // need to force this or else ball can end up going off screen
        vel.x = -0.5 * vel.x;  // reflect and damp velocity
        acc.x = -acc.x;  // reflect accleration
    }

}

void update_physics_engine()
{
    // from Newton's Laws

    acc.x = 0.9F*acc.x;  // reduce a little due to air friction

    // calc new velocity (assume 'unit' time)
    vel.x = vel.x + acc.x; // * g_gt;
    vel.y = vel.y + acc.y; // * g_gt;

    // calc new position (assume 'unit' time)
    pos.x = pos.x + vel.x;// * g_gt;
    pos.y = pos.y + vel.y;// * g_dt;
    
    // should really multiply the above by the time-step,
    // but since the pixel can only be a integer value,
    // it makes the motion a little 'jumpy'.

}

void init_ball()
{
    // initial position (top-left)
    pos.x = BALLRADIUS;
    pos.y = BALLRADIUS;
    // initial velocity - still
    vel.x = 0.0;
    vel.y = 0.0;
    // initial acceleration - gravity and a bit of push to right
    acc.x = 0.5;
    acc.y = 1.0;  // +ve so ball accelerates to bottom of display (top of screen is y=0, bottom is y=47)
    // should be 9.8, but can play with value to get a 'nice' ball movement
}

void game_timer_isr()
{
    g_timer_flag = 1;
}