-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathgame.c
303 lines (275 loc) · 7.81 KB
/
game.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
/**
Game module source code
@team 128
@author Ambrose Ledbrook - 79172462
@author Josh Jarvis - 28803714
@date 09-oct-2018
@brief This module provides the main functionality of the game, allowing
the two players of the game to actually play the game.
*/
// Inlcuding modules used
#include "system.h"
#include "tinygl.h"
#include "pacer.h"
#include "paddle.h"
#include "messages.h"
#include "font3x5_1.h"
#include "font.h"
#include "comms.h"
#include "game.h"
#include "led.h"
#include "ball.h"
/*
Intialises the tinygl module used by the game
*/
void tiny_init(void) {
// Setting up initial values of the tinygl module
tinygl_init (PACER_RATE);
tinygl_font_set (&font3x5_1);
tinygl_text_speed_set (MESSAGE_RATE);
tinygl_text_mode_set (TINYGL_TEXT_MODE_SCROLL);
tinygl_text_dir_set (TINYGL_TEXT_DIR_ROTATE);
}
/*
Intialises the game enviroment and other modules used by the game, while also
setting the initial game state
*/
void game_init(void) {
// Initializing used modules
system_init();
ball_init();
navswitch_init();
paddle_init();
pacer_init(PACER_RATE);
tiny_init();
comms_init();
led_init();
// Turning the led off
led_set(BLUE_LED, LED_OFF);
// Setting the initial state of the game
game_state = NOT_STARTED;
}
/*
Handles the movement of the game paddle through the use of the paddle module.
*/
void paddle_task(void) {
paddle_move();
}
/*
Clears the display of the ledmat
*/
void clear_display(void) {
tinygl_clear();
}
/**
Changes the state of the game to that of the passed state. Also performs
initializing tasks for the new state.
*/
void change_states(Game_states new_state) {
// Updating the game state
game_state = new_state;
// Checking the new current state and performing actions if required
// dependent on the current state
switch (game_state) {
case PLAYING :
// Turning the led on
led_set(BLUE_LED, LED_ON);
break;
case WAITING :
// Turning the led on
led_set(BLUE_LED, LED_OFF);
default :
break;
}
}
/**
Checks if the button is pressed if so the game state is changed to PLAYING
*/
void button_task(void) {
// Chekcing for a button event
if (navswitch_push_event_p(NAVSWITCH_PUSH)) {
// Clearing the display
clear_display();
switch (game_state) {
case NOT_STARTED :
change_states(MENU);
break;
case MENU :
change_states(WAITING);
// Sendng a signal to the other board to start the game
send_speed(ball_speed);
break;
default :
break;
}
}
}
/**
Checks if the ball has reached the top of the ledmat if so the ball is sent
to the other board. Otherwise the ball postion is updated.
*/
void ball_task(void) {
if (check_send()) {
// Sending the ball
send_ball_pos();
// Changing states to wait for the ball to return
change_states(WAITING);
} else {
if (!check_paddle()) {
clear_display();
show_lost();
send_won();
led_set(BLUE_LED, LED_OFF);
change_states(NOT_STARTED);
} else {
ball_update();
}
}
}
/**
Receives data through the ir receiver. If the data recieved matches the
defined SPEED_CODE then the game state is changed to PLAYING.
*/
void check_start(void) {
Data received = receive_data();
// Checking if data recieved is a START_CODE
if (received.type == SPEED_CODE) {
// Clearing the display and changing the game state to PLAYING
ball_speed = received.ball_pos;
clear_display();
reset_ball();
change_states(PLAYING);
}
}
/**
Updates the index of the selected difficulty by a passed value
*/
void update_index(uint8_t to_add) {
speed_index += to_add;
speed_index = speed_index % NUM_DIFFICULTIES;
}
/**
Updates the selected ball speed on a NAVSWITCH_NORTH or NAVSWITCH_SOUTH push
event.
*/
void change_speed(void) {
// Checking for navswitch_push_event_p and updating index as required
if (navswitch_push_event_p(NAVSWITCH_NORTH)) {
update_index(1);
} else if (navswitch_push_event_p(NAVSWITCH_SOUTH)) {
update_index(NUM_DIFFICULTIES + 1);
}
// Updating new ball speed value
switch (speed_index) {
case 0 :
ball_speed = EASY;
break;
case 1 :
ball_speed = MEDIUM;
break;
case 2 :
ball_speed = HARD;
break;
default :
break;
}
// Showing the newly selected speed on the ledmat
show_speed(speed_index);
}
/**
This method receives data through the ir receiver. It then checks if the
received data is any of the expected values, a WIN_CODE or a BALL_CODE.
Corresponding to either a notification that this board has won the game or
passing the ball back to this board.
*/
void check_ir(void) {
Data received = receive_data();
// Checking the type of the recieved data
switch(received.type) {
case WIN_CODE :
// Clearing the display and showing the winning message
clear_display();
show_won();
led_set(BLUE_LED, LED_ON);
change_states(NOT_STARTED);
break;
case BALL_CODE :
// Receiving the ball from the other board
receive_ball(received.ball_pos, received.ball_dir);
// Changing the state t PLAYING
change_states(PLAYING);
break;
default :
break;
}
}
/**
Performing the required tasks dependent on the passed game state
@param state The current state of the game
@param ball_tick The tick count for updating the ball
@return The new tick count for the ball
*/
uint8_t game_tasks(Game_states state, uint8_t ball_tick) {
switch(state) {
case NOT_STARTED :
// Checking for a button press or START_CODE to start the game
button_task();
check_start();
break;
case MENU :
// Checking for a navswitch push to either change the speed
// or start the game
change_speed();
button_task();
// Checking for START_CODE from other board
check_start();
break;
case PLAYING :
// If updating ball dependent on the selected ball_speed
if (ball_tick >= ball_speed) {
ball_task();
ball_tick = 0;
}
// Checking for paddle movement
paddle_task();
break;
case WAITING :
// Waiting for a BALL_CODE or WIN_CODE
check_ir();
// Checking for paddle movement
paddle_task();
break;
break;
}
return ball_tick;
}
/**
This method runs the game. Different sets of tasks are performed dependent
on the current game_state.
*/
int main(void) {
// Initializing the game enviroment and used modules
game_init();
// Showing the welcome message
show_welcome();
// Intialising tick varaibles used in the pacer loop
uint8_t game_tick = 0;
uint8_t ball_tick = 0;
// Pace looping to run the game
while(1) {
// Waiting
pacer_wait();
// Incrementing ticks
game_tick++;
ball_tick++;
// Updating navswitch
if (game_tick == (PACER_RATE / BUTTON_RATE)) {
navswitch_update();
game_tick = 0;
}
// Updating tinygl
tinygl_update();
// Performign tasks bassed on teh current game state
ball_tick = game_tasks(game_state, ball_tick);
}
}