simple snake game

Dependencies:   C12832_lcd EthernetInterface WebSocketClient mbed-rtos mbed

Snake.cpp

Committer:
lyukx
Date:
2016-12-08
Revision:
0:2e5a51003afe

File content as of revision 0:2e5a51003afe:

#include "Snake.h"

// Record snake nodes' positions, max length is 100
int snake_body[2][100];
// Record snake length
int snake_length;
// Record the food place
int food[2];

C12832_LCD lcd;
Timer t;

int raw[1280];
// Raw data of the screen
// 0 - Nothing
// 1 - Food
// 2 - Snake head
// 3 - Snake body
// 4 - Snake tail
// 5 - Wall
// loc(x, y) -> raw[x + y * 40]

char lcd_data[160]; // Save the all screen data

Bitmap lcd_bmp = {
    40, // XSize
    32, // YSize
    5, // Bytes in Line
    lcd_data,  // Pointer to picture data 
};

void Screen::init(){
    // Initial the screen
    lcd.cls();
    lcd.setmode(XOR);
    
    for(int i = 0; i < 1280; i++){
        raw[i] = 0;
    }
    // Draw the wall
    for(int i = 0; i < 40; i++){
        raw[i] = 5;
        raw[i + 31 * 40] = 5;
    }
    for(int i = 0; i < 32; i++){
        raw[i * 40] = 5;
        raw[39 + i * 40] = 5;
    }
    // Draw the snake
    raw[snake_body[0][0] + snake_body[1][0] * 40] = 2;
    raw[snake_body[0][snake_length - 1] + snake_body[1][snake_length - 1] * 40] = 4;
    for(int i = 1; i < snake_length - 1; i++){
        raw[snake_body[0][i] + snake_body[1][i] * 40] = 3;
    }
    
    // Draw the food
    raw[food[0] + food[1] * 40] = 1;
    
    srand(t.read_ms());
    
    return;
}

void Screen::generate_lcd(){
    for(int i = 0; i < 32; i++){
        for(int j = 0; j < 5; j++){
            char temp_c = 0x00;
            for(int k = 0; k < 8; k++){
                int temp = raw[k + j * 8 + i * 40];
                temp_c = (temp_c << 1);
                if(temp > 0){
                    temp_c = temp_c + 0x01;
                }
                else{
                    temp_c = temp_c + 0x00;
                }
            }
            lcd_data[i * 5 + j] = temp_c;
        }
    }
    return;
}

void Screen::write_to_screen(){
    lcd.cls();
    lcd.print_bm(lcd_bmp,0,0);
    lcd.copy_to_lcd();
    return;
}

void SnakeControll::init(){
    snake_length = 3;       // Initialize the snake with 3 nodes
    snake_body[0][0] = 18;
    snake_body[1][0] = 16;
    snake_body[0][1] = 19;
    snake_body[1][1] = 16;
    snake_body[0][2] = 20;
    snake_body[1][2] = 16;
    direction = 0;
    
    // Initialize the food place
    food[0] = 10;
    food[1] = 16;
    
    // Initialize the points
    point = 0;
    
    // Initialize the timer
    t.start();
    return;
}

int SnakeControll::step(){
    int step_direction[2];
    switch(direction){
        case 0: step_direction[0] = -1;     // Left
                    step_direction[1] = 0;
                    break;
        case 1: step_direction[0] = 1;      // Right
                    step_direction[1] = 0;
                    break;
        case 2: step_direction[0] = 0;      // Up
                    step_direction[1] = -1;
                    break;
        case 3: step_direction[0] = 0;      // Down
                    step_direction[1] = 1;
                    break;
    }
    // Snake moves
    int temp_tail[2];
    temp_tail[0] = snake_body[0][snake_length - 1];
    temp_tail[1] = snake_body[1][snake_length - 1];
    raw[snake_body[0][snake_length - 1] + snake_body[1][snake_length - 1] * 40] = 0;
    for(int i = snake_length - 1; i >0; i--){
        snake_body[0][i] = snake_body[0][i - 1];
        snake_body[1][i] = snake_body[1][i - 1];
    }
    snake_body[0][0] = snake_body[0][0] + step_direction[0];
    snake_body[1][0] = snake_body[1][0] + step_direction[1];
    int temp = raw[snake_body[0][0] + snake_body[1][0] * 40];
    raw[snake_body[0][snake_length - 1] + snake_body[1][snake_length - 1] * 40] = 4;
    raw[snake_body[0][0] + snake_body[1][0] * 40] = 2;
    raw[snake_body[0][1] + snake_body[1][1] * 40] = 3;
        
    if(temp > 1){ // Hit something except food
        raw[snake_body[0][snake_length - 1] + snake_body[1][snake_length - 1] * 40] = 4;
        return 1;
    }
    if(temp == 1){  // Eat a food
        point++;
        raw[snake_body[0][snake_length - 1] + snake_body[1][snake_length - 1] * 40] = 3;
        if(snake_length <= 100){
            snake_length++;
            snake_body[0][snake_length - 1] = temp_tail[0];
            snake_body[1][snake_length - 1] = temp_tail[1];
            raw[snake_body[0][snake_length - 1] + snake_body[1][snake_length - 1] * 40] = 4;
        }
        generate_food();
        return 0;
    }
    else{ // Not hit
        return 0;
    }
}

void SnakeControll::set_direction(int d){
    if(d >= 0){
        direction = d;
    }
    return;
}

void SnakeControll::generate_food(){
    int x = (rand() % 40);
    int y = (rand() % 32);
    while(raw[x + y * 40] > 0){
        x = (rand() % 40);
        y = (rand() % 32);
    }
    food[0] = x;
    food[1] = y;
    raw[food[0]+food[1]*40] = 1;
}

string SnakeControll::get_gamedata(){
    string temp_json;
    temp_json = "{body:[";
    
    temp_json.append(pos2str(snake_body[0][0], snake_body[1][0]));

    for(int i = 1; i < snake_length; i++){
        temp_json.append(",");
        temp_json.append(pos2str(snake_body[0][i], snake_body[1][i]));
    }
    temp_json.append("],length:");
    temp_json.append(num2str(snake_length));
    temp_json.append(",food:");
    temp_json.append(pos2str(food[0], food[1]));
    temp_json.append("}");
    
    return temp_json;
}

string SnakeControll::num2str(int num){
    char temp[3];   // Max snake length is 100
    sprintf(temp, "%d", num);
    string temp_str = temp;
    return temp_str;
}

string SnakeControll::pos2str(int x, int y){
    char temp[7];   // [xx,xx] 7 chars
    sprintf(temp, "[%d,%d]", x, y);
    string temp_str = temp;
    return temp_str;
}