From 0590a782b81560ea0be2e6ef753d9fa56fc449df Mon Sep 17 00:00:00 2001 From: Hanse-14 Date: Mon, 18 Dec 2023 00:06:28 +0100 Subject: [PATCH] Add input functions - user must enter nickname - user must enter difficulty level - user must enter map --- include/menu.h | 15 +++- include/render.h | 1 + src/input.c | 7 ++ src/menu.c | 95 ++++++++++++++++----- src/render.c | 214 +++++++++++++++++++++++++++++++++++------------ 5 files changed, 253 insertions(+), 79 deletions(-) diff --git a/include/menu.h b/include/menu.h index 0154645..c5268c0 100644 --- a/include/menu.h +++ b/include/menu.h @@ -8,8 +8,10 @@ #define MAX_COLOURS 10 #define MAX_LINES_TFF 20 //max lines (of ttf) for the whole project #define MAX_LINES_STARTSCREEN 6 -#define MAX_LINES_SETTINGS 7 -#define MAX_LINE_INFOSCREEN 17 +#define MAX_LINES_SETTINGS 14 +#define MAX_LINES_INFOSCREEN 17 + +#define TEXT_INPUT_SIZE 30 #define TIME_BETWEEN_UPDATE_MENU 1000 // [ms] // Enum that defines the active menu @@ -40,8 +42,13 @@ typedef struct tllData_t int lineHeight; // to print text in middle int totalHeight; // to print text in middle int textPrintPosition; // where first line is printed - const time_t cycleDuration; - bool showEnter; + const time_t cycleDuration; // time between blinking ENTER + bool showEnter; // ENTER should be printed only every second cycle + int inputStatus; // 1 if player name was entered; 2 if difficulty level was entered, 3 map was entered + char textInput[TEXT_INPUT_SIZE]; // auxiliary variable for user input + char userName[TEXT_INPUT_SIZE]; // user name + int userDifficultyLevel; // difficulty level which was entered by user + int userSelectedMap; // map which was entered by user } ttlData_t; extern ttlData_t ttlStorage; diff --git a/include/render.h b/include/render.h index 7401ad2..081f034 100644 --- a/include/render.h +++ b/include/render.h @@ -1,5 +1,6 @@ #pragma once +#include #include "game.h" #include "snake.h" #include "menu.h" diff --git a/src/input.c b/src/input.c index 9a38cf9..d39e656 100644 --- a/src/input.c +++ b/src/input.c @@ -81,6 +81,7 @@ void handleInput_runningState(SDL_Event event) void processInputEvent() { SDL_Event event; + // loop through all queued input events that occoured since last run while (SDL_PollEvent(&event)) { @@ -110,6 +111,12 @@ void processInputEvent() break; } } + //--- key text input --- + // not possible to make this check in the else if query before + else if(event.type == SDL_TEXTINPUT && game.gameState == MENU) + { + menuHandleInput(event); + } } return; diff --git a/src/menu.c b/src/menu.c index d825087..80b4728 100644 --- a/src/menu.c +++ b/src/menu.c @@ -15,7 +15,11 @@ ttlData_t ttlStorage = .fontSize_30 = 30, // size of font .fontSize_200 = 200, // size of font .cycleDuration = 500, // time between show and not showing ENTER in start screen - .showEnter = false + .showEnter = false, + .inputStatus = 0, + .textInput[0] = '\0' + + }; // Default @@ -53,7 +57,7 @@ void manageMenu() // shows start screen with blinking ENTER void showStartScreen() { - LOGI("menu: showing start-screen\n"); + LOGD("menu: showing start-screen\n"); time_t now = GET_TIME_MS(); @@ -69,7 +73,7 @@ void showStartScreen() void showLeaderboard() { - LOGI("menu: showing leaderboard\n"); + LOGD("menu: showing leaderboard\n"); //--- play crash sound --- //play audio file, wait until playback is finished @@ -84,7 +88,7 @@ void showLeaderboard() void showPauseScreen() { - LOGI("menu: showing leaderboard\n"); + LOGD("menu: showing leaderboard\n"); game.gameState = PAUSED; return; } @@ -92,7 +96,7 @@ void showPauseScreen() void showSettings() { - LOGI("menu: showing settings\n"); + LOGD("menu: showing settings\n"); time_t now = GET_TIME_MS(); @@ -110,7 +114,7 @@ void showSettings() void showInfoScreen() { - LOGI("menu: showing info-screen\n"); + LOGD("menu: showing info-screen\n"); time_t now = GET_TIME_MS(); @@ -125,11 +129,12 @@ void showInfoScreen() } // handle input over keyboard -// delete text at the and of one menu section +// delete text at the end of one menu section void menuHandleInput(SDL_Event event){ //compare 'handleInput_runningState(SDL_Event event)' in input.c switch(activeMenu) - { + { + // start case START: switch (event.key.keysym.sym) { @@ -148,13 +153,13 @@ void menuHandleInput(SDL_Event event){ } break; - + // settings case SETTINGS: switch(event.key.keysym.sym) { - case SDLK_q: // q: quit - game.gameState = EXIT; - break; + // case SDLK_q: // q: quit + // game.gameState = EXIT; + // break; case SDLK_F1: // go to info screen activeMenu = INFOSCREEN; @@ -166,19 +171,70 @@ void menuHandleInput(SDL_Event event){ } break; - case SDLK_RETURN: //start game - activeMenu = NONE; - game.gameState = RUNNING; - // delete text - for (int i = 0; i < MAX_LINES_TFF; ++i) + case SDLK_RETURN: // confirm user input or start game + + switch(ttlStorage.inputStatus) { - SDL_DestroyTexture(ttlStorage.textTextures[i]); - } + case 0: // confirm user name + // user must enter at least one letter + if(ttlStorage.textInput[0] != '\0') + { + ttlStorage.inputStatus++; + strcpy(ttlStorage.userName, ttlStorage.textInput); // copy textInput to userName + memset(ttlStorage.textInput, 0, sizeof(ttlStorage.textInput)); // clear textInput[] + } + break; + + case 1: // confirm difficulty level + // user input must be between 0 and 3 + if((ttlStorage.textInput[0] > '0') && (ttlStorage.textInput[0] <= '3')) + { + ttlStorage.inputStatus++; + ttlStorage.userDifficultyLevel = ttlStorage.textInput[0] - '\0'; // copy textInput to userDifficultyLevel + } + memset(ttlStorage.textInput, 0, sizeof(ttlStorage.textInput)); // clear textInput[] + break; + + case 2: // confirm map + // user input must be between 0 and 3 + if((ttlStorage.textInput[0] > '0') && (ttlStorage.textInput[0] <= '3')) + { + ttlStorage.inputStatus++; + ttlStorage.userSelectedMap = ttlStorage.textInput[0] - '\0'; // copy textInput to userSelectedMap + } + memset(ttlStorage.textInput, 0, sizeof(ttlStorage.textInput)); // clear textInput[] + break; + + case 3: // start game + activeMenu = NONE; + game.gameState = RUNNING; + // delete text + for (int i = 0; i < MAX_LINES_TFF; ++i) + { + SDL_DestroyTexture(ttlStorage.textTextures[i]); + } + break; + } + break; + + + default: // for user inputs + // keyboard input + if (event.type == SDL_TEXTINPUT) + { + strcat(ttlStorage.textInput, event.text.text); + } + // delete single inputs via backspace + else if (event.type == SDL_KEYDOWN && event.key.keysym.sym == SDLK_BACKSPACE && strlen(ttlStorage.textInput) > 0) + { + ttlStorage.textInput[strlen(ttlStorage.textInput) - 1] = '\0'; + } break; } break; + // info screen case INFOSCREEN: switch(event.key.keysym.sym) { @@ -198,7 +254,6 @@ void menuHandleInput(SDL_Event event){ break; } - return; } diff --git a/src/render.c b/src/render.c index f825458..102e051 100644 --- a/src/render.c +++ b/src/render.c @@ -213,65 +213,168 @@ void renderStartMenu() //-------------------SETTINGS----------------------------------- //-------------------------------------------------------------- void renderSettings() -{ +{ + int textWidth, textHeight; // auxiliary variables for printing + + // text in menu settings + static char* textLinesInMenu[MAX_LINES_SETTINGS] = { + "Fuer Infos zum Gameplay, sowie einigen Shortcuts druecken Sie bitte F1", + " ", + " ", + "Bitte geben Sie ihren Nickname ein: ", + " ", + " ", + "Bitte geben Sie ein Schwierigkeitslevel ein:", + "1 fuer Einfach - 2 fuer Fortgeschritten - 3 fuer Profi", + " ", + " ", + "Bitte waehlen Sie eine Map:", + "1 fuer Klein - 2 fuer Mittel - 3 fuer Gross", + " ", + "-- ENTER --" + }; + + //=========== only first loop ================ if(ttlStorage.lastTimeStep == 0) - { + { + printf("In first loop\n"); ttlStorage.ptrFont_20 = TTF_OpenFont("../fonts/Prototype.ttf", ttlStorage.fontSize_20); - - // text in start screen - const char* textLines[] = { - "Fuer Infos zum Gameplay, sowie einigen Shortcuts druecken Sie bitte F1", - " ", - //"Bitte geben Sie ihren Spielnamen ein: ", - "test", - "test", - "test", - "test", - "-- ENTER --" - }; - - // render setting screen - for (int i = 0; i < MAX_LINES_SETTINGS; ++i) - { - ttlStorage.textSurface = TTF_RenderText_Solid(ttlStorage.ptrFont_20, textLines[i], ttlStorage.textColour[5]); - ttlStorage.textTextures[i] = SDL_CreateTextureFromSurface(game.renderer, ttlStorage.textSurface); - SDL_FreeSurface(ttlStorage.textSurface); - } + SDL_StartTextInput(); // start text input } + - //=========== is always performerd ================ - SDL_RenderClear(game.renderer); - - int textWidth, textHeight; - - // print settings - ttlStorage.textPrintPosition = 0; // first print position - for (int i = 0; i < (MAX_LINES_SETTINGS - 1); ++i) { + //=========dependent of which text is currently entered(userName, difficultyLevel, userSelectedMap) ========= + switch(ttlStorage.inputStatus) + { + //=== no user inputs === + case 0: + //--- rendering --- + for (int i = 0; i < 4; ++i) + { + ttlStorage.textSurface = TTF_RenderText_Solid(ttlStorage.ptrFont_20, textLinesInMenu[i], ttlStorage.textColour[5]); + ttlStorage.textTextures[i] = SDL_CreateTextureFromSurface(game.renderer, ttlStorage.textSurface); + SDL_FreeSurface(ttlStorage.textSurface); + + } - SDL_QueryTexture(ttlStorage.textTextures[i], NULL, NULL, &textWidth, &textHeight); + ttlStorage.textSurface = TTF_RenderText_Solid(ttlStorage.ptrFont_20, ttlStorage.textInput, ttlStorage.textColour[5]); + ttlStorage.textTextures[4] = SDL_CreateTextureFromSurface(game.renderer, ttlStorage.textSurface); + SDL_FreeSurface(ttlStorage.textSurface); + SDL_RenderClear(game.renderer); - SDL_Rect dstRect = { 1, ttlStorage.textPrintPosition, textWidth, textHeight }; - SDL_RenderCopy(game.renderer, ttlStorage.textTextures[i], NULL, &dstRect); - ttlStorage.textPrintPosition += textHeight; // increase print position - } + //--- printing --- + ttlStorage.textPrintPosition = 0; // first print position + for (int i = 0; i < 5; ++i) + { + SDL_QueryTexture(ttlStorage.textTextures[i], NULL, NULL, &textWidth, &textHeight); + SDL_Rect dstRect = { 1, ttlStorage.textPrintPosition, textWidth, textHeight }; + SDL_RenderCopy(game.renderer, ttlStorage.textTextures[i], NULL, &dstRect); + ttlStorage.textPrintPosition += textHeight; // increase print position + } + break; + + + // === one user input === + case 1: + textLinesInMenu[4] = ttlStorage.userName; + //--- rendering --- + for (int i = 0; i < 8; ++i) + { + ttlStorage.textSurface = TTF_RenderText_Solid(ttlStorage.ptrFont_20, textLinesInMenu[i], ttlStorage.textColour[5]); + ttlStorage.textTextures[i] = SDL_CreateTextureFromSurface(game.renderer, ttlStorage.textSurface); + SDL_FreeSurface(ttlStorage.textSurface); + + } + + ttlStorage.textSurface = TTF_RenderText_Solid(ttlStorage.ptrFont_20, ttlStorage.textInput, ttlStorage.textColour[5]); + ttlStorage.textTextures[8] = SDL_CreateTextureFromSurface(game.renderer, ttlStorage.textSurface); + SDL_FreeSurface(ttlStorage.textSurface); + SDL_RenderClear(game.renderer); + + //---printing --- + ttlStorage.textPrintPosition = 0; // first print position + for (int i = 0; i < 9; ++i) + { + SDL_QueryTexture(ttlStorage.textTextures[i], NULL, NULL, &textWidth, &textHeight); + SDL_Rect dstRect = { 1, ttlStorage.textPrintPosition, textWidth, textHeight }; + SDL_RenderCopy(game.renderer, ttlStorage.textTextures[i], NULL, &dstRect); + ttlStorage.textPrintPosition += textHeight; // increase print position + } + break; + + //=== two user inputs === + case 2: + textLinesInMenu[8] = &(ttlStorage.userDifficultyLevel); + //--- rendering --- + for (int i = 0; i < 12; ++i) + { + ttlStorage.textSurface = TTF_RenderText_Solid(ttlStorage.ptrFont_20, textLinesInMenu[i], ttlStorage.textColour[5]); + ttlStorage.textTextures[i] = SDL_CreateTextureFromSurface(game.renderer, ttlStorage.textSurface); + SDL_FreeSurface(ttlStorage.textSurface); + + } + + ttlStorage.textSurface = TTF_RenderText_Solid(ttlStorage.ptrFont_20, ttlStorage.textInput, ttlStorage.textColour[5]); + ttlStorage.textTextures[12] = SDL_CreateTextureFromSurface(game.renderer, ttlStorage.textSurface); + SDL_FreeSurface(ttlStorage.textSurface); + SDL_RenderClear(game.renderer); + + //---printing --- + ttlStorage.textPrintPosition = 0; // first print position + for (int i = 0; i < 13; ++i) + { + SDL_QueryTexture(ttlStorage.textTextures[i], NULL, NULL, &textWidth, &textHeight); + SDL_Rect dstRect = { 1, ttlStorage.textPrintPosition, textWidth, textHeight }; + SDL_RenderCopy(game.renderer, ttlStorage.textTextures[i], NULL, &dstRect); + ttlStorage.textPrintPosition += textHeight; // increase print position + } + break; + + //=== user inputs completely + case 3: + textLinesInMenu[12] = &(ttlStorage.userSelectedMap); + //--- rendering --- + for (int i = 0; i < (MAX_LINES_SETTINGS - 1); ++i) + { + ttlStorage.textSurface = TTF_RenderText_Solid(ttlStorage.ptrFont_20, textLinesInMenu[i], ttlStorage.textColour[5]); + ttlStorage.textTextures[i] = SDL_CreateTextureFromSurface(game.renderer, ttlStorage.textSurface); + SDL_FreeSurface(ttlStorage.textSurface); + + } + + ttlStorage.textSurface = TTF_RenderText_Solid(ttlStorage.ptrFont_20, textLinesInMenu[MAX_LINES_SETTINGS - 1], ttlStorage.textColour[5]); + ttlStorage.textTextures[MAX_LINES_SETTINGS - 1] = SDL_CreateTextureFromSurface(game.renderer, ttlStorage.textSurface); + SDL_FreeSurface(ttlStorage.textSurface); + SDL_RenderClear(game.renderer); + + //---printing --- + ttlStorage.textPrintPosition = 0; // first print position + for (int i = 0; i < (MAX_LINES_SETTINGS - 1); ++i) + { + SDL_QueryTexture(ttlStorage.textTextures[i], NULL, NULL, &textWidth, &textHeight); + SDL_Rect dstRect = { 1, ttlStorage.textPrintPosition, textWidth, textHeight }; + SDL_RenderCopy(game.renderer, ttlStorage.textTextures[i], NULL, &dstRect); + ttlStorage.textPrintPosition += textHeight; // increase print position + } //print ENTER every second cycle - if(ttlStorage.showEnter) - { - ttlStorage.textPrintPosition = (config.windowSize / 1.5); // print position for ENTER - SDL_QueryTexture(ttlStorage.textTextures[MAX_LINES_SETTINGS-1], NULL, NULL, &textWidth, &textHeight); - SDL_Rect dstRect1 = { (config.windowSize - textWidth) / 2, ttlStorage.textPrintPosition, textWidth, textHeight }; - SDL_RenderCopy(game.renderer, ttlStorage.textTextures[MAX_LINES_SETTINGS-1], NULL, &dstRect1); - } - - // update screen + if(ttlStorage.showEnter) + { + ttlStorage.textPrintPosition = (config.windowSize / 1.5); // print position for ENTER + SDL_QueryTexture(ttlStorage.textTextures[MAX_LINES_SETTINGS-1], NULL, NULL, &textWidth, &textHeight); + SDL_Rect dstRect1 = { (config.windowSize - textWidth) / 2, ttlStorage.textPrintPosition, textWidth, textHeight }; + SDL_RenderCopy(game.renderer, ttlStorage.textTextures[MAX_LINES_SETTINGS-1], NULL, &dstRect1); + } + break; + } + + // update screen SDL_RenderPresent(game.renderer); ttlStorage.lastTimeStep = GET_TIME_MS(); return; - } //-------------------------------------------------------------- @@ -284,27 +387,28 @@ void renderInfoScreen() { // text in start screen const char* textLines[] = { - " Steuerung: W (nach oben)", + " STEUERUNG: W (nach oben)", " A (nach links)", " S (nach unten)", " D (nach rechts) ", - " oder: Pfeiltasten ", + " oder: Pfeiltasten ", " ", " ", - " Pause: p", - " oder: Leertaste", + " PAUSE: p", + " oder: Leertaste", " ", " ", - "Spiel verlassen: q ", + "SPIEL VERLASSEN: q ", " ", " ", " ", "By Jonas Schoenberger, Johannes Graf und Julia Steinberger", "-- ENTER --" }; - + + // render setting screen - for (int i = 0; i < MAX_LINE_INFOSCREEN; ++i) + for (int i = 0; i < MAX_LINES_INFOSCREEN; ++i) { ttlStorage.textSurface = TTF_RenderText_Solid(ttlStorage.ptrFont_20, textLines[i], ttlStorage.textColour[5]); ttlStorage.textTextures[i] = SDL_CreateTextureFromSurface(game.renderer, ttlStorage.textSurface); @@ -320,7 +424,7 @@ void renderInfoScreen() // print settings ttlStorage.textPrintPosition = 0; // first print position - for (int i = 0; i < (MAX_LINE_INFOSCREEN - 1); ++i) { + for (int i = 0; i < (MAX_LINES_INFOSCREEN - 1); ++i) { SDL_QueryTexture(ttlStorage.textTextures[i], NULL, NULL, &textWidth, &textHeight); @@ -333,9 +437,9 @@ void renderInfoScreen() if(ttlStorage.showEnter) { ttlStorage.textPrintPosition = (config.windowSize / 1.5); // print position for ENTER - SDL_QueryTexture(ttlStorage.textTextures[MAX_LINE_INFOSCREEN-1], NULL, NULL, &textWidth, &textHeight); + SDL_QueryTexture(ttlStorage.textTextures[MAX_LINES_INFOSCREEN-1], NULL, NULL, &textWidth, &textHeight); SDL_Rect dstRect1 = { (config.windowSize - textWidth) / 2, ttlStorage.textPrintPosition, textWidth, textHeight }; - SDL_RenderCopy(game.renderer, ttlStorage.textTextures[MAX_LINE_INFOSCREEN-1], NULL, &dstRect1); + SDL_RenderCopy(game.renderer, ttlStorage.textTextures[MAX_LINES_INFOSCREEN-1], NULL, &dstRect1); }