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"
4
 
5
static SNAKE_DATA *data_p;
6
 
7
void Snake_Init(SNAKE_DATA *data) {
8
    data_p = data;
9
 
10
    // Disable watchdog timer
11
    WDTCON = 0x00000000;
12
 
13
    // Set starting point
14
    data_p->body[0].x = 0;
15
    data_p->body[0].y = 0;
16
    data_p->body[0].z = 0;
17
 
18
    data_p->pos_head = 0;
19
    data_p->pos_tail = 0;
20
    data_p->length = 1;
21
    data_p->level = 1;
22
    data_p->delay = 800;
23
 
24
    // Generate a starting location for the candy
25
    data_p->candy_loc = Snake_Generate_Candy();
26
 
27
    // Draw the snake (head)
28
    Cube_Clear();
29
    uint32_t index = data_p->pos_head;
30
    Cube_Set_Pixel(data_p->body[index].z, data_p->body[index].x, data_p->body[index].y, SNAKE_HEAD_COLOR);
31
    while (index != data_p->pos_tail) {
32
        if (data_p->length > 1) {
33
            index = (index == 0) ? CUBE_PIXELS - 1 : index - 1;
34
            Cube_Set_Pixel(data_p->body[index].z, data_p->body[index].x, data_p->body[index].y, SNAKE_BODY_COLOR);
35
        }
36
    }
37
}
38
 
39
void Snake_Main(void) {
40
    Delay_MS(2000);
41
    while (1) {
42
        Snake_Update_Frame();
43
        Delay_MS(data_p->delay);
44
    }
45
}
46
 
47
void Snake_Update_Direction(uint8_t p1, uint8_t p2) {
48
    // Determine the next direction for the snake based off the last button press
49
    SNAKE_DIRECTION dir;
50
    dir.value = p1 | p2;
51
    data_p->last_direction = dir.value;
52
 
53
    SNAKE_POINT point = data_p->body[data_p->pos_head];
54
 
55
    if (dir.up) {
56
        point.z = (point.z == CUBE_LAYER_COUNT - 1) ? 0 : point.z + 1;
57
    } else if (dir.down) {
58
        point.z = (point.z == 0) ? CUBE_LAYER_COUNT - 1 : point.z - 1;
59
    } else if (dir.forward) {
60
        point.x = (point.x == CUBE_ROW_COUNT - 1) ? 0 : point.x + 1;
61
    } else if (dir.right) {
62
        point.y = (point.y == CUBE_COLUMN_COUNT - 1) ? 0 : point.y + 1;
63
    } else if (dir.backward) {
64
        point.x = (point.x == 0) ? CUBE_ROW_COUNT - 1 : point.x - 1;
65
    } else if (dir.left) {
66
        point.y = (point.y== 0) ? CUBE_COLUMN_COUNT - 1 : point.y - 1;
67
    }
68
 
69
    data_p->direction = point;
70
 
71
    // Update the overlay with the candy location
72
    Cube_Overlay_Clear();
73
    Cube_Overlay_Set_Pixel(data_p->candy_loc.z, data_p->candy_loc.x, data_p->candy_loc.y, SNAKE_CANDY_COLOR);
74
}
75
 
76
void Snake_Update_Frame(void) {
77
    uint8_t om_nom_nom = 0;
78
 
79
    // Check if we are moving onto a candy, if so extend body
80
    if (data_p->direction.x == data_p->candy_loc.x &&
81
            data_p->direction.y == data_p->candy_loc.y &&
82
            data_p->direction.z == data_p->candy_loc.z) {
83
        data_p->pos_head = (data_p->pos_head == CUBE_PIXELS - 1) ? 0 : data_p->pos_head + 1;
84
        data_p->body[data_p->pos_head] = data_p->direction;
85
        data_p->length++;
86
        data_p->candy_loc = Snake_Generate_Candy();
87
        om_nom_nom = 1;
88
    }
89
 
90
    // Check if the location that we are moving to is overlapping the body
91
    uint32_t pos = data_p->pos_tail;
92
    while (pos != data_p->pos_head) {
93
        if (data_p->direction.x == data_p->body[pos].x &&
94
                data_p->direction.y == data_p->body[pos].y &&
95
                data_p->direction.z == data_p->body[pos].z) {
96
            Cube_Overlay_Set_Pixel(data_p->direction.z, data_p->direction.x, data_p->direction.y, SNAKE_HEAD_COLOR);
97
            Delay_MS(3000);
98
            Reset_Board(BOARD_MODE_IDLE);
99
        }
100
        pos = (pos == CUBE_PIXELS - 1) ? 0 : pos + 1;
101
    }
102
 
103
    // If we didnt eat a candy, increment the frame to move the body along
104
    if (!om_nom_nom) {
105
        data_p->pos_head = (data_p->pos_head == CUBE_PIXELS - 1) ? 0 : data_p->pos_head + 1;
106
        data_p->pos_tail = (data_p->pos_tail == CUBE_PIXELS - 1) ? 0 : data_p->pos_tail + 1;
107
        data_p->body[data_p->pos_head] = data_p->direction;
108
    }
109
 
110
    // Draw updated snake location
111
    Cube_Clear();
112
    uint32_t index = data_p->pos_head;
113
    Cube_Set_Pixel(data_p->body[index].z, data_p->body[index].x, data_p->body[index].y, SNAKE_HEAD_COLOR);
114
    while (index != data_p->pos_tail) {
115
        if (data_p->length > 1) {
116
            index = (index == 0) ? CUBE_PIXELS - 1 : index - 1;
117
            Cube_Set_Pixel(data_p->body[index].z, data_p->body[index].x, data_p->body[index].y, SNAKE_BODY_COLOR);
118
        }
119
    }
120
 
121
    // Determine the next direction to take
122
    Snake_Update_Direction(data_p->last_direction, 0x0);
123
 
124
    // If we ate a candy, delay for a bit to rest
125
    if (om_nom_nom) {
126
        data_p->level += 1; // Increase the level by one
127
        if (data_p->level % SNAKE_LEVEL_STEP == 0) {
128
            uint8_t tier = data_p->level / SNAKE_LEVEL_STEP;
129
            Controller_Set_Leds(tier, tier);
130
        }
131
        data_p->delay -= 5; // Decrease the delay between frame updates by 5ms
132
    }
133
}
134
 
135
SNAKE_POINT Snake_Generate_Candy(void) {
136
    // Generates a random position within the cube that doesnt overlap anything
137
    SNAKE_POINT ret;
138
    uint32_t x, y, z, brk = 0;
139
    while(1) {
140
        x = rand() % 8;
141
        y = rand() % 8;
142
        z = rand() % 8;
143
 
144
        if (data_p->length != 1) {
145
            uint32_t pos = data_p->pos_tail;
146
            uint32_t overlap = 0;
147
            // Iterate through the frame till we finish or find an overlap
148
            while (pos != data_p->pos_head) {
149
                if (data_p->body[pos].x == x &&
150
                        data_p->body[pos].y == y &&
151
                        data_p->body[pos].z == z) {
152
                    overlap = 1;
153
                    break;
154
                } else {
155
                    pos = (pos == CUBE_PIXELS - 1) ? 0 : pos + 1;
156
                }
157
            }
158
            if (!overlap)
159
                brk = 1;
160
        } else {
161
            uint32_t pos = data_p->pos_tail;
162
            if (data_p->body[pos].x != x &&
163
                    data_p->body[pos].y != y &&
164
                    data_p->body[pos].z != z) {
165
                brk = 1;
166
            }
167
        }
168
 
169
        if (brk)
170
            break;
171
    }
172
 
173
    ret.x = x;
174
    ret.y = y;
175
    ret.z = z;
176
    return ret;
177
}