Subversion Repositories Code-Repo

Compare Revisions

Ignore whitespace Rev 277 → Rev 278

/PIC Stuff/Cerebot_32MX7_LED_Cube/SNAKE.c
3,36 → 3,38
#include "SNAKE.h"
#include "TIMER4.h"
 
static SNAKE_DATA *data_p;
static SNAKE_DATA *snake_data_p;
static uint32_t rand_value __attribute__((persistent));
 
void Snake_Init(SNAKE_DATA *data) {
data_p = data;
snake_data_p = data;
 
// Set starting point
data_p->body[0] = (SNAKE_POINT){0,0,7};
snake_data_p->body[0] = (SNAKE_POINT){0,0,7};
 
data_p->pos_head = 0;
data_p->pos_tail = 0;
data_p->length = 1;
data_p->level = 0;
data_p->delay = SNAKE_MAXIMUM_DELAY;
data_p->direction = (SNAKE_POINT){1,0,7};
data_p->last_direction = 0x08;
snake_data_p->pos_head = 0;
snake_data_p->pos_tail = 0;
snake_data_p->length = 1;
snake_data_p->level = 0;
snake_data_p->delay = SNAKE_MAXIMUM_DELAY;
 
// Initialize the starting direction
snake_data_p->direction = (SNAKE_POINT){1,0,7};
snake_data_p->last_direction = 0x08;
 
srand(rand_value);
 
// Generate a starting location for the candy
data_p->candy_loc = Snake_Generate_Candy();
snake_data_p->candy_loc = Snake_Generate_Candy();
 
// Draw the snake (head)
Cube_Clear();
uint32_t index = data_p->pos_head;
Cube_Set_Pixel(data_p->body[index].z, data_p->body[index].x, data_p->body[index].y, SNAKE_HEAD_COLOR);
while (index != data_p->pos_tail) {
if (data_p->length > 1) {
uint32_t index = snake_data_p->pos_head;
Cube_Set_Pixel(snake_data_p->body[index].z, snake_data_p->body[index].x, snake_data_p->body[index].y, SNAKE_HEAD_COLOR);
while (index != snake_data_p->pos_tail) {
if (snake_data_p->length > 1) {
index = (index == 0) ? CUBE_PIXELS - 1 : index - 1;
Cube_Set_Pixel(data_p->body[index].z, data_p->body[index].x, data_p->body[index].y, SNAKE_BODY_COLOR);
Cube_Set_Pixel(snake_data_p->body[index].z, snake_data_p->body[index].x, snake_data_p->body[index].y, SNAKE_BODY_COLOR);
}
}
}
40,11 → 42,13
void Snake_Main(void) {
// Main function, loops and delays while updating the frame every x milliseconds
 
// Ensure that a controller is connected before starting
while(!Controller_Get_Connected()) {
Delay_MS(100);
Controller_Poll_Connected();
}
 
// Set the first controller as active and indicate it on its LEDs
Controller_Set_Active(0);
Delay_MS(20);
Controller_Set_Left_Leds(0, 0x1);
55,7 → 59,7
rand_value = rand();
 
Snake_Update_Frame();
Delay_MS(data_p->delay);
Delay_MS(snake_data_p->delay);
}
}
 
62,8 → 66,8
void Snake_Update_Direction(uint8_t controller, CTRL_BTN_STATUS value) {
// Determine the next direction for the snake based off the last button press
if (controller == 0) {
data_p->last_direction = value.w;
SNAKE_POINT point = data_p->body[data_p->pos_head];
snake_data_p->last_direction = value.w;
SNAKE_POINT point = snake_data_p->body[snake_data_p->pos_head];
 
if (value.BTN_L_N || value.BTN_L_E) { // Up
point.z = (point.z == CUBE_LAYER_COUNT - 1) ? 0 : point.z + 1;
79,12 → 83,12
point.y = (point.y== 0) ? CUBE_COLUMN_COUNT - 1 : point.y - 1;
}
 
data_p->direction = point;
snake_data_p->direction = point;
}
 
// Update the overlay with the candy location
Cube_Overlay_Clear();
Cube_Overlay_Set_Pixel(data_p->candy_loc.z, data_p->candy_loc.x, data_p->candy_loc.y, SNAKE_CANDY_COLOR);
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);
}
 
void Snake_Update_Frame(void) {
91,24 → 95,24
uint8_t om_nom_nom = 0;
 
// Check if we are moving onto a candy, if so extend body
if (data_p->direction.x == data_p->candy_loc.x &&
data_p->direction.y == data_p->candy_loc.y &&
data_p->direction.z == data_p->candy_loc.z) {
data_p->pos_head = (data_p->pos_head == CUBE_PIXELS - 1) ? 0 : data_p->pos_head + 1;
data_p->body[data_p->pos_head] = data_p->direction;
data_p->length++;
data_p->candy_loc = Snake_Generate_Candy();
if (snake_data_p->direction.x == snake_data_p->candy_loc.x &&
snake_data_p->direction.y == snake_data_p->candy_loc.y &&
snake_data_p->direction.z == snake_data_p->candy_loc.z) {
snake_data_p->pos_head = (snake_data_p->pos_head == CUBE_PIXELS - 1) ? 0 : snake_data_p->pos_head + 1;
snake_data_p->body[snake_data_p->pos_head] = snake_data_p->direction;
snake_data_p->length++;
snake_data_p->candy_loc = Snake_Generate_Candy();
om_nom_nom = 1;
}
 
// Check if the location that we are moving to is overlapping the body
uint32_t pos = data_p->pos_tail;
while (pos != data_p->pos_head) {
if (data_p->direction.x == data_p->body[pos].x &&
data_p->direction.y == data_p->body[pos].y &&
data_p->direction.z == data_p->body[pos].z) {
uint32_t pos = snake_data_p->pos_tail;
while (pos != snake_data_p->pos_head) {
if (snake_data_p->direction.x == snake_data_p->body[pos].x &&
snake_data_p->direction.y == snake_data_p->body[pos].y &&
snake_data_p->direction.z == snake_data_p->body[pos].z) {
// Indicate the overlapping pixel, delay, then return to idle state
Cube_Set_Pixel(data_p->direction.z, data_p->direction.x, data_p->direction.y, SNAKE_COLLISION_COLOR);
Cube_Set_Pixel(snake_data_p->direction.z, snake_data_p->direction.x, snake_data_p->direction.y, SNAKE_COLLISION_COLOR);
Delay_MS(3000);
Cube_Overlay_Clear();
Animation_Cube_In_Out(200, ORANGE);
119,39 → 123,39
 
// If we didnt eat a candy, increment the frame to move the body along
if (!om_nom_nom) {
data_p->pos_head = (data_p->pos_head == CUBE_PIXELS - 1) ? 0 : data_p->pos_head + 1;
data_p->pos_tail = (data_p->pos_tail == CUBE_PIXELS - 1) ? 0 : data_p->pos_tail + 1;
data_p->body[data_p->pos_head] = data_p->direction;
snake_data_p->pos_head = (snake_data_p->pos_head == CUBE_PIXELS - 1) ? 0 : snake_data_p->pos_head + 1;
snake_data_p->pos_tail = (snake_data_p->pos_tail == CUBE_PIXELS - 1) ? 0 : snake_data_p->pos_tail + 1;
snake_data_p->body[snake_data_p->pos_head] = snake_data_p->direction;
}
 
// Draw updated snake location
Cube_Clear();
uint32_t index = data_p->pos_head;
Cube_Set_Pixel(data_p->body[index].z, data_p->body[index].x, data_p->body[index].y, SNAKE_HEAD_COLOR);
while (index != data_p->pos_tail) {
if (data_p->length > 1) {
uint32_t index = snake_data_p->pos_head;
Cube_Set_Pixel(snake_data_p->body[index].z, snake_data_p->body[index].x, snake_data_p->body[index].y, SNAKE_HEAD_COLOR);
while (index != snake_data_p->pos_tail) {
if (snake_data_p->length > 1) {
index = (index == 0) ? CUBE_PIXELS - 1 : index - 1;
Cube_Set_Pixel(data_p->body[index].z, data_p->body[index].x, data_p->body[index].y, SNAKE_BODY_COLOR);
Cube_Set_Pixel(snake_data_p->body[index].z, snake_data_p->body[index].x, snake_data_p->body[index].y, SNAKE_BODY_COLOR);
}
}
 
// Determine the next direction to take
Snake_Update_Direction(0, (CTRL_BTN_STATUS)data_p->last_direction);
// Determine the next point to move to
Snake_Update_Direction(0, (CTRL_BTN_STATUS)snake_data_p->last_direction);
 
// If we ate a candy, delay for a bit to rest
if (om_nom_nom) {
// Increase the level by one
data_p->level += 1;
snake_data_p->level += 1;
 
TIMER4_Stop();
Controller_Set_Middle_Leds(0, data_p->level);
if (data_p->level >= 256)
Controller_Set_Middle_Leds(0, snake_data_p->level);
if (snake_data_p->level >= 256)
Controller_Set_Left_Leds(0, 0x9);
TIMER4_Start();
 
// Decrease the delay between frame updates by 5ms
if (data_p->delay > SNAKE_MINIMUM_DELAY)
data_p->delay -= 5;
if (snake_data_p->delay > SNAKE_MINIMUM_DELAY)
snake_data_p->delay -= 5;
// Clear the watchdog timer to prevent resets in a middle of a game
ClearWDT();
}
166,14 → 170,14
y = rand() % 8;
z = rand() % 8;
 
if (data_p->length != 1) {
uint32_t pos = data_p->pos_tail;
if (snake_data_p->length != 1) {
uint32_t pos = snake_data_p->pos_tail;
uint32_t overlap = 0;
// Iterate through the frame till we finish or find an overlap
while (pos != data_p->pos_head) {
if (data_p->body[pos].x == x &&
data_p->body[pos].y == y &&
data_p->body[pos].z == z) {
while (pos != snake_data_p->pos_head) {
if (snake_data_p->body[pos].x == x &&
snake_data_p->body[pos].y == y &&
snake_data_p->body[pos].z == z) {
overlap = 1;
break;
} else {
183,10 → 187,10
if (!overlap)
brk = 1;
} else {
uint32_t pos = data_p->pos_tail;
if (data_p->body[pos].x != x &&
data_p->body[pos].y != y &&
data_p->body[pos].z != z) {
uint32_t pos = snake_data_p->pos_tail;
if (snake_data_p->body[pos].x != x &&
snake_data_p->body[pos].y != y &&
snake_data_p->body[pos].z != z) {
brk = 1;
}
}