Subversion Repositories Code-Repo

Rev

Rev 276 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

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