diff --git a/src/game.c b/src/game.c index 537085a..e285f8a 100644 --- a/src/game.c +++ b/src/game.c @@ -11,9 +11,6 @@ void game_init(game_t* game, uint16_t ticks_per_sec) { // gpio init io_init(); - // adc init - init_adc(); - // lcd init LCD_Init(); LCD_Clear(GUI_COLOR_BLACK); @@ -74,22 +71,22 @@ bool game_check_boundary_collision(game_t* game, player_t* player, uint8_t pixel // Check boundary collision switch(player->direction){ case up: - if((int16_t)(player->position.y) - pixels <= TFT_GAME_FIELD_TOP){ + if((int16_t)(player->position.y) - pixels <= TG_FIELD_TOP){ return true; // Collision at top boundary } break; case down: - if((int16_t)(player->position.y) + pixels >= (TFT_HEIGHT - TFT_GAME_FIELD_BOTTOM - 1)){ + if((int16_t)(player->position.y) + pixels >= (TFT_HEIGHT - TG_FIELD_BOTTOM - 1)){ return true; // Collision at bottom boundary } break; case left: - if((int16_t)(player->position.x) - pixels <= TFT_GAME_FIELD_LEFT){ + if((int16_t)(player->position.x) - pixels <= TG_FIELD_LEFT){ return true; // Collision at left boundary } break; case right: - if((int16_t)(player->position.x) + pixels >= (TFT_WIDTH - TFT_GAME_FIELD_RIGHT - 1)){ + if((int16_t)(player->position.x) + pixels >= (TFT_WIDTH - TG_FIELD_RIGHT - 1)){ return true; // Collision at right boundary } break; @@ -210,131 +207,247 @@ bool game_player_update(game_t* game, player_t* player, uint8_t pixels){ return state_changed; // return state } +void game_get_color(uint16_t confbits, uint16_t* player1_color, uint16_t* player2_color) { + + //we have 4 bits per player color, we use 1 bit for red, 2 for green, 1 for blue + //Display color is 16 bit: 5bits red (15-11), 6 green (10-5), 5 blue (4-0) + *player1_color =0; + *player2_color =0; + uint16_t temp; + if(confbits&0x80) { //player1, red1 + *player1_color|=0xF800; //set full red + } + temp = (confbits&0x60) << 1; //move the player1, green1-2 bits to the highest bit position (bits 7-6) + *player1_color|= temp << 3; //move green into the right position (bits 10-9) + if(confbits&0x10) { //player 1, blue1 + *player1_color|=0x1F; //set full blue + } + if(*player1_color==0) { + *player1_color= (3 << 11) | (7 << 5) | (3 << 0); //set color to gray (2 bits active per color, or 3 bits for green) + } + + + if(confbits&0x08) { //player2, red1 + *player2_color|=0xF800; //set full red + } + temp = (confbits&0x06) << 5; //move the player2, green1-2 bits to the highest bit position (bits 7-6) + *player2_color|= temp << 3; //move green into the right position (bits 10-9) + if(confbits&0x01) { //player 2, blue1 + *player2_color|=0x1F; //set full blue + } + + if(*player2_color==0) { + *player2_color= (3 << 11) | (7 << 5) | (3 << 0); //set color to gray (2 bits active per color, or 3 bits for green) + } +} + +static const char* texts [] = { + "Config Instructions:", + "* Change the player colors using the switches S7-S0", + "* Use the poti to change the game speed", + "* Press T0 to start the game", + "", + "Game Instructions:", + "* Player 1 Keys: T3 and T2", + "* Player 2 Keys: T1 and T0", + "* Stay alive!", + NULL +}; + + +bool game_step_prestart(game_t* game) { + + //Draw "Player x: Color" Strings + for(int i=0; iplayer[0]), // Fill object of player 1 + BTN_PLAYER_1_LEFT, // Left-button of player1 + BTN_PLAYER_1_RIGHT, // Right-button of player 1 + (point_t) { //Start point of player 1 + .x=(TG_FIELD_START_OFFSET + TG_FIELD_LEFT), // x start coordinate + .y=(((TFT_HEIGHT - TG_FIELD_TOP - TG_FIELD_BOTTOM) / 2) + TG_FIELD_TOP) // y start coordinate + }, + player1_color, // color of player 1 + right); // initial moving direction of player 2 + + //Init player 2 + player_init(&(game->player[1]), + BTN_PLAYER_2_LEFT, + BTN_PLAYER_2_RIGHT, + (point_t) { + .x=(TFT_WIDTH - 1 - TG_FIELD_RIGHT - TG_FIELD_START_OFFSET), // x start coordinate + .y=(((TFT_HEIGHT - TG_FIELD_TOP - TG_FIELD_BOTTOM) / 2) + TG_FIELD_TOP) // y start coordinate + }, + player2_color, + left); + + + game->state = running; // Switch the game state to running + game->time = 0; // Reset the game time + + LCD_Clear(GUI_COLOR_BLACK); // Clear the background + + // Draw the game boundary + LCD_DrawRect(TG_FIELD_LEFT, // left top x + TG_FIELD_TOP, // left top y + (TFT_WIDTH - TG_FIELD_LEFT - TG_FIELD_RIGHT - 1), // right bottom x + (TFT_HEIGHT - TG_FIELD_TOP - TG_FIELD_BOTTOM - 1), // right bottom y + GUI_COLOR_WHITE); // Color of the boundary + + LCD_SetTextColor(GUI_COLOR_WHITE); // Reset color to white + LCD_DisplayStringXY(TG_HEADER_TIME_X, TG_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(TG_HEADER_PLAYER_X+i*TG_HEADER_PLAYER_WIDTH, TG_HEADER_PLAYER_Y, buf); // Print everything + } + + return true; +} + +bool game_step_running(game_t* game, uint64_t delta_time) + +{ + uint16_t ticks; + uint16_t pixels = 0; + + 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; // Calculate number of seconds from past ticks + + 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){ // 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(TG_HEADER_TIME_X, TG_HEADER_TIME_Y, buf); // Print the time + } + } + + bool all_players_dead = true; // Assume all players are dead ;-) + + // For each player do ... + 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); // Format and paste the status to the buffer + LCD_SetTextColor(player->color); // Set the text color to the players color + LCD_DisplayStringXY(TG_HEADER_PLAYER_X+i*TG_HEADER_PLAYER_WIDTH, TG_HEADER_PLAYER_Y, buf); // Print the status + } + + if(player->state!=dead) { // If the current player still lives not all players are dead ... + all_players_dead=false; + } + } + + 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; + } +} + +bool game_step_ended(game_t* game) { + 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; +} + bool game_step(game_t* game, uint64_t delta_time) { // Calculate the next game step - static long l = 0; switch(game->state) { case prestart: // If the game is in prestart state - // Draw welcome screen - LCD_DrawRectF(10,10,100,50,GUI_COLOR_BLUE); - - // TODO: Read color of player 1 - uint16_t player1_color = get_player_color(&(game->player[0]), true); - - // TODO: Read color of player 2 - uint16_t player2_color = get_player_color(&(game->player[1]), false); - - // TODO: Read potentiometer and set game speed accordingly - uint16_t game_speed = read_adc(); - - // 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), // 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, // color - right); // default moving direction - - 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), // 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, // color - left); // default moving direction - - // Wait on player to press start - while(!io_button_has_edge(BTN_START)); - - game->state = running; // Switch the game state to running - game->time = 0; // Reset the game time - - LCD_Clear(GUI_COLOR_BLACK); // Clear the background - - // 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; - + return game_step_prestart(game); case running: - { - uint16_t ticks; - uint16_t pixels = 0; - - 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; // Calculate number of seconds from past ticks - - 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){ // 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 ... - 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); // 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 the current player still lives not all players are dead ... - all_players_dead=false; - } - } - - 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; - } - } - + return game_step_running(game,delta_time); case ended: - 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; + return game_step_ended(game); } } diff --git a/src/game.h b/src/game.h index ae81f3f..8e9634d 100644 --- a/src/game.h +++ b/src/game.h @@ -23,16 +23,26 @@ #define BTN_PLAYER_2_RIGHT 0 // Display definitions -#define TFT_GAME_FIELD_TOP 20 -#define TFT_GAME_FIELD_BOTTOM 5 -#define TFT_GAME_FIELD_LEFT 5 -#define TFT_GAME_FIELD_RIGHT 5 -#define TFT_GAME_FIELD_START_OFFSET 10 -#define TFT_GAME_HEADER_TIME_X 5 -#define TFT_GAME_HEADER_TIME_Y 3 -#define TFT_GAME_HEADER_PLAYER_X 100 -#define TFT_GAME_HEADER_PLAYER_Y 3 -#define TFT_GAME_HEADER_PLAYER_WIDTH 100 +#define TG_FIELD_TOP 20 +#define TG_FIELD_BOTTOM 5 +#define TG_FIELD_LEFT 5 +#define TG_FIELD_RIGHT 5 +#define TG_FIELD_START_OFFSET 10 +#define TG_HEADER_TIME_X 5 +#define TG_HEADER_TIME_Y 3 +#define TG_HEADER_PLAYER_X 100 +#define TG_HEADER_PLAYER_Y 3 +#define TG_HEADER_PLAYER_WIDTH 100 +#define TG_START_X 10 +#define TG_START_Y 10 +#define TG_START_BLOCK_HEIGHT 20 +#define TG_START_BLOCK_SPACING 5 +#define TG_START_FONT_OFFSET_Y 5 +#define TG_START_FONT_HEIGHT 10 +#define TG_START_COL2_X 90 +#define TG_START_COL2_WIDTH 100 + + /** * @brief Game data type which contains all game data and players. diff --git a/src/io.c b/src/io.c index 2c486a7..15a2d2e 100644 --- a/src/io.c +++ b/src/io.c @@ -19,18 +19,15 @@ static pin_t pin_t0; static pin_t pin_t1; static pin_t pin_t2; static pin_t pin_t3; -static pin_t pin_s0; -static pin_t pin_s1; -static pin_t pin_s2; -static pin_t pin_s3; -static pin_t pin_s4; -static pin_t pin_s5; -static pin_t pin_s6; -static pin_t pin_s7; static uint8_t new = 0; static uint8_t old = 0; static volatile uint8_t edg = 0; +//Memory mapped IO's +static volatile unsigned char* LED = (volatile unsigned char*)0x6C000200; +static volatile unsigned char* SWITCH = (volatile unsigned char*)0x6C000400; + + void pin_create(pin_t* pin, GPIO_TypeDef* GPIO, uint8_t pinnr, bool input) { GPIO_InitTypeDef gi; // Create gpio init structure GPIO_StructInit(&gi); // Fill gpio init structure with defaults @@ -82,41 +79,7 @@ void io_init(void){ pin_create(&pin_t2, GPIOB, 14, true); // create pin_t2 pin_create(&pin_t3, GPIOI, 0, true); // create pin_t3 - // TODO: Create color choosing pins - /*pin_create(&pin_s0, GPIO, , true); // create pin_t0 - pin_create(&pin_s1, GPIO, , true); // create pin_t1 - pin_create(&pin_s2, GPIO, , true); // create pin_t2 - pin_create(&pin_s3, GPIO, , true); // create pin_t3 - pin_create(&pin_s4, GPIO, , true); // create pin_t0 - pin_create(&pin_s5, GPIO, , true); // create pin_t1 - pin_create(&pin_s6, GPIO, , true); // create pin_t2 - pin_create(&pin_s7, GPIO, , true); // create pin_t3*/ - - -} - -void io_process(void) { - new = pin_get(&pin_t0) | - pin_get(&pin_t1) << 1 | - pin_get(&pin_t2) << 2 | - pin_get(&pin_t3) << 3; - - edg |= (new ^ old) & new; // detect positive edge - old = new; -} - -bool io_button_has_edge(uint8_t btnnumber) { - uint8_t bm = (1 << btnnumber); // create bitmask - bool status = ((edg & bm) > 0); // check if button is pressed - - if(status){ - edg &= ~bm; // clear edge bit - } - - return status; -} - -void init_adc(){ + // ADC Init /* //Enable the peripheral clock of GPIOB //This has been already done in the startup code @@ -148,6 +111,28 @@ void init_adc(){ // Page 418/1718 of "RM0090 Reference Reference Manual (October 2014)" ADC1->CR2 = ADC_CR2_ADON; */ + +} + +void io_process(void) { + new = pin_get(&pin_t0) | + pin_get(&pin_t1) << 1 | + pin_get(&pin_t2) << 2 | + pin_get(&pin_t3) << 3; + + edg |= (new ^ old) & new; // detect positive edge + old = new; +} + +bool io_button_has_edge(uint8_t btnnumber) { + uint8_t bm = (1 << btnnumber); // create bitmask + bool status = ((edg & bm) > 0); // check if button is pressed + + if(status){ + edg &= ~bm; // clear edge bit + } + + return status; } uint16_t read_adc(){ @@ -170,12 +155,9 @@ uint16_t read_adc(){ return value; } -uint16_t get_player_color(player_t* player, bool first_player){ - if(!first_player){ - // Read bit 0-3 and calculate color - }else{ - // Read but 4-7 and calculate color - } - return 0; + +uint8_t read_switches() { + *LED=*SWITCH; + return *SWITCH; } diff --git a/src/io.h b/src/io.h index 19397f6..f35fe6e 100644 --- a/src/io.h +++ b/src/io.h @@ -26,11 +26,6 @@ void io_process(void); */ bool io_button_has_edge(uint8_t btnnumber); -/** - * @brief Initialize the analog/digital converter in order to read the potentiometer. - */ -void init_adc(); - /** * @brief Read a value from the analog/digital converter. * @@ -38,15 +33,13 @@ void init_adc(); */ uint16_t read_adc(); + /** - * @brief Uses buttons s0-7 to determine the coler of the player. - * Player1 is represented by the bits s0-3. - * Player2 is represented by the bits s4-s7. + * @brief Read the values of the 8 switches * - * @param player Playerobject - * @param first_player Specify first or second player - * @return Color value for the according player + * @return Returns the state of the switches, one bit per switch, high active */ -uint16_t get_player_color(player_t* player, bool first_player); +uint8_t read_switches(); + #endif /* IO_H */