From d68baac859b0b9977022837ecd3ff44e20ecc1b9 Mon Sep 17 00:00:00 2001 From: JanEhehalt Date: Sat, 14 Jan 2023 15:00:40 +0100 Subject: [PATCH] Jeder screen hat jetzt einen eigenen UiContainer, Bug mit selectable hovered gefixed, SegFault gefixed --- Ui/debug.c | 4 ++- Ui/debug.h | 2 +- Ui/screenIDs.h | 3 ++ Ui/selectable.c | 15 +++++---- Ui/uiContainer.c | 83 +++++++++++++++++++++++++++++++++++++----------- Ui/uiContainer.h | 4 +-- game.c | 4 +++ game.h | 3 ++ main.c | 28 +++++----------- 9 files changed, 96 insertions(+), 50 deletions(-) diff --git a/Ui/debug.c b/Ui/debug.c index 676a06b..a0f5f8e 100644 --- a/Ui/debug.c +++ b/Ui/debug.c @@ -5,7 +5,7 @@ #include #include "../Input/inputHandler.h" -void DebugDraw(Game *game, UiContainer *uiContainer){ +void DebugDraw(Game *game){ char strings[30][41]; // Platz für bis zu 30 Strings der Länge 40 int lineamount = 0; // sollte aktuell gehalten werden, wie viele Lines sind aktuell im Strings Array @@ -18,6 +18,8 @@ void DebugDraw(Game *game, UiContainer *uiContainer){ sprintf(strings[lineamount++], "MouseScreenY: %d", GetMouseY()); sprintf(strings[lineamount++], "MouseWorldX: %d", (int)game->inputHandler->cursorWorldPos.x); sprintf(strings[lineamount++], "MouseWorldY: %d", (int)game->inputHandler->cursorWorldPos.y); + sprintf(strings[lineamount++], "WorldTile: %d", (int)game->inputHandler->cursorWorldTile.x); + sprintf(strings[lineamount++], "WorldTile: %d", (int)game->inputHandler->cursorWorldTile.y); sprintf(strings[lineamount++], "Selected Layer: %d", game->inputHandler->selectedLayer); sprintf(strings[lineamount++], "DEPTH: %d", (int)(game->inputHandler->cursorWorldPos.x + game->inputHandler->cursorWorldPos.y + game->inputHandler->selectedLayer)); sprintf(strings[lineamount++], "Camera Zoom: %f", game->camera->zoom); diff --git a/Ui/debug.h b/Ui/debug.h index 6524983..d1f2933 100644 --- a/Ui/debug.h +++ b/Ui/debug.h @@ -7,6 +7,6 @@ #define DEBUG_FONT_SIZE 20 // Font size of the Debug window // Drawed das Debug Fenster in die obere Linke Ecke -void DebugDraw(Game *game, UiContainer *uiContainer); +void DebugDraw(Game *game); #endif \ No newline at end of file diff --git a/Ui/screenIDs.h b/Ui/screenIDs.h index 4108644..a97f4fe 100644 --- a/Ui/screenIDs.h +++ b/Ui/screenIDs.h @@ -1,6 +1,9 @@ #ifndef SCREENIDS_H_ #define SCREENIDS_H_ +// Keinen Platz zwischen den IDs lassen! Jede Zahl nutzen! + +#define SCREEN_AMOUNT 5 // AUCH IN GAME.H ÄNDERN!!! #define SCREEN_EXIT 0 // Will exit the game using code 0 #define SCREEN_MAINMENU 1 #define SCREEN_OPTIONS 2 diff --git a/Ui/selectable.c b/Ui/selectable.c index c8f93d6..97efab3 100644 --- a/Ui/selectable.c +++ b/Ui/selectable.c @@ -35,14 +35,14 @@ Selectable * SelectableInit(Texture2D textures[3], Texture2D backgroundTextures[ // Sobald ein Button gedrückt wurde in diesem Frame oder rect gezogen wird oder so ist sind Maus Funktionen gesperrt // verhindert Spawnen von entities wenn man UI Elemente Drückt etc void SelectableExecuteSelectable(Selectable *selectable, Game * game){ - // reset state after executing? - //selectable->state = SELECTABLE_STATE_DEFAULT; switch(selectable->id){ case SELECTABLE_ID_TEST: // Test Case Platzhalter - //printf("SELECTED\n"); + // Hier sollte eine Bedingung stehen die nur in einem Frame true sein kann + // Oder das selectable wird abgewählt indem seine ID auf default zurückgesetzt wird + // Sonst kann das hier jeden Frame passieren. ID wird nicht automatisch zurückgesetzt break; default: - printf("\n\n\n\n\n\n Unsupported SELECTABLE ID %d \n\n\n\n\n\n", selectable->id); + printf("\n\n\n\n\n\n WARNING: Unsupported SELECTABLE ID %d \n\n\n\n\n\n", selectable->id); break; } } @@ -68,11 +68,14 @@ int SelectableUpdateSelectableState(Selectable * selectable){ } int SelectableUnselectSelectable(Selectable * selectable){ - selectable->state = SELECTABLE_STATE_DEFAULT; + if(selectable->state == SELECTABLE_STATE_SELECTED){ + selectable->state = SELECTABLE_STATE_DEFAULT; + } + return selectable->state; } void SelectableDrawSelectable(Selectable * selectable){ - if(selectable->hasBackground) { + if(selectable->hasBackground == 1) { DrawTexture(selectable->backgroundTexture[selectable->state], selectable->position.x, selectable->position.y, WHITE); } DrawTexture(selectable->texture[selectable->state], selectable->position.x, selectable->position.y, WHITE); diff --git a/Ui/uiContainer.c b/Ui/uiContainer.c index de0e091..db6ccf8 100644 --- a/Ui/uiContainer.c +++ b/Ui/uiContainer.c @@ -4,9 +4,19 @@ #include "raylib.h" #include "stdlib.h" #include "stdio.h" +#include "screenIDs.h" +static UiContainer * UiContainerInitEmptyUiContainer(){ + UiContainer *uiContainer = malloc(sizeof(UiContainer)); + + uiContainer->buttonCounter = 0; + uiContainer->selectableCounter = 0; + + return uiContainer; +} -UiContainer * UiContainerInitPauseUiContainer(){ +// Only for use in UiContainer +static UiContainer * UiContainerInitPauseUiContainer(){ UiContainer *uiContainer = malloc(sizeof(UiContainer)); Texture2D textures[4] = { LoadTexture("assets/button.png"), //DEFAULT @@ -26,11 +36,15 @@ UiContainer * UiContainerInitPauseUiContainer(){ uiContainer->buttons[1] = exitButton; uiContainer->buttonCounter = 2; + // WICHTIG, auch wenn der UiContainer gar keine selectables hat! + uiContainer->selectableCounter = 0; + // Methode funktioniert wieso auch immer auch ohne dieses return. C returned Implizit odder was O_o return uiContainer; } -UiContainer * UiContainerInitMainMenuUiContainer(){ +// Only for use in UiContainer +static UiContainer * UiContainerInitMainMenuUiContainer(){ UiContainer *uiContainer = malloc(sizeof(UiContainer)); Texture2D textures[4] = { LoadTexture("assets/button.png"), //DEFAULT @@ -44,17 +58,21 @@ UiContainer * UiContainerInitMainMenuUiContainer(){ uiContainer->buttons[0] = continuebutton; uiContainer->buttonCounter = 1; + // WICHTIG, auch wenn der UiContainer gar keine selectables hat! + uiContainer->selectableCounter = 0; + position.y += 250; Button *exitButton = ButtonInitButton(textures, &position, "EXIT", 5, buttonFontSize, BUTTON_ID_EXIT); uiContainer->buttons[1] = exitButton; uiContainer->buttonCounter = 2; - // Methode funktioniert wieso auch immer auch ohne dieses return. C returned Implizit odder was O_o + // Methode funktioniert wieso auch immer auch ohne dieses return. GCC returned Implizit odder was O_o return uiContainer; } -UiContainer * UiContainerInitGameUiContainer(){ +// Only for use in UiContainer +static UiContainer * UiContainerInitGameUiContainer(){ UiContainer *uiContainer = malloc(sizeof(UiContainer)); uiContainer->buttonCounter = 0; @@ -68,8 +86,8 @@ UiContainer * UiContainerInitGameUiContainer(){ LoadTexture("assets/selectable_background_hovered.png"), //HOVERED LoadTexture("assets/selectable_background_selected.png") //SELECTED }; - Vector2 position = (Vector2){50, 250}; - int showDescription = 0; + Vector2 position = (Vector2){20, 300}; + int showDescription = 1; Selectable *selectable1 = SelectableInit(textures, backgroundTextures, 1, &position, "Building", showDescription, 9, 16, SELECTABLE_ID_TEST); position.y += 100; Selectable *selectable2 = SelectableInit(textures, backgroundTextures, 1,&position, "Building2", showDescription, 10, 16, SELECTABLE_ID_TEST); @@ -94,35 +112,62 @@ UiContainer * UiContainerInitGameUiContainer(){ return uiContainer; } -// Updated alle Buttons und führt gegebenenfalls deren Code aus -void UiContainerUpdateUiContainer(UiContainer *uiContainer, Game *game){ +UiContainer * UiContainerInitUiContainerForScreenID(int id){ + switch(id){ + case SCREEN_MAINMENU: + return UiContainerInitMainMenuUiContainer(); + case SCREEN_GAME: + return UiContainerInitGameUiContainer(); + case SCREEN_PAUSE: + return UiContainerInitPauseUiContainer(); + default: + printf("WARNING: Creating UiContainer for Screen ID %d (not implemented)\n", id); + return UiContainerInitEmptyUiContainer(); + } +} + +// Only for use in UiContainer, should not be used on their own +static void UpdateButtons(Game *game, Button **buttons, int buttonCounter){ int i = 0; - for(i=0 ; i < uiContainer->buttonCounter; i++){ - ButtonUpdateButtonState(uiContainer->buttons[i]); - if(uiContainer->buttons[i]->state == BUTTON_STATE_RELEASED){ - ButtonExecuteButton(uiContainer->buttons[i], game); + for(i=0 ; i < buttonCounter; i++){ + ButtonUpdateButtonState(buttons[i]); + if(buttons[i]->state == BUTTON_STATE_RELEASED){ + ButtonExecuteButton(buttons[i], game); } } - for(i=0 ; i < uiContainer->selectableCounter; i++){ - int setState = SelectableUpdateSelectableState(uiContainer->selectables[i]); +} + +// Only for use in UiContainer, should not be used on their own +static void UpdateSelectables(Game *game, Selectable **selectables, int selectableCounter){ + int i = 0; + for(i=0 ; i < selectableCounter; i++){ + int setState = SelectableUpdateSelectableState(selectables[i]); // Unselecting every selectable if one is selected if(setState == SELECTABLE_STATE_SELECTED){ int j; - for(j=0 ; j < uiContainer->selectableCounter; j++){ + for(j=0 ; j < selectableCounter; j++){ if(i != j){ - SelectableUnselectSelectable(uiContainer->selectables[j]); + SelectableUnselectSelectable(selectables[j]); } } } - if(uiContainer->selectables[i]->state == SELECTABLE_STATE_SELECTED){ - SelectableExecuteSelectable(uiContainer->selectables[i], game); + if(selectables[i]->state == SELECTABLE_STATE_SELECTED){ + SelectableExecuteSelectable(selectables[i], game); } } } -// Drawed alle Buttons +// Updated alle Buttons und Selectables und führt gegebenenfalls deren Code aus +void UiContainerUpdateUiContainer(UiContainer *uiContainer, Game *game){ + UpdateButtons(game, uiContainer->buttons, uiContainer->buttonCounter); + UpdateSelectables(game, uiContainer->selectables, uiContainer->selectableCounter); +} + +// Drawed alle Buttons und Selectables void UiContainerDrawUiContainer(UiContainer *uiContainer){ + if(uiContainer == 0) return; int i = 0; + // Funktion kann genauso wie update auch noch aufgeteilt werden, aktuell aber noch nicht notwendig for(i=0 ; i < uiContainer->buttonCounter; i++){ ButtonDrawButton(uiContainer->buttons[i]); } diff --git a/Ui/uiContainer.h b/Ui/uiContainer.h index 2c2ae90..502b7a5 100644 --- a/Ui/uiContainer.h +++ b/Ui/uiContainer.h @@ -16,8 +16,6 @@ typedef struct UiContainer{ void UiContainerUpdateUiContainer(UiContainer *uiContainer, Game *game); void UiContainerDrawUiContainer(UiContainer *uiContainer); -UiContainer * UiContainerInitPauseUiContainer(); -UiContainer * UiContainerInitGameUiContainer(); -UiContainer * UiContainerInitMainMenuUiContainer(); +UiContainer * UiContainerInitUiContainerForScreenID(int id); #endif \ No newline at end of file diff --git a/game.c b/game.c index d67f67c..a28b5d0 100644 --- a/game.c +++ b/game.c @@ -9,6 +9,7 @@ #include "Ui/screenIDs.h" #include "Entity/entity.h" #include "MapObject/mapobject.h" +#include "Ui/uiContainer.h" // returns pointer to new Game instance Game *GameInit() @@ -58,6 +59,9 @@ Game *GameInit() } } // ------- + for(i = 0; i < SCREEN_AMOUNT; i++){ + game->UiContainers[i] = UiContainerInitUiContainerForScreenID(i); + } return game; } diff --git a/game.h b/game.h index c8b03b0..6368b3f 100644 --- a/game.h +++ b/game.h @@ -3,6 +3,8 @@ #include "raylib.h" +#define SCREEN_AMOUNT 5 //AUCH IN SCREENIDS ÄNDERN + typedef struct Game{ Texture2D worker[8]; struct TextureAtlas *textures; @@ -13,6 +15,7 @@ typedef struct Game{ struct IsometricMap *map; struct MapObjectList *mapObjects; struct EntityList *entities; + struct UiContainer *UiContainers[SCREEN_AMOUNT]; int screen; } Game; diff --git a/main.c b/main.c index 7e5f56b..26d9fbc 100644 --- a/main.c +++ b/main.c @@ -19,12 +19,6 @@ int main(){ Game *game = GameInit(); - // TODO: Screen structs, die zum Beispiel die UiContainer enthalten? - - UiContainer *pauseScreenUiContainer = UiContainerInitPauseUiContainer(); - UiContainer *mainMenuScreenUiContainer = UiContainerInitMainMenuUiContainer(); - UiContainer *gameScreenUiContainer = UiContainerInitGameUiContainer(); - // Hides the operating systems own cursor HideCursor(); @@ -44,9 +38,7 @@ int main(){ printf("EXIT \n"); return 0; case SCREEN_MAINMENU: - // MainMenu hat aktuell nur paar Buttons - UiContainerUpdateUiContainer(mainMenuScreenUiContainer, game); - UiContainerDrawUiContainer(mainMenuScreenUiContainer); + // MainMenu hat aktuell nur paar Buttons, die unten gedrawed werden break; case SCREEN_OPTIONS: printf("OPTIONS \n"); @@ -65,9 +57,6 @@ int main(){ mouseInput(game); keyboardInput(game->inputHandler, game->camera); - // Button / UI stuff - UiContainerUpdateUiContainer(gameScreenUiContainer, game); - UiContainerDrawUiContainer(gameScreenUiContainer); if(IsKeyPressed(KEY_P)){ game->screen = SCREEN_PAUSE; @@ -93,13 +82,6 @@ int main(){ DrawText("WASD: Move Camera", 5, GetScreenHeight()/2 + 48, 16, WHITE); DrawText("ESC: Exit Game", 5, GetScreenHeight()/2 + 64, 16, WHITE); - // Button / UI stuff - UiContainerUpdateUiContainer(pauseScreenUiContainer, game); - UiContainerDrawUiContainer(pauseScreenUiContainer); - - // Debug Menu - DebugDraw(game, pauseScreenUiContainer); - if(IsKeyPressed(KEY_P)){ game->screen = SCREEN_GAME; } @@ -109,9 +91,15 @@ int main(){ return 1; break; } + + // Always drawing UiContainer? Can still be put into cases: + UiContainerUpdateUiContainer(game->UiContainers[game->screen], game); + UiContainerDrawUiContainer(game->UiContainers[game->screen]); + + // Dinge die grundsätzlich immer gedrawed werden sollen // Debug Menu, FPS anzeige, Cursor - DebugDraw(game, pauseScreenUiContainer); + DebugDraw(game); DrawFPS(GetScreenWidth() - 95, 10); DrawSpriteToScreen(game->cursorSprite); EndDrawing();