| 241 |
Kevin |
1 |
#include "defines.h"
|
|
|
2 |
#include "CONTROLLERS.h"
|
|
|
3 |
#include "TRON.h"
|
| 278 |
Kevin |
4 |
#include "TIMER4.h"
|
| 241 |
Kevin |
5 |
|
| 278 |
Kevin |
6 |
static TRON_DATA *tron_data_p;
|
| 241 |
Kevin |
7 |
|
|
|
8 |
void Tron_Init(TRON_DATA *data) {
|
| 278 |
Kevin |
9 |
tron_data_p = data;
|
| 241 |
Kevin |
10 |
|
| 278 |
Kevin |
11 |
// Set players 1-4 colors
|
|
|
12 |
tron_data_p->Color_Head_R[0] = 0xFF;
|
|
|
13 |
tron_data_p->Color_Head_G[0] = 0x00;
|
|
|
14 |
tron_data_p->Color_Head_B[0] = 0x00;
|
|
|
15 |
tron_data_p->Color_Body_R[0] = 0x20;
|
|
|
16 |
tron_data_p->Color_Body_G[0] = 0x00;
|
|
|
17 |
tron_data_p->Color_Body_B[0] = 0x00;
|
| 241 |
Kevin |
18 |
|
| 278 |
Kevin |
19 |
tron_data_p->Color_Head_R[1] = 0x00;
|
|
|
20 |
tron_data_p->Color_Head_G[1] = 0x00;
|
|
|
21 |
tron_data_p->Color_Head_B[1] = 0xFF;
|
|
|
22 |
tron_data_p->Color_Body_R[1] = 0x00;
|
|
|
23 |
tron_data_p->Color_Body_G[1] = 0x00;
|
|
|
24 |
tron_data_p->Color_Body_B[1] = 0x20;
|
| 241 |
Kevin |
25 |
|
| 278 |
Kevin |
26 |
tron_data_p->Color_Head_R[2] = 0x00;
|
|
|
27 |
tron_data_p->Color_Head_G[2] = 0xFF;
|
|
|
28 |
tron_data_p->Color_Head_B[2] = 0x00;
|
|
|
29 |
tron_data_p->Color_Body_R[2] = 0x00;
|
|
|
30 |
tron_data_p->Color_Body_G[2] = 0x20;
|
|
|
31 |
tron_data_p->Color_Body_B[2] = 0x00;
|
|
|
32 |
|
|
|
33 |
tron_data_p->Color_Head_R[3] = 0xFF;
|
|
|
34 |
tron_data_p->Color_Head_G[3] = 0x60;
|
|
|
35 |
tron_data_p->Color_Head_B[3] = 0x00;
|
|
|
36 |
tron_data_p->Color_Body_R[3] = 0x20;
|
|
|
37 |
tron_data_p->Color_Body_G[3] = 0x10;
|
|
|
38 |
tron_data_p->Color_Body_B[3] = 0x00;
|
|
|
39 |
|
|
|
40 |
// // Set starting points for players
|
|
|
41 |
tron_data_p->body[0][0] = (TRON_POINT){0,0,7};
|
|
|
42 |
tron_data_p->body[1][0] = (TRON_POINT){7,7,7};
|
|
|
43 |
tron_data_p->body[2][0] = (TRON_POINT){0,7,7};
|
|
|
44 |
tron_data_p->body[3][0] = (TRON_POINT){7,0,7};
|
|
|
45 |
|
|
|
46 |
tron_data_p->delay = TRON_DELAY;
|
|
|
47 |
|
| 241 |
Kevin |
48 |
Cube_Clear();
|
|
|
49 |
Cube_Overlay_Clear();
|
|
|
50 |
|
| 278 |
Kevin |
51 |
// Determine the number of players (connected controllers)
|
|
|
52 |
tron_data_p->players = Controller_Get_Connected();
|
|
|
53 |
while (tron_data_p->players < 2) {
|
|
|
54 |
Delay_MS(100);
|
|
|
55 |
Controller_Poll_Connected();
|
|
|
56 |
tron_data_p->players = Controller_Get_Connected();
|
| 241 |
Kevin |
57 |
}
|
| 278 |
Kevin |
58 |
if (tron_data_p->players > TRON_MAX_PLAYERS)
|
|
|
59 |
tron_data_p->players = TRON_MAX_PLAYERS;
|
|
|
60 |
tron_data_p->players_alive = tron_data_p->players;
|
| 241 |
Kevin |
61 |
|
| 278 |
Kevin |
62 |
// Draw each player's light trail
|
|
|
63 |
uint8_t i;
|
|
|
64 |
for (i = 0; i < tron_data_p->players; i++) {
|
|
|
65 |
tron_data_p->length[i] = 1;
|
|
|
66 |
tron_data_p->dead[i] = 0;
|
|
|
67 |
// Draw the head
|
|
|
68 |
Cube_Set_Pixel(tron_data_p->body[i][tron_data_p->length[i] - 1].z,
|
|
|
69 |
tron_data_p->body[i][tron_data_p->length[i] - 1].x,
|
|
|
70 |
tron_data_p->body[i][tron_data_p->length[i] - 1].y,
|
|
|
71 |
tron_data_p->Color_Head_R[i], tron_data_p->Color_Head_G[i],
|
|
|
72 |
tron_data_p->Color_Head_B[i]);
|
| 241 |
Kevin |
73 |
}
|
| 278 |
Kevin |
74 |
|
|
|
75 |
// Set starting direction for players
|
|
|
76 |
Tron_Update_Direction(0, (CTRL_BTN_STATUS) (uint8_t) 0x08);
|
|
|
77 |
Tron_Update_Direction(1, (CTRL_BTN_STATUS) (uint8_t) 0x10);
|
|
|
78 |
Tron_Update_Direction(2, (CTRL_BTN_STATUS) (uint8_t) 0x04);
|
|
|
79 |
Tron_Update_Direction(3, (CTRL_BTN_STATUS) (uint8_t) 0x20);
|
| 241 |
Kevin |
80 |
}
|
|
|
81 |
|
|
|
82 |
void Tron_Main(void) {
|
|
|
83 |
// Main function, loops and delays while updating the frame every x milliseconds
|
| 278 |
Kevin |
84 |
uint8_t i;
|
|
|
85 |
for (i = 0; i < tron_data_p->players; i++) {
|
|
|
86 |
Controller_Set_Active(i);
|
|
|
87 |
}
|
|
|
88 |
Delay_MS(20);
|
|
|
89 |
// Light up the player indicators
|
|
|
90 |
switch (tron_data_p->players) {
|
|
|
91 |
case 4:
|
|
|
92 |
Controller_Set_Left_Leds(3, 0x02);
|
|
|
93 |
case 3:
|
|
|
94 |
Controller_Set_Left_Leds(2, 0x04);
|
|
|
95 |
case 2:
|
|
|
96 |
default:
|
|
|
97 |
Controller_Set_Left_Leds(1, 0x08);
|
|
|
98 |
Controller_Set_Left_Leds(0, 0x01);
|
|
|
99 |
break;
|
|
|
100 |
}
|
|
|
101 |
TIMER4_Start();
|
|
|
102 |
Delay_MS(3000);
|
| 241 |
Kevin |
103 |
while (1) {
|
|
|
104 |
Tron_Update_Frame();
|
| 278 |
Kevin |
105 |
Delay_MS(tron_data_p->delay);
|
| 241 |
Kevin |
106 |
}
|
|
|
107 |
}
|
|
|
108 |
|
| 278 |
Kevin |
109 |
void Tron_Update_Direction(uint8_t controller, CTRL_BTN_STATUS value) {
|
| 241 |
Kevin |
110 |
// Determine the next direction for the trails based off the last button press
|
| 278 |
Kevin |
111 |
if (controller < tron_data_p->players) {
|
|
|
112 |
// Save the current button value
|
|
|
113 |
tron_data_p->last_direction[controller] = value.w;
|
|
|
114 |
|
|
|
115 |
// Grab the location of the head
|
|
|
116 |
TRON_POINT next_pos = tron_data_p->body[controller][tron_data_p->length[controller] - 1];
|
|
|
117 |
|
|
|
118 |
// Determine which next point to move to
|
|
|
119 |
if (value.BTN_L_N || value.BTN_L_E) { // Up
|
|
|
120 |
next_pos.z = (next_pos.z == CUBE_LAYER_COUNT - 1) ? 0 : next_pos.z + 1;
|
|
|
121 |
} else if (value.BTN_L_S || value.BTN_L_W) { // Down
|
|
|
122 |
next_pos.z = (next_pos.z == 0) ? CUBE_LAYER_COUNT - 1 : next_pos.z - 1;
|
|
|
123 |
} else if (value.BTN_R_N) { // Forward
|
|
|
124 |
next_pos.x = (next_pos.x == CUBE_ROW_COUNT - 1) ? 0 : next_pos.x + 1;
|
|
|
125 |
} else if (value.BTN_R_W) { // Left
|
|
|
126 |
next_pos.y = (next_pos.y == CUBE_COLUMN_COUNT - 1) ? 0 : next_pos.y + 1;
|
|
|
127 |
} else if (value.BTN_R_S) { // Backwards
|
|
|
128 |
next_pos.x = (next_pos.x == 0) ? CUBE_ROW_COUNT - 1 : next_pos.x - 1;
|
|
|
129 |
// } else if (value.BTN_R_E) { // Right
|
|
|
130 |
} else { // Right
|
|
|
131 |
next_pos.y = (next_pos.y== 0) ? CUBE_COLUMN_COUNT - 1 : next_pos.y - 1;
|
| 241 |
Kevin |
132 |
}
|
| 278 |
Kevin |
133 |
|
|
|
134 |
// Save the next point to move to
|
|
|
135 |
tron_data_p->direction[controller] = next_pos;
|
| 241 |
Kevin |
136 |
}
|
|
|
137 |
}
|
|
|
138 |
|
|
|
139 |
void Tron_Update_Frame(void) {
|
| 278 |
Kevin |
140 |
uint8_t player, player2;
|
|
|
141 |
|
|
|
142 |
// Change the current head color to the body color
|
|
|
143 |
for (player = 0; player < tron_data_p->players; player++) {
|
|
|
144 |
if (tron_data_p->dead[player] == 0) {
|
|
|
145 |
Cube_Set_Pixel(tron_data_p->body[player][tron_data_p->length[player] - 1].z,
|
|
|
146 |
tron_data_p->body[player][tron_data_p->length[player] - 1].x,
|
|
|
147 |
tron_data_p->body[player][tron_data_p->length[player] - 1].y,
|
|
|
148 |
tron_data_p->Color_Body_R[player],
|
|
|
149 |
tron_data_p->Color_Body_G[player],
|
|
|
150 |
tron_data_p->Color_Body_B[player]);
|
|
|
151 |
}
|
| 241 |
Kevin |
152 |
}
|
|
|
153 |
|
| 278 |
Kevin |
154 |
// Check if there is a head-on collision between any of the players
|
|
|
155 |
for (player = 0; player < tron_data_p->players; player++) {
|
|
|
156 |
if (tron_data_p->dead[player] == 0) {
|
|
|
157 |
for (player2 = 0; player2 < tron_data_p->players; player2++) {
|
|
|
158 |
if (player2 == player) continue;
|
|
|
159 |
if (tron_data_p->dead[player2] == 0) {
|
|
|
160 |
if (tron_data_p->direction[player].x == tron_data_p->direction[player2].x &&
|
|
|
161 |
tron_data_p->direction[player].y == tron_data_p->direction[player2].y &&
|
|
|
162 |
tron_data_p->direction[player].z == tron_data_p->direction[player2].z) {
|
|
|
163 |
// Indicate the collision point
|
|
|
164 |
Cube_Set_Pixel(tron_data_p->direction[player].z, tron_data_p->direction[player].x,
|
|
|
165 |
tron_data_p->direction[player].y, TRON_COLLISION);
|
|
|
166 |
// Mark the players as dead
|
|
|
167 |
tron_data_p->dead[player] = 1;
|
|
|
168 |
tron_data_p->dead[player2] = 1;
|
|
|
169 |
tron_data_p->players_alive -= 2;
|
|
|
170 |
}
|
|
|
171 |
}
|
|
|
172 |
}
|
|
|
173 |
}
|
|
|
174 |
}
|
|
|
175 |
|
| 241 |
Kevin |
176 |
// Check if the location that we are moving to is overlapping either trails
|
| 278 |
Kevin |
177 |
uint8_t index;
|
|
|
178 |
for (player = 0; player < tron_data_p->players; player++) {
|
|
|
179 |
// Check if the player in question is dead
|
|
|
180 |
if (tron_data_p->dead[player] == 0) {
|
|
|
181 |
// See if the player's next point hits anyone elses trail
|
|
|
182 |
for (player2 = 0; player2 < tron_data_p->players; player2++) {
|
|
|
183 |
for (index = 0; index < tron_data_p->length[player2]; index++) {
|
|
|
184 |
if (tron_data_p->direction[player].x == tron_data_p->body[player2][index].x &&
|
|
|
185 |
tron_data_p->direction[player].y == tron_data_p->body[player2][index].y &&
|
|
|
186 |
tron_data_p->direction[player].z == tron_data_p->body[player2][index].z) {
|
|
|
187 |
// Indicate the collision point
|
|
|
188 |
Cube_Set_Pixel(tron_data_p->direction[player].z, tron_data_p->direction[player].x,
|
|
|
189 |
tron_data_p->direction[player].y, TRON_COLLISION);
|
|
|
190 |
// Mark the player as dead
|
|
|
191 |
tron_data_p->dead[player] = 1;
|
|
|
192 |
tron_data_p->players_alive -= 1;
|
|
|
193 |
}
|
|
|
194 |
}
|
|
|
195 |
}
|
| 241 |
Kevin |
196 |
}
|
|
|
197 |
}
|
|
|
198 |
|
|
|
199 |
// Save the new head location of each trail
|
| 278 |
Kevin |
200 |
for (player = 0; player < tron_data_p->players; player++) {
|
|
|
201 |
// If player is still alive, extend its body in the next direction
|
|
|
202 |
if (tron_data_p->dead[player] == 0) {
|
|
|
203 |
tron_data_p->length[player]++;
|
|
|
204 |
tron_data_p->body[player][tron_data_p->length[player] - 1] = tron_data_p->direction[player];
|
|
|
205 |
}
|
| 241 |
Kevin |
206 |
}
|
|
|
207 |
|
| 278 |
Kevin |
208 |
// Update the head to its corresponding color
|
|
|
209 |
for (player = 0; player < tron_data_p->players; player++) {
|
|
|
210 |
// If player is still alive, recolor its body to indicate its new head
|
|
|
211 |
if (tron_data_p->dead[player] == 0) {
|
|
|
212 |
// Set the color of the new head
|
|
|
213 |
Cube_Set_Pixel(tron_data_p->body[player][tron_data_p->length[player] - 1].z,
|
|
|
214 |
tron_data_p->body[player][tron_data_p->length[player] - 1].x,
|
|
|
215 |
tron_data_p->body[player][tron_data_p->length[player] - 1].y,
|
|
|
216 |
tron_data_p->Color_Head_R[player],
|
|
|
217 |
tron_data_p->Color_Head_G[player],
|
|
|
218 |
tron_data_p->Color_Head_B[player]);
|
|
|
219 |
}
|
| 241 |
Kevin |
220 |
}
|
|
|
221 |
|
| 278 |
Kevin |
222 |
// End the game if there is one player left alive
|
|
|
223 |
if (tron_data_p->players_alive == 1) {
|
|
|
224 |
Delay_MS(5000);
|
|
|
225 |
// Determine which player is still alive and flash his color
|
|
|
226 |
for (player = 0; player < tron_data_p->players; player++) {
|
|
|
227 |
if (tron_data_p->dead[player] == 0) {
|
|
|
228 |
Animation_Cube_In_Out(200, tron_data_p->Color_Head_R[player],
|
|
|
229 |
tron_data_p->Color_Head_G[player], tron_data_p->Color_Head_B[player]);
|
|
|
230 |
}
|
|
|
231 |
}
|
| 241 |
Kevin |
232 |
Reset_Board(BOARD_MODE_IDLE);
|
| 278 |
Kevin |
233 |
} else if (tron_data_p->players_alive == 0) {
|
|
|
234 |
// If no players are alive flash neutral color
|
|
|
235 |
Delay_MS(5000);
|
|
|
236 |
Animation_Cube_In_Out(200, TRON_COLLISION_2);
|
|
|
237 |
Reset_Board(BOARD_MODE_IDLE);
|
| 241 |
Kevin |
238 |
}
|
|
|
239 |
|
| 278 |
Kevin |
240 |
// Determine the next direction to move to for each player
|
|
|
241 |
for (player = 0; player < tron_data_p->players; player++) {
|
|
|
242 |
if (tron_data_p->dead[player] == 0) {
|
|
|
243 |
Tron_Update_Direction(player, (CTRL_BTN_STATUS)tron_data_p->last_direction[player]);
|
|
|
244 |
}
|
|
|
245 |
}
|
| 241 |
Kevin |
246 |
|
|
|
247 |
// Decrease the delay between frame updates by 5ms
|
| 278 |
Kevin |
248 |
tron_data_p->delay -= 5;
|
| 241 |
Kevin |
249 |
}
|