Rev 276 | Blame | Last modification | View Log | RSS feed
#include "defines.h"
#include "CONTROLLERS.h"
#include "TRON.h"
#include "TIMER4.h"
static TRON_DATA *tron_data_p;
void Tron_Init(TRON_DATA *data) {
tron_data_p = data;
// Set players 1-4 colors
tron_data_p->Color_Head_R[0] = 0xFF;
tron_data_p->Color_Head_G[0] = 0x00;
tron_data_p->Color_Head_B[0] = 0x00;
tron_data_p->Color_Body_R[0] = 0x20;
tron_data_p->Color_Body_G[0] = 0x00;
tron_data_p->Color_Body_B[0] = 0x00;
tron_data_p->Color_Head_R[1] = 0x00;
tron_data_p->Color_Head_G[1] = 0x00;
tron_data_p->Color_Head_B[1] = 0xFF;
tron_data_p->Color_Body_R[1] = 0x00;
tron_data_p->Color_Body_G[1] = 0x00;
tron_data_p->Color_Body_B[1] = 0x20;
tron_data_p->Color_Head_R[2] = 0x00;
tron_data_p->Color_Head_G[2] = 0xFF;
tron_data_p->Color_Head_B[2] = 0x00;
tron_data_p->Color_Body_R[2] = 0x00;
tron_data_p->Color_Body_G[2] = 0x20;
tron_data_p->Color_Body_B[2] = 0x00;
tron_data_p->Color_Head_R[3] = 0xFF;
tron_data_p->Color_Head_G[3] = 0x60;
tron_data_p->Color_Head_B[3] = 0x00;
tron_data_p->Color_Body_R[3] = 0x20;
tron_data_p->Color_Body_G[3] = 0x10;
tron_data_p->Color_Body_B[3] = 0x00;
// // Set starting points for players
tron_data_p->body[0][0] = (TRON_POINT){0,0,7};
tron_data_p->body[1][0] = (TRON_POINT){7,7,7};
tron_data_p->body[2][0] = (TRON_POINT){0,7,7};
tron_data_p->body[3][0] = (TRON_POINT){7,0,7};
tron_data_p->delay = TRON_DELAY;
Cube_Clear();
Cube_Overlay_Clear();
// Determine the number of players (connected controllers)
tron_data_p->players = Controller_Get_Connected();
while (tron_data_p->players < 2) {
Delay_MS(100);
Controller_Poll_Connected();
tron_data_p->players = Controller_Get_Connected();
}
if (tron_data_p->players > TRON_MAX_PLAYERS)
tron_data_p->players = TRON_MAX_PLAYERS;
tron_data_p->players_alive = tron_data_p->players;
// Draw each player's light trail
uint8_t i;
for (i = 0; i < tron_data_p->players; i++) {
tron_data_p->length[i] = 1;
tron_data_p->dead[i] = 0;
// Draw the head
Cube_Set_Pixel(tron_data_p->body[i][tron_data_p->length[i] - 1].z,
tron_data_p->body[i][tron_data_p->length[i] - 1].x,
tron_data_p->body[i][tron_data_p->length[i] - 1].y,
tron_data_p->Color_Head_R[i], tron_data_p->Color_Head_G[i],
tron_data_p->Color_Head_B[i]);
}
// Set starting direction for players
Tron_Update_Direction(0, (CTRL_BTN_STATUS) (uint8_t) 0x08);
Tron_Update_Direction(1, (CTRL_BTN_STATUS) (uint8_t) 0x10);
Tron_Update_Direction(2, (CTRL_BTN_STATUS) (uint8_t) 0x04);
Tron_Update_Direction(3, (CTRL_BTN_STATUS) (uint8_t) 0x20);
}
void Tron_Main(void) {
// Main function, loops and delays while updating the frame every x milliseconds
uint8_t i;
for (i = 0; i < tron_data_p->players; i++) {
Controller_Set_Active(i);
}
Delay_MS(20);
// Light up the player indicators
switch (tron_data_p->players) {
case 4:
Controller_Set_Left_Leds(3, 0x02);
case 3:
Controller_Set_Left_Leds(2, 0x04);
case 2:
default:
Controller_Set_Left_Leds(1, 0x08);
Controller_Set_Left_Leds(0, 0x01);
break;
}
TIMER4_Start();
Delay_MS(3000);
while (1) {
Tron_Update_Frame();
Delay_MS(tron_data_p->delay);
}
}
void Tron_Update_Direction(uint8_t controller, CTRL_BTN_STATUS value) {
// Determine the next direction for the trails based off the last button press
if (controller < tron_data_p->players) {
// Save the current button value
tron_data_p->last_direction[controller] = value.w;
// Grab the location of the head
TRON_POINT next_pos = tron_data_p->body[controller][tron_data_p->length[controller] - 1];
// Determine which next point to move to
if (value.BTN_L_N || value.BTN_L_E) { // Up
next_pos.z = (next_pos.z == CUBE_LAYER_COUNT - 1) ? 0 : next_pos.z + 1;
} else if (value.BTN_L_S || value.BTN_L_W) { // Down
next_pos.z = (next_pos.z == 0) ? CUBE_LAYER_COUNT - 1 : next_pos.z - 1;
} else if (value.BTN_R_N) { // Forward
next_pos.x = (next_pos.x == CUBE_ROW_COUNT - 1) ? 0 : next_pos.x + 1;
} else if (value.BTN_R_W) { // Left
next_pos.y = (next_pos.y == CUBE_COLUMN_COUNT - 1) ? 0 : next_pos.y + 1;
} else if (value.BTN_R_S) { // Backwards
next_pos.x = (next_pos.x == 0) ? CUBE_ROW_COUNT - 1 : next_pos.x - 1;
// } else if (value.BTN_R_E) { // Right
} else { // Right
next_pos.y = (next_pos.y== 0) ? CUBE_COLUMN_COUNT - 1 : next_pos.y - 1;
}
// Save the next point to move to
tron_data_p->direction[controller] = next_pos;
}
}
void Tron_Update_Frame(void) {
uint8_t player, player2;
// Change the current head color to the body color
for (player = 0; player < tron_data_p->players; player++) {
if (tron_data_p->dead[player] == 0) {
Cube_Set_Pixel(tron_data_p->body[player][tron_data_p->length[player] - 1].z,
tron_data_p->body[player][tron_data_p->length[player] - 1].x,
tron_data_p->body[player][tron_data_p->length[player] - 1].y,
tron_data_p->Color_Body_R[player],
tron_data_p->Color_Body_G[player],
tron_data_p->Color_Body_B[player]);
}
}
// Check if there is a head-on collision between any of the players
for (player = 0; player < tron_data_p->players; player++) {
if (tron_data_p->dead[player] == 0) {
for (player2 = 0; player2 < tron_data_p->players; player2++) {
if (player2 == player) continue;
if (tron_data_p->dead[player2] == 0) {
if (tron_data_p->direction[player].x == tron_data_p->direction[player2].x &&
tron_data_p->direction[player].y == tron_data_p->direction[player2].y &&
tron_data_p->direction[player].z == tron_data_p->direction[player2].z) {
// Indicate the collision point
Cube_Set_Pixel(tron_data_p->direction[player].z, tron_data_p->direction[player].x,
tron_data_p->direction[player].y, TRON_COLLISION);
// Mark the players as dead
tron_data_p->dead[player] = 1;
tron_data_p->dead[player2] = 1;
tron_data_p->players_alive -= 2;
}
}
}
}
}
// Check if the location that we are moving to is overlapping either trails
uint8_t index;
for (player = 0; player < tron_data_p->players; player++) {
// Check if the player in question is dead
if (tron_data_p->dead[player] == 0) {
// See if the player's next point hits anyone elses trail
for (player2 = 0; player2 < tron_data_p->players; player2++) {
for (index = 0; index < tron_data_p->length[player2]; index++) {
if (tron_data_p->direction[player].x == tron_data_p->body[player2][index].x &&
tron_data_p->direction[player].y == tron_data_p->body[player2][index].y &&
tron_data_p->direction[player].z == tron_data_p->body[player2][index].z) {
// Indicate the collision point
Cube_Set_Pixel(tron_data_p->direction[player].z, tron_data_p->direction[player].x,
tron_data_p->direction[player].y, TRON_COLLISION);
// Mark the player as dead
tron_data_p->dead[player] = 1;
tron_data_p->players_alive -= 1;
}
}
}
}
}
// Save the new head location of each trail
for (player = 0; player < tron_data_p->players; player++) {
// If player is still alive, extend its body in the next direction
if (tron_data_p->dead[player] == 0) {
tron_data_p->length[player]++;
tron_data_p->body[player][tron_data_p->length[player] - 1] = tron_data_p->direction[player];
}
}
// Update the head to its corresponding color
for (player = 0; player < tron_data_p->players; player++) {
// If player is still alive, recolor its body to indicate its new head
if (tron_data_p->dead[player] == 0) {
// Set the color of the new head
Cube_Set_Pixel(tron_data_p->body[player][tron_data_p->length[player] - 1].z,
tron_data_p->body[player][tron_data_p->length[player] - 1].x,
tron_data_p->body[player][tron_data_p->length[player] - 1].y,
tron_data_p->Color_Head_R[player],
tron_data_p->Color_Head_G[player],
tron_data_p->Color_Head_B[player]);
}
}
// End the game if there is one player left alive
if (tron_data_p->players_alive == 1) {
Delay_MS(5000);
// Determine which player is still alive and flash his color
for (player = 0; player < tron_data_p->players; player++) {
if (tron_data_p->dead[player] == 0) {
Animation_Cube_In_Out(200, tron_data_p->Color_Head_R[player],
tron_data_p->Color_Head_G[player], tron_data_p->Color_Head_B[player]);
}
}
Reset_Board(BOARD_MODE_IDLE);
} else if (tron_data_p->players_alive == 0) {
// If no players are alive flash neutral color
Delay_MS(5000);
Animation_Cube_In_Out(200, TRON_COLLISION_2);
Reset_Board(BOARD_MODE_IDLE);
}
// Determine the next direction to move to for each player
for (player = 0; player < tron_data_p->players; player++) {
if (tron_data_p->dead[player] == 0) {
Tron_Update_Direction(player, (CTRL_BTN_STATUS)tron_data_p->last_direction[player]);
}
}
// Decrease the delay between frame updates by 5ms
tron_data_p->delay -= 5;
}