Subversion Repositories Code-Repo

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
240 Kevin 1
#include "defines.h"
2
#include "CONTROLLERS.h"
3
#include "SNAKE.h"
276 Kevin 4
#include "TIMER4.h"
240 Kevin 5
 
6
static SNAKE_DATA *data_p;
242 Kevin 7
static uint32_t rand_value __attribute__((persistent));
240 Kevin 8
 
9
void Snake_Init(SNAKE_DATA *data) {
10
    data_p = data;
11
 
12
    // Set starting point
241 Kevin 13
    data_p->body[0] = (SNAKE_POINT){0,0,7};
240 Kevin 14
 
15
    data_p->pos_head = 0;
16
    data_p->pos_tail = 0;
17
    data_p->length = 1;
276 Kevin 18
    data_p->level = 0;
19
    data_p->delay = SNAKE_MAXIMUM_DELAY;
20
    data_p->direction = (SNAKE_POINT){1,0,7};
21
    data_p->last_direction = 0x08;
240 Kevin 22
 
242 Kevin 23
    srand(rand_value);
24
 
240 Kevin 25
    // Generate a starting location for the candy
26
    data_p->candy_loc = Snake_Generate_Candy();
27
 
28
    // Draw the snake (head)
29
    Cube_Clear();
30
    uint32_t index = data_p->pos_head;
31
    Cube_Set_Pixel(data_p->body[index].z, data_p->body[index].x, data_p->body[index].y, SNAKE_HEAD_COLOR);
32
    while (index != data_p->pos_tail) {
33
        if (data_p->length > 1) {
34
            index = (index == 0) ? CUBE_PIXELS - 1 : index - 1;
35
            Cube_Set_Pixel(data_p->body[index].z, data_p->body[index].x, data_p->body[index].y, SNAKE_BODY_COLOR);
36
        }
37
    }
38
}
39
 
40
void Snake_Main(void) {
241 Kevin 41
    // Main function, loops and delays while updating the frame every x milliseconds
276 Kevin 42
 
43
    while(!Controller_Get_Connected()) {
44
        Delay_MS(100);
45
        Controller_Poll_Connected();
46
    }
47
 
48
    Controller_Set_Active(0);
49
    Delay_MS(20);
50
    Controller_Set_Left_Leds(0, 0x1);
51
    TIMER4_Start();
52
    Delay_MS(1000);
240 Kevin 53
    while (1) {
242 Kevin 54
        // Regenerate the seed upon each update so that the candy starts somewhere new every time
55
        rand_value = rand();
276 Kevin 56
 
240 Kevin 57
        Snake_Update_Frame();
58
        Delay_MS(data_p->delay);
59
    }
60
}
61
 
276 Kevin 62
void Snake_Update_Direction(uint8_t controller, CTRL_BTN_STATUS value) {
240 Kevin 63
    // Determine the next direction for the snake based off the last button press
276 Kevin 64
    if (controller == 0) {
65
        data_p->last_direction = value.w;
66
        SNAKE_POINT point = data_p->body[data_p->pos_head];
240 Kevin 67
 
276 Kevin 68
        if (value.BTN_L_N || value.BTN_L_E) {    // Up
69
            point.z = (point.z == CUBE_LAYER_COUNT - 1) ? 0 : point.z + 1;
70
        } else if (value.BTN_L_W || value.BTN_L_S) { // Down
71
            point.z = (point.z == 0) ? CUBE_LAYER_COUNT - 1 : point.z - 1;
72
        } else if (value.BTN_R_N) { // Forward
73
            point.x = (point.x == CUBE_ROW_COUNT - 1) ? 0 : point.x + 1;
74
        } else if (value.BTN_R_W) { // Right
75
            point.y = (point.y == CUBE_COLUMN_COUNT - 1) ? 0 : point.y + 1;
76
        } else if (value.BTN_R_S) { // Backward
77
            point.x = (point.x == 0) ? CUBE_ROW_COUNT - 1 : point.x - 1;
78
        } else if (value.BTN_R_E) { // Left
79
            point.y = (point.y== 0) ? CUBE_COLUMN_COUNT - 1 : point.y - 1;
80
        }
81
 
82
        data_p->direction = point;
240 Kevin 83
    }
84
 
85
    // Update the overlay with the candy location
86
    Cube_Overlay_Clear();
87
    Cube_Overlay_Set_Pixel(data_p->candy_loc.z, data_p->candy_loc.x, data_p->candy_loc.y, SNAKE_CANDY_COLOR);
88
}
89
 
90
void Snake_Update_Frame(void) {
91
    uint8_t om_nom_nom = 0;
92
 
93
    // Check if we are moving onto a candy, if so extend body
94
    if (data_p->direction.x == data_p->candy_loc.x &&
95
            data_p->direction.y == data_p->candy_loc.y &&
96
            data_p->direction.z == data_p->candy_loc.z) {
97
        data_p->pos_head = (data_p->pos_head == CUBE_PIXELS - 1) ? 0 : data_p->pos_head + 1;
98
        data_p->body[data_p->pos_head] = data_p->direction;
99
        data_p->length++;
100
        data_p->candy_loc = Snake_Generate_Candy();
101
        om_nom_nom = 1;
102
    }
103
 
104
    // Check if the location that we are moving to is overlapping the body
105
    uint32_t pos = data_p->pos_tail;
106
    while (pos != data_p->pos_head) {
107
        if (data_p->direction.x == data_p->body[pos].x &&
108
                data_p->direction.y == data_p->body[pos].y &&
109
                data_p->direction.z == data_p->body[pos].z) {
241 Kevin 110
            // Indicate the overlapping pixel, delay, then return to idle state
242 Kevin 111
            Cube_Set_Pixel(data_p->direction.z, data_p->direction.x, data_p->direction.y, SNAKE_COLLISION_COLOR);
240 Kevin 112
            Delay_MS(3000);
242 Kevin 113
            Cube_Overlay_Clear();
114
            Animation_Cube_In_Out(200, ORANGE);
240 Kevin 115
            Reset_Board(BOARD_MODE_IDLE);
116
        }
117
        pos = (pos == CUBE_PIXELS - 1) ? 0 : pos + 1;
118
    }
119
 
120
    // If we didnt eat a candy, increment the frame to move the body along
121
    if (!om_nom_nom) {
122
        data_p->pos_head = (data_p->pos_head == CUBE_PIXELS - 1) ? 0 : data_p->pos_head + 1;
123
        data_p->pos_tail = (data_p->pos_tail == CUBE_PIXELS - 1) ? 0 : data_p->pos_tail + 1;
124
        data_p->body[data_p->pos_head] = data_p->direction;
125
    }
126
 
127
    // Draw updated snake location
128
    Cube_Clear();
129
    uint32_t index = data_p->pos_head;
130
    Cube_Set_Pixel(data_p->body[index].z, data_p->body[index].x, data_p->body[index].y, SNAKE_HEAD_COLOR);
131
    while (index != data_p->pos_tail) {
132
        if (data_p->length > 1) {
133
            index = (index == 0) ? CUBE_PIXELS - 1 : index - 1;
134
            Cube_Set_Pixel(data_p->body[index].z, data_p->body[index].x, data_p->body[index].y, SNAKE_BODY_COLOR);
135
        }
136
    }
137
 
138
    // Determine the next direction to take
276 Kevin 139
    Snake_Update_Direction(0, (CTRL_BTN_STATUS)data_p->last_direction);
240 Kevin 140
 
141
    // If we ate a candy, delay for a bit to rest
142
    if (om_nom_nom) {
276 Kevin 143
        // Increase the level by one
241 Kevin 144
        data_p->level += 1;
276 Kevin 145
 
146
        TIMER4_Stop();
147
        Controller_Set_Middle_Leds(0, data_p->level);
148
        if (data_p->level >= 256)
149
            Controller_Set_Left_Leds(0, 0x9);
150
        TIMER4_Start();
151
 
241 Kevin 152
        // Decrease the delay between frame updates by 5ms
276 Kevin 153
        if (data_p->delay > SNAKE_MINIMUM_DELAY)
154
            data_p->delay -= 5;
241 Kevin 155
        // Clear the watchdog timer to prevent resets in a middle of a game
156
        ClearWDT();
240 Kevin 157
    }
158
}
159
 
160
SNAKE_POINT Snake_Generate_Candy(void) {
161
    // Generates a random position within the cube that doesnt overlap anything
162
    SNAKE_POINT ret;
163
    uint32_t x, y, z, brk = 0;
164
    while(1) {
165
        x = rand() % 8;
166
        y = rand() % 8;
167
        z = rand() % 8;
168
 
169
        if (data_p->length != 1) {
170
            uint32_t pos = data_p->pos_tail;
171
            uint32_t overlap = 0;
172
            // Iterate through the frame till we finish or find an overlap
173
            while (pos != data_p->pos_head) {
174
                if (data_p->body[pos].x == x &&
175
                        data_p->body[pos].y == y &&
176
                        data_p->body[pos].z == z) {
177
                    overlap = 1;
178
                    break;
179
                } else {
180
                    pos = (pos == CUBE_PIXELS - 1) ? 0 : pos + 1;
181
                }
182
            }
183
            if (!overlap)
184
                brk = 1;
185
        } else {
186
            uint32_t pos = data_p->pos_tail;
187
            if (data_p->body[pos].x != x &&
188
                    data_p->body[pos].y != y &&
189
                    data_p->body[pos].z != z) {
190
                brk = 1;
191
            }
192
        }
193
 
194
        if (brk)
195
            break;
196
    }
197
 
198
    ret.x = x;
199
    ret.y = y;
200
    ret.z = z;
201
    return ret;
202
}