ELEC2645 Embedded Systems Project (JOYSTICK)

Dependencies:   N5110 SDFileSystem mbed

main.cpp

Committer:
wuchyi
Date:
2016-05-05
Revision:
1:06958b7bbf65
Parent:
0:1719e11ef162
Child:
2:537b8388dc6a

File content as of revision 1:06958b7bbf65:

/*
Progress update:
Easter -- Added ticker for joystick update
            joystick initial position checker

week 22 -- main logic behind snake game added
            to do : wraparound (optional in main menu)
                    menu system - play game, settings(joy calibration, wraparound on//off) ; game over screen
*/


#include "mbed.h"
#include "N5110.h"
#include "SDFileSystem.h"
#define JOYSTICK_TOLERANCE 0.1 //direction tolerance of joystick

//          VCC,    SCE,  RST,    D/C,   MOSI,  SCLK,   LED
N5110 lcd (PTE26 , PTA0 , PTC4 , PTD0 , PTD2 , PTD1 , PTC3);
SDFileSystem sd(PTE3, PTE1, PTE2, PTE4, "sd");

void init_display();
void draw_screen();
void calibrate_joystick();
void joystick_pos();
void game_timer_isr();
void food_pos();
void snake_move();
void snake_logic_1();
float refresh_rate = 10; //refresh screen in Hz
volatile int g_timer_flag = 0;
bool gameOver; //if game has ended
int pdirection;
int gamemode;

const int width = (84 - 2) / 2 ; // screen width (playable area due to 2x size of snake)
const int height = (48 - 4) / 2 ; // screen height

Ticker gameTimer;
Ticker gameTimer1;
Ticker gameTimer2;
Ticker joystickTimer; // ticker timer for joystick poisition update
int fx,fy,Button,score; // global variables to hold data (control)
AnalogIn xAxis(A0);
AnalogIn yAxis(A1);
AnalogIn pot(A2);
DigitalOut red_led(LED_RED);



enum DirectionName { //joystick directions
    CENTRE,
    UP,
    LEFT,
    DOWN,
    RIGHT,
    UNKNOWN
};

;
// struct for joystick
typedef struct joystick1 Joystick;
struct joystick1 {
    float x;    // current x value
    float x0;   // 'centred' x value
    float y;    // current y value
    float y0;   // 'centred' y value
    int button; // button state (assume pull-down used, so 1 = pressed, 0 = unpressed)
    DirectionName direction;  // current direction
};

Joystick joystick;

typedef struct snake1 Snake;
struct snake1 {
    int hx; // head x value
    int hy; // head y value
    int length; // snake length
    int tailx[100],taily[100]; //tail coordinates array
};

Snake snake;



void init_display()
{
    lcd.init();
    lcd.normalMode();      // normal colour mode
    lcd.setBrightness(0.5); // put LED backlight on 50%
    lcd.clear(); // clear screen (init)
}

void adjust_brightness()
{
    int x = pot;
    lcd.setBrightness(x);
}


void draw_screen()
{
    lcd.clear();

    lcd.drawRect(0,1,83,45,0);    // borders square

    for (int q = 0; q < snake.length ; q++) { //print snake
        //lcd.setPixel (snake.tailx[q],snake.taily[q]);
        lcd.drawRect ((snake.tailx[q]*2),(snake.taily[q]*2),1,1,1);
        // red_led = 0;

    }
    //lcd.setPixel(snake.hx,snake.hy); //print snake head position
    lcd.drawRect ((fx * 2), (fy * 2), 1,1,1);
    //lcd.setPixel (fx,fy); //print food position
    lcd.refresh();  // update display

}

void game_timer_isr()
{
    g_timer_flag = 1;
}

void calibrate_joystick()
{
    //get initial joystick position as offset
    joystick.x0 = xAxis;
    joystick.y0 = yAxis;

}

void joystick_pos()
{
    joystick.x = xAxis - joystick.x0;
    joystick.y = yAxis - joystick.y0;

    if ( fabs(joystick.y) <= JOYSTICK_TOLERANCE && fabs(joystick.x) < JOYSTICK_TOLERANCE) {
        joystick.direction = CENTRE;
    } else if ( joystick.y > JOYSTICK_TOLERANCE && fabs(joystick.x) < JOYSTICK_TOLERANCE) {
        joystick.direction = UP;
    } else if ( joystick.y < JOYSTICK_TOLERANCE && fabs(joystick.x) < JOYSTICK_TOLERANCE) {
        joystick.direction = DOWN;
    } else if ( joystick.x > JOYSTICK_TOLERANCE && fabs(joystick.y) < JOYSTICK_TOLERANCE) {
        joystick.direction = RIGHT;
    } else if ( joystick.x < JOYSTICK_TOLERANCE && fabs(joystick.y) < JOYSTICK_TOLERANCE) {
        joystick.direction = LEFT;
    } else {
        joystick.direction = UNKNOWN;
    }

}


void snake_move() //move the coordinate of the snake head, if CENTRE, checks for pdirection and repeats.
{
    // red_led = 0;
    if (pdirection == 0 && joystick.direction == RIGHT) { // disable going backwards
        snake.hx--;
    } else if (pdirection == 1 && joystick.direction == DOWN) {
        snake.hy++;
    } else if (pdirection == 2 && joystick.direction == LEFT) {
        snake.hx++;
    } else if (pdirection == 3 && joystick.direction == UP) {
        snake.hy--;
    } else {

        if (joystick.direction == CENTRE) {
            if (pdirection == 0)  {
                snake.hx-- ;
            } else if (pdirection == 1) {
                snake.hy++ ;
            } else if (pdirection == 2) {
                snake.hx++ ;
            } else if (pdirection == 3) {
                snake.hy-- ;
            } else {
            }
        } else {
            if (joystick.direction == LEFT)  {
                snake.hx-- ;
                pdirection = 0;
            } else if (joystick.direction == UP) {
                snake.hy++ ;
                pdirection = 1;
            } else if (joystick.direction == RIGHT) {
                snake.hx++ ;
                pdirection = 2;
            } else if (joystick.direction == DOWN) {
                snake.hy-- ;
                pdirection = 3;
            } else {
            }

        }
    }
}

void game()
{
    //brightnessTimer.attach(adjust_brightness,0.1);
    joystickTimer.detach();
    gameTimer.detach();
    gameTimer1.detach();
    gameTimer2.detach();
    joystick.direction = CENTRE;
    // gamemode = 0;
    gameOver = false;
    snake.hx = width / 2; // initial position of snake head
    snake.hy = height / 2;
    food_pos();
    score = 0;
    pdirection = 1;
    snake.length = 4; //length including head and tail
    for (int w = 0 ; w < snake.length  ; w++) { //set initial snake position
        snake.tailx[w] = (snake.hx - w) ;
        snake.taily[w] = snake.hy;

    }
    //draw_screen();




    if (gamemode == 0) {
        while (!gameOver) {
            joystickTimer.attach(&joystick_pos, 0.1);
            // gameTimer.attach(&snake_move,0.2);
            gameTimer1.attach(&snake_logic_1,0.1);
            gameTimer2.attach(&draw_screen, 0.1);
            sleep();
        }
        if (gameOver == true) {
            gameTimer1.detach();
            gameTimer2.detach();
}
        }
    }

    void snake_logic_1() {
//red_led = 0;
        snake_move();
        for (int d = (snake.length) ; d > 0 ; d--) { //move all snake body one position back
            snake.tailx[d] = snake.tailx[d - 1];
            snake.taily[d] = snake.taily[d - 1];

        }
        snake.tailx[0] = snake.hx;
        snake.taily[0] = snake.hy;
        //  snake.hx = snake.tailx[0];
        // snake.hy = snake.taily[0];

        // snake_move();
        // draw_screen();

        for (int p = 1; p < snake.length + 1; p++) { //snake dies when come in contact with tail
            if (snake.tailx[0] == snake.tailx[p] && snake.taily[0] == snake.taily[p]) {
                gameOver = true;
                red_led = 0;
            }



        }

        if (snake.tailx[0] == 0 || snake.tailx[0] == width || snake.taily[0] == 1 || snake.taily[0] == height-1) {
            gameOver = true;
        }


        if (snake.tailx[0] == fx && snake.taily[0] == fy) { // snake grows when in contact with food
            score++;
            food_pos();
            snake.length++;
            // draw_screen();
        }
        //snake_move();
    }





    void food_pos() {
        srand(time(NULL));
        fx = rand() % (width - 3) + 2; // random x from 4 to width - 3 for x coordinate
        fy = rand() % (height - 3) + 2; // random y from 4 to height - 3 for y coordinate

    }

    void main_menu() {
        //brightnessTimer.attach(adjust_brightness,0.1);
        joystickTimer.attach(joystick_pos,0.1);
        int select = 0;
        while (1) {
            switch(select) {
                case 0:
                    switch(joystick.direction) {
                        case UP:
                            select = 1;
                            break;
                        case DOWN:
                            select = 1;
                            break;
                    }
                    break;
                case 1:
                    switch(joystick.direction) {
                        case UP:
                            select = 0;
                            break;
                        case DOWN:
                            select = 0;
                            break;
                    }
                    break;
            }
            wait(0.1);
            if (select == 0) {
                lcd.clear();
                lcd.printString("Start Game",7,0);
                lcd.printString("Settings",7,1);
                lcd.drawCircle(3,3,2,1);
                lcd.refresh();
            } else if (select == 1) {
                lcd.clear();
                lcd.printString("Start Game", 7,0);
                lcd.printString("Settings",7,1);
                lcd.drawCircle(3,11,2,1);
                lcd.refresh();
            }
        }
    }

    int main() {
        init_display();
        //brightnessTimer.attach(adjust_brightness,0.1);
        joystickTimer.attach(joystick_pos,0.1);
        calibrate_joystick();
        gamemode = 0;
        //lcd.printString("Hello, World!",0,0);
        //main_menu();
        red_led = 1;
        game();
        /*while(1) {

            lcd.clear();
            if (joystick.direction == UP) {
                lcd.printString ("UP",1,0);
            } else if (joystick.direction == CENTRE) {
                lcd.printString ("CENTRE",1,0);
           } else if (joystick.direction == DOWN) {
                lcd.printString ("DOWN",1,0);
            } else if (joystick.direction == LEFT) {
                lcd.printString ("LEFT",1,0);
            } else if (joystick.direction == RIGHT) {
                lcd.printString ("RIGHT",1,0);
            } else {
                lcd.printString ("UNKNOWN",1,0);
            }
            lcd.refresh();
            wait(1);
        }
        */


    }