Comments and refactoring
This commit is contained in:
218
src/game.c
218
src/game.c
@@ -2,17 +2,15 @@
|
||||
#include <lcd_lld.h>
|
||||
#include <color.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "game.h"
|
||||
#include "io.h"
|
||||
|
||||
void game_init(game_t* game, uint16_t ticks_per_sec) {
|
||||
//Sysinit
|
||||
|
||||
|
||||
//gpio init
|
||||
io_init();
|
||||
|
||||
//uart init
|
||||
|
||||
//lcd init
|
||||
LCD_Init();
|
||||
LCD_Clear(GUI_COLOR_BLACK);
|
||||
@@ -46,50 +44,50 @@ bool game_check_line_collision(player_t* player, point_t start, point_t end, uin
|
||||
switch(player->direction){
|
||||
case up:
|
||||
if(player->position.y > start.y && ((int16_t)player->position.y - pixels) <= start.y) {
|
||||
return true;
|
||||
return true; // going up and hitting a line segment
|
||||
}
|
||||
break;
|
||||
case down:
|
||||
if(player->position.y < start.y && ((int16_t)player->position.y + pixels) >= start.y) {
|
||||
return true;
|
||||
return true; // going down and hitting a line segment
|
||||
}
|
||||
break;
|
||||
case left:
|
||||
if(player->position.x > start.x && ((int16_t)player->position.x - pixels) <= start.x) {
|
||||
return true;
|
||||
return true; // going left and hitting a line segment
|
||||
}
|
||||
break;
|
||||
case right:
|
||||
if(player->position.x < start.x && ((int16_t)player->position.x + pixels) >= start.x) {
|
||||
return true;
|
||||
return true; // going right and hitting a line segment
|
||||
}
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool game_check_bounding_collision(game_t* game, player_t* player, uint8_t pixels){
|
||||
bool game_check_boundary_collision(game_t* game, player_t* player, uint8_t pixels){
|
||||
|
||||
// Check bounding collision
|
||||
// Check boundary collision
|
||||
switch(player->direction){
|
||||
case up:
|
||||
if((int16_t)(player->position.y) - pixels <= TFT_GAME_FIELD_TOP){
|
||||
return true; // Collision at top
|
||||
return true; // Collision at top boundary
|
||||
}
|
||||
break;
|
||||
case down:
|
||||
if((int16_t)(player->position.y) + pixels >= (TFT_HEIGHT - TFT_GAME_FIELD_BOTTOM - 1)){
|
||||
return true; // Collision at bottom
|
||||
return true; // Collision at bottom boundary
|
||||
}
|
||||
break;
|
||||
case left:
|
||||
if((int16_t)(player->position.x) - pixels <= TFT_GAME_FIELD_LEFT){
|
||||
return true; // Collision at left
|
||||
return true; // Collision at left boundary
|
||||
}
|
||||
break;
|
||||
case right:
|
||||
if((int16_t)(player->position.x) + pixels >= (TFT_WIDTH - TFT_GAME_FIELD_RIGHT - 1)){
|
||||
return true; // Collision at right
|
||||
return true; // Collision at right boundary
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -122,11 +120,10 @@ bool game_check_player_collision(game_t* game, player_t* player, uint8_t pixels)
|
||||
}
|
||||
}
|
||||
|
||||
// Do all collision checks!
|
||||
bool game_check_collision(game_t* game, player_t* player, uint8_t pixels){
|
||||
bool game_check_collision(game_t* game, player_t* player, uint8_t pixels){ // Check boundary and player collisions
|
||||
|
||||
// Check for collisions with boundings
|
||||
if(game_check_bounding_collision(game, player, pixels)){
|
||||
// Check for collisions with boundarys
|
||||
if(game_check_boundary_collision(game, player, pixels)){
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -140,39 +137,37 @@ bool game_check_collision(game_t* game, player_t* player, uint8_t pixels){
|
||||
|
||||
bool game_player_update(game_t* game, player_t* player, uint8_t pixels){
|
||||
|
||||
bool directionChange = false;
|
||||
bool stateChanged = false;
|
||||
bool direction_change = false;
|
||||
bool state_changed = false;
|
||||
|
||||
// Check for button presses
|
||||
if(io_button_has_edge(player->btn_left)) {
|
||||
player->direction= (player->direction + (4 - 1)) % 4 ; // "decrement enum value"
|
||||
directionChange = true;
|
||||
} else if(io_button_has_edge(player->btn_right)) {
|
||||
player->direction= (player->direction + 1) % 4 ; // "increment enum value"
|
||||
directionChange = true;
|
||||
if(io_button_has_edge(player->btn_left)) { // If left button is pressed
|
||||
player->direction= (player->direction + (4 - 1)) % 4 ; // Decrement direction value (counterclockwise)
|
||||
direction_change = true;
|
||||
} else if(io_button_has_edge(player->btn_right)) { // If right button is pressed
|
||||
player->direction= (player->direction + 1) % 4 ; // Increment direction value (clockwise)
|
||||
direction_change = true;
|
||||
}
|
||||
|
||||
// Check if player is alive
|
||||
if(player->state != alive){
|
||||
return stateChanged;
|
||||
return state_changed; // If player is dead return state
|
||||
}
|
||||
// Change direction
|
||||
if(directionChange) {
|
||||
player_append_position(player,player->position);
|
||||
if(direction_change) {
|
||||
player_append_position(player,player->position); // Append new position if direction has changed
|
||||
}
|
||||
|
||||
if(pixels) {
|
||||
|
||||
// Check if a collision is about to happen
|
||||
if(game_check_collision(game, player, pixels)){
|
||||
player->state=dead;
|
||||
stateChanged=true;
|
||||
if(game_check_collision(game, player, pixels)){ // Check if a collision is about to happen
|
||||
player->state = dead; // If a collision is happening kill the player
|
||||
state_changed = true; // return the state
|
||||
}
|
||||
|
||||
point_t last_point = player->past_positions[player->num_positions-1];
|
||||
point_t last_point = player->past_positions[player->num_positions-1]; // Get the players newest point
|
||||
|
||||
switch(player->direction) {
|
||||
case down:
|
||||
switch(player->direction) { // Get the players moving direction and render his move
|
||||
case down: // render down
|
||||
player->position.y+=pixels;
|
||||
LCD_DrawRectF( player->position.x,
|
||||
last_point.y,
|
||||
@@ -180,7 +175,7 @@ bool game_player_update(game_t* game, player_t* player, uint8_t pixels){
|
||||
player->position.y - last_point.y,
|
||||
player->color);
|
||||
break;
|
||||
case left:
|
||||
case left: // render left
|
||||
player->position.x-=pixels;
|
||||
LCD_DrawRectF( player->position.x,
|
||||
player->position.y,
|
||||
@@ -188,7 +183,7 @@ bool game_player_update(game_t* game, player_t* player, uint8_t pixels){
|
||||
PLAYER_WIDTH,
|
||||
player->color);
|
||||
break;
|
||||
case up:
|
||||
case up: // render up
|
||||
player->position.y-=pixels;
|
||||
LCD_DrawRectF( player->position.x,
|
||||
player->position.y,
|
||||
@@ -196,7 +191,7 @@ bool game_player_update(game_t* game, player_t* player, uint8_t pixels){
|
||||
last_point.y - player->position.y,
|
||||
player->color);
|
||||
break;
|
||||
case right:
|
||||
case right: // render right
|
||||
player->position.x+=pixels;
|
||||
LCD_DrawRectF( last_point.x,
|
||||
player->position.y,
|
||||
@@ -206,111 +201,116 @@ bool game_player_update(game_t* game, player_t* player, uint8_t pixels){
|
||||
break;
|
||||
}
|
||||
}
|
||||
return stateChanged;
|
||||
|
||||
return state_changed; // return state
|
||||
}
|
||||
|
||||
bool game_step(game_t* game, uint64_t deltaTime) {
|
||||
bool game_step(game_t* game, uint64_t delta_time) { // Calculate the next game step
|
||||
static long l = 0;
|
||||
|
||||
switch(game->state) {
|
||||
case prestart:
|
||||
//Draw welcome screen
|
||||
case prestart: // If the game is in prestart state
|
||||
// Draw welcome screen
|
||||
LCD_DrawRectF(10,10,100,50,GUI_COLOR_BLUE);
|
||||
|
||||
//wait on player to press start (host)
|
||||
// Wait on player to press start
|
||||
while(!io_button_has_edge(BTN_START));
|
||||
|
||||
//send game start request to slave
|
||||
//wait on game accept response
|
||||
|
||||
//setup
|
||||
player_init(&(game->player[0]),
|
||||
BTN_PLAYER_1_LEFT,
|
||||
BTN_PLAYER_1_RIGHT,
|
||||
// Setup the two players
|
||||
player_init(&(game->player[0]), // Player object to fill
|
||||
BTN_PLAYER_1_LEFT, // Left-button
|
||||
BTN_PLAYER_1_RIGHT, // Right-button
|
||||
(point_t){
|
||||
.x=(TFT_GAME_FIELD_START_OFFSET + TFT_GAME_FIELD_LEFT),
|
||||
.y=(((TFT_HEIGHT - TFT_GAME_FIELD_TOP - TFT_GAME_FIELD_BOTTOM) / 2) + TFT_GAME_FIELD_TOP)
|
||||
.x=(TFT_GAME_FIELD_START_OFFSET + TFT_GAME_FIELD_LEFT), // x start coordinate
|
||||
.y=(((TFT_HEIGHT - TFT_GAME_FIELD_TOP - TFT_GAME_FIELD_BOTTOM) / 2) + TFT_GAME_FIELD_TOP) // y start coordinate
|
||||
},
|
||||
GUI_COLOR_BLUE,
|
||||
right);
|
||||
GUI_COLOR_BLUE, // color
|
||||
right); // default moving direction
|
||||
|
||||
player_init(&(game->player[1]),
|
||||
BTN_PLAYER_2_LEFT,
|
||||
BTN_PLAYER_2_RIGHT,
|
||||
player_init(&(game->player[1]), // Player object to fill
|
||||
BTN_PLAYER_2_LEFT, // Left-button
|
||||
BTN_PLAYER_2_RIGHT, // Right-button
|
||||
(point_t){
|
||||
.x=(TFT_WIDTH - 1 - TFT_GAME_FIELD_RIGHT - TFT_GAME_FIELD_START_OFFSET),
|
||||
.y=(((TFT_HEIGHT - TFT_GAME_FIELD_TOP - TFT_GAME_FIELD_BOTTOM) / 2) + TFT_GAME_FIELD_TOP)
|
||||
.x=(TFT_WIDTH - 1 - TFT_GAME_FIELD_RIGHT - TFT_GAME_FIELD_START_OFFSET), // x start coordinate
|
||||
.y=(((TFT_HEIGHT - TFT_GAME_FIELD_TOP - TFT_GAME_FIELD_BOTTOM) / 2) + TFT_GAME_FIELD_TOP) // y start coordinate
|
||||
},
|
||||
GUI_COLOR_RED,
|
||||
left);
|
||||
GUI_COLOR_RED, // color
|
||||
left); // default moving direction
|
||||
|
||||
//switch state
|
||||
game->state = running;
|
||||
game->time = 0;
|
||||
game->state = running; // Switch the game state to running
|
||||
game->time = 0; // Reset the game time
|
||||
|
||||
LCD_Clear(GUI_COLOR_BLACK);
|
||||
LCD_DrawRect(TFT_GAME_FIELD_LEFT,
|
||||
TFT_GAME_FIELD_TOP,
|
||||
(TFT_WIDTH - TFT_GAME_FIELD_LEFT - TFT_GAME_FIELD_RIGHT - 1),
|
||||
(TFT_HEIGHT - TFT_GAME_FIELD_TOP - TFT_GAME_FIELD_BOTTOM - 1),
|
||||
GUI_COLOR_WHITE);
|
||||
LCD_Clear(GUI_COLOR_BLACK); // Clear the background
|
||||
|
||||
LCD_SetTextColor(GUI_COLOR_WHITE);
|
||||
LCD_DisplayStringXY(TFT_GAME_HEADER_TIME_X, TFT_GAME_HEADER_TIME_Y, "Time: 0:00");
|
||||
for(int i = 0; i < PLAYER_COUNT; i++){
|
||||
static char buf[16];
|
||||
LCD_SetTextColor(game->player[i].color);
|
||||
sprintf(buf, "Player%d: alive", (i+1));
|
||||
LCD_DisplayStringXY(TFT_GAME_HEADER_PLAYER_X+i*TFT_GAME_HEADER_PLAYER_WIDTH, TFT_GAME_HEADER_PLAYER_Y, buf);
|
||||
// Draw the game boundary
|
||||
LCD_DrawRect(TFT_GAME_FIELD_LEFT, // left top x
|
||||
TFT_GAME_FIELD_TOP, // left top y
|
||||
(TFT_WIDTH - TFT_GAME_FIELD_LEFT - TFT_GAME_FIELD_RIGHT - 1), // right bottom x
|
||||
(TFT_HEIGHT - TFT_GAME_FIELD_TOP - TFT_GAME_FIELD_BOTTOM - 1), // right bottom y
|
||||
GUI_COLOR_WHITE); // Color of the boundary
|
||||
|
||||
LCD_SetTextColor(GUI_COLOR_WHITE); // Reset color to white
|
||||
LCD_DisplayStringXY(TFT_GAME_HEADER_TIME_X, TFT_GAME_HEADER_TIME_Y, "Time: 0:00"); // Draw the zero-time
|
||||
|
||||
for(int i = 0; i < PLAYER_COUNT; i++){ // For each player print its name and its state
|
||||
static char buf[16]; // Text buffer
|
||||
LCD_SetTextColor(game->player[i].color); // Set the text color according to the players color
|
||||
sprintf(buf, "Player%d: alive", (i+1)); // Print the state and the players name to the text buffer
|
||||
LCD_DisplayStringXY(TFT_GAME_HEADER_PLAYER_X+i*TFT_GAME_HEADER_PLAYER_WIDTH, TFT_GAME_HEADER_PLAYER_Y, buf); // Print everything
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
case running:
|
||||
{
|
||||
uint16_t ticks;
|
||||
uint16_t ticks;
|
||||
uint16_t pixels = 0;
|
||||
|
||||
if(deltaTime) {
|
||||
ticks = game->ticks_leftover + deltaTime;
|
||||
pixels = ticks / game->ticks_per_pixel;
|
||||
game->ticks_leftover = ticks % game->ticks_per_pixel;
|
||||
game->ticks_sum_sec += deltaTime;
|
||||
if(delta_time) {
|
||||
ticks = game->ticks_leftover + delta_time; // Calculate the number of past ticks
|
||||
pixels = ticks / game->ticks_per_pixel; // Calculate the number of pixels moved in the calculated amount of ticks
|
||||
game->ticks_leftover = ticks % game->ticks_per_pixel; // Calculate the number of ticks which are left
|
||||
game->ticks_sum_sec += delta_time; // Add the delta_time to the tick sum which is used to calculate the game time
|
||||
|
||||
uint16_t new_seconds = game->ticks_sum_sec / game->ticks_per_sec;
|
||||
uint16_t new_seconds = game->ticks_sum_sec / game->ticks_per_sec; // Calculate number of seconds from past ticks
|
||||
|
||||
game->time += new_seconds;
|
||||
game->ticks_sum_sec = game->ticks_sum_sec % game->ticks_per_sec;
|
||||
game->time += new_seconds; // Add the new amount of seconds to the game time
|
||||
game->ticks_sum_sec = game->ticks_sum_sec % game->ticks_per_sec; // Limit the tick sum used to calculate the amount of seconds
|
||||
|
||||
if(new_seconds > 0){
|
||||
static char buf[15];
|
||||
sprintf(buf, "Time: %d:%02d", (game->time / 60), (game->time % 60));
|
||||
LCD_SetTextColor(GUI_COLOR_WHITE);
|
||||
LCD_DisplayStringXY(TFT_GAME_HEADER_TIME_X, TFT_GAME_HEADER_TIME_Y, buf);
|
||||
if(new_seconds > 0){ // Print the time if it got updated
|
||||
static char buf[15]; // Textbufer
|
||||
sprintf(buf, "Time: %d:%02d", (game->time / 60), (game->time % 60)); // Format time and paste it to the textbuffer
|
||||
LCD_SetTextColor(GUI_COLOR_WHITE); // Set the text color to white
|
||||
LCD_DisplayStringXY(TFT_GAME_HEADER_TIME_X, TFT_GAME_HEADER_TIME_Y, buf); // Print the time
|
||||
}
|
||||
}
|
||||
|
||||
bool all_players_dead = true; // Assume all players are dead ;-)
|
||||
|
||||
// For each player do ...
|
||||
bool all_players_dead = true;
|
||||
for(int i = 0; i < PLAYER_COUNT; i++) {
|
||||
player_t* player = &(game->player[i]);
|
||||
if(game_player_update(game, player, pixels)) { //update player and execute if, when player state has changed
|
||||
static char buf[15];
|
||||
const char* state_text = "alive";
|
||||
if(player->state==dead) {
|
||||
for(int i = 0; i < PLAYER_COUNT; i++) {
|
||||
player_t* player = &(game->player[i]); // Copy an object of the current player
|
||||
|
||||
if(game_player_update(game, player, pixels)) { // Update player and execute if, when player state has changed
|
||||
static char buf[15]; // Buffer to hold the text output
|
||||
const char* state_text = "alive"; // Assume that the player is alive
|
||||
|
||||
if(player->state==dead) { // If the player is dead change the text
|
||||
state_text="dead";
|
||||
}
|
||||
sprintf(buf, "Player%d: %s ", (i+1),state_text);
|
||||
LCD_SetTextColor(player->color);
|
||||
LCD_DisplayStringXY(TFT_GAME_HEADER_PLAYER_X+i*TFT_GAME_HEADER_PLAYER_WIDTH, TFT_GAME_HEADER_PLAYER_Y, buf);
|
||||
|
||||
sprintf(buf, "Player%d: %s ", (i+1),state_text); // Format and paste the status to the buffer
|
||||
LCD_SetTextColor(player->color); // Set the text color to the players color
|
||||
LCD_DisplayStringXY(TFT_GAME_HEADER_PLAYER_X+i*TFT_GAME_HEADER_PLAYER_WIDTH, TFT_GAME_HEADER_PLAYER_Y, buf); // Print the status
|
||||
}
|
||||
|
||||
if(player->state!=dead) {
|
||||
if(player->state!=dead) { // If the current player still lives not all players are dead ...
|
||||
all_players_dead=false;
|
||||
}
|
||||
}
|
||||
|
||||
if(all_players_dead) {
|
||||
game->state=ended;
|
||||
if(all_players_dead) { // End the game if all players are dead
|
||||
game->state=ended; // Set the state to ended
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
@@ -318,9 +318,9 @@ bool game_step(game_t* game, uint64_t deltaTime) {
|
||||
}
|
||||
|
||||
case ended:
|
||||
while(!io_button_has_edge(BTN_START));
|
||||
LCD_Clear(GUI_COLOR_BLACK);
|
||||
game->state= prestart;
|
||||
while(!io_button_has_edge(BTN_START)); // Wait for the start button to be pressed again
|
||||
LCD_Clear(GUI_COLOR_BLACK); // Clear the background
|
||||
game->state= prestart; // Set the state to prestart
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user