diff --git a/Makefile b/Makefile index e8ffd86..92a35a9 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ CC = gcc FLAGS = -lraylib -lGL -lm -lpthread -ldl -lrt -lX11 -OBJS = main.o sprite.o inputHandler.o isometricMap.o game.o textureatlas.o animation.o animationHandler.o button.o uiContainer.o debug.o building.o entity.o selectable.o task.o entityacts.o +OBJS = main.o sprite.o inputHandler.o isometricMap.o game.o textureatlas.o animation.o animationHandler.o button.o uiContainer.o debug.o building.o entity.o selectable.o task.o entityacts.o onClickFunctions.o spiel: $(OBJS) $(CC) -o spiel $(OBJS) $(FLAGS) @@ -53,5 +53,8 @@ task.o: Entity/task.c entityacts.o: Entity/entityacts.c $(CC) -c Entity/entityacts.c $(FLAGS) +onClickFunctions.o: Ui/onClickFunctions.c + $(CC) -c Ui/onClickFunctions.c $(FLAGS) + clean: rm *.o spiel diff --git a/Ui/button.c b/Ui/button.c index 222dea5..4319924 100644 --- a/Ui/button.c +++ b/Ui/button.c @@ -4,6 +4,7 @@ #include "stdlib.h" #include "raylib.h" #include "string.h" +#include "onClickFunctions.h" Button * ButtonInitButton(Texture2D textures[4], Vector2 *position, char *text, int textLEN, int fontSize, int id){ Button *button = malloc(sizeof(Button)); @@ -22,25 +23,28 @@ Button * ButtonInitButton(Texture2D textures[4], Vector2 *position, char *text, button->fontSize = fontSize; - return button; -} - -void ButtonExecuteButton(Button *button, Game *game){ - button->state = BUTTON_STATE_DEFAULT; switch(button->id){ - case BUTTON_ID_CONTINUE: // continue game - game->screen = SCREEN_GAME; + case BUTTON_ID_CONTINUE: + button->onClick = &OnClickContinueButton; break; case BUTTON_ID_EXIT: - game->screen = SCREEN_EXIT; + button->onClick = &OnClickExitButton; break; case BUTTON_ID_START_GAME: - game->screen = SCREEN_GAME; + button->onClick = &OnClickStartButton; break; default: printf("\n\n\n\n\n\n Unsupported Button ID %d \n\n\n\n\n\n", button->id); + button->onClick = &OnClickButton; break; } + + return button; +} + +void ButtonExecuteButton(Button *button, Game *game){ + button->state = BUTTON_STATE_DEFAULT; + button->onClick(game, button); } void ButtonDrawButton(Button * button){ @@ -49,7 +53,7 @@ void ButtonDrawButton(Button * button){ DrawText(button->text, button->centerPosition.x - MeasureText(button->text, button->fontSize)/2, button->centerPosition.y - button->fontSize/2, button->fontSize, BLACK); } -int ButtonUpdateButtonState(Button * button){ +int ButtonUpdateButtonState(Button * button, Game *game){ if(button->state == BUTTON_STATE_RELEASED){ // Wir verlassen den RELEASED State automatisch wenn wir den Code des Buttons ausführen, siehe ButtonExecuteButton // So lange der Code nicht ausgeführt wurde bleiben wir im state damit er definitiv im nächsten Frame ausgeführt wird @@ -60,6 +64,7 @@ int ButtonUpdateButtonState(Button * button){ GetMouseY() > button->position.y && GetMouseY() < button->position.y + button->textures[button->state].height ){ + game->mouseOnUI = 1; if(IsMouseButtonDown(MOUSE_BUTTON_LEFT)){ return button->state = BUTTON_STATE_PRESSED; } diff --git a/Ui/button.h b/Ui/button.h index 1cff561..8e2b289 100644 --- a/Ui/button.h +++ b/Ui/button.h @@ -4,6 +4,8 @@ #include "raylib.h" #include "../game.h" +typedef struct Button Button; + typedef struct Button{ Texture2D textures[4]; // [0]: Normal [1]: Hovered [2]: Pressed [3]: Released Vector2 position; // Linke obere Ecke des Buttons @@ -12,6 +14,8 @@ typedef struct Button{ int state; // 0: default 1: hovered 2: pressed 3: released int id; // Durch die ID wird dem Button eine Funktion zugeordnet int fontSize; // FontSize kann für jeden Button individuell festgelegt werden + + void (*onClick)(Game *game, Button *button); } Button; // Textures: [0]: Normal [1]: Hovered [2]: Pressed [3]: Released @@ -20,7 +24,7 @@ Button * ButtonInitButton(Texture2D textures[4], Vector2 *position, char *text, // executes the logic of one button of certain id - huge switch? void ButtonExecuteButton(Button *button, Game * game); -int ButtonUpdateButtonState(Button * button); +int ButtonUpdateButtonState(Button * button, Game *game); void ButtonDrawButton(Button * button); diff --git a/Ui/onClickFunctions.c b/Ui/onClickFunctions.c new file mode 100644 index 0000000..ee63090 --- /dev/null +++ b/Ui/onClickFunctions.c @@ -0,0 +1,52 @@ +#include "../game.h" +#include "selectable.h" +#include "button.h" +#include "../definitions.h" +#include "raylib.h" +#include "stdio.h" +#include "../MapObject/building.h" +#include "../Sprite/sprite.h" +#include "../Entity/entity.h" +#include "../Input/inputHandler.h" + +void OnClickButton(Game *game, Button *button){ + printf("\n\n\n\n\n\n Unsupported Button ID %d \n\n\n\n\n\n", button->id); + return; +} +void OnClickContinueButton(Game *game, Button *button){ + game->screen = SCREEN_GAME; +} +void OnClickExitButton(Game *game, Button *button){ + game->screen = SCREEN_EXIT; +} +void OnClickStartButton(Game *game, Button *button){ + game->screen = SCREEN_GAME; +} + + + +// 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 +void OnSelectedSelectable(Game *game, Selectable *selectable){ + printf("\n\n\n\n\n\n WARNING: Unsupported SELECTABLE ID %d \n\n\n\n\n\n", selectable->id); + return; +} +void OnSelectedSpawnBuilding(Game *game, Selectable *selectable){ + if(IsMouseButtonDown(MOUSE_BUTTON_LEFT) && game->mouseOnUI == 0){ + Building *newObject = BuildingInit(game, BU_HOUSE, game->inputHandler->cursorWorldPos.x, game->inputHandler->cursorWorldPos.y); + BuildingListInsert(game->buildings, newObject); + + selectable->state = SELECTABLE_STATE_DEFAULT; + } +} +void OnSelectedSpawnWorker(Game *game, Selectable *selectable){ + if(IsMouseButtonDown(MOUSE_BUTTON_LEFT) && game->mouseOnUI == 0){ + Sprite *newSprite = SpriteCreate(game->textures, TE_WORKER, game->inputHandler->cursorWorldPos.x, game->inputHandler->cursorWorldPos.y); + Entity *entity = EntityInit(newSprite, PR_BUILDER, game->textures); + EntityListInsert(game->entities, entity); + SpriteListInsert(game->sprites, newSprite); + + selectable->state = SELECTABLE_STATE_DEFAULT; + } +} \ No newline at end of file diff --git a/Ui/onClickFunctions.h b/Ui/onClickFunctions.h new file mode 100644 index 0000000..489600b --- /dev/null +++ b/Ui/onClickFunctions.h @@ -0,0 +1,16 @@ +#ifndef ONCLICK_H_ +#define ONCLICK_H_ + +#include "../game.h" +#include "button.h" +#include "selectable.h" + +void OnClickButton(Game *game, Button *button); +void OnClickContinueButton(Game *game, Button *button); +void OnClickExitButton(Game *game, Button *button); +void OnClickStartButton(Game *game, Button *button); +void OnSelectedSelectable(Game *game, Selectable *selectable); +void OnSelectedSpawnBuilding(Game *game, Selectable *selectable); +void OnSelectedSpawnWorker(Game *game, Selectable *selectable); + +#endif \ No newline at end of file diff --git a/Ui/selectable.c b/Ui/selectable.c index 031fc39..d565088 100644 --- a/Ui/selectable.c +++ b/Ui/selectable.c @@ -7,6 +7,7 @@ #include "../Sprite/sprite.h" #include "../Input/inputHandler.h" #include "../Entity/entity.h" +#include "onClickFunctions.h" Selectable * SelectableInit(Texture2D textures[3], Texture2D backgroundTextures[3], int hasBackground, Vector2 *position, char *description, int showDescripton, int descriptionLEN, int fontSize, int id, int groupID){ @@ -35,53 +36,44 @@ Selectable * SelectableInit(Texture2D textures[3], Texture2D backgroundTextures[ selectable->state = 0; selectable->groupID = groupID; - return selectable; -} - -void SelectableExecuteSelectable(Selectable *selectable, Game * game){ - // 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 switch(selectable->id){ - case SELECTABLE_ID_SPAWN_BUILDING: // Test Case Platzhalter - // 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 - if(IsMouseButtonDown(MOUSE_BUTTON_LEFT) && game->mouseOnUI == 0){ - Building *newObject = BuildingInit(game, BU_HOUSE, game->inputHandler->cursorWorldPos.x, game->inputHandler->cursorWorldPos.y); - BuildingListInsert(game->buildings, newObject); - - selectable->state = SELECTABLE_STATE_DEFAULT; - } + case SELECTABLE_ID_SPAWN_BUILDING: + selectable->onSelected = &OnSelectedSpawnBuilding; break; case SELECTABLE_ID_SPAWN_WORKER: - if(IsMouseButtonDown(MOUSE_BUTTON_LEFT) && game->mouseOnUI == 0){ - Sprite *newSprite = SpriteCreate(game->textures, TE_WORKER, game->inputHandler->cursorWorldPos.x, game->inputHandler->cursorWorldPos.y); - Entity *entity = EntityInit(newSprite, PR_BUILDER, game->textures); - EntityListInsert(game->entities, entity); - SpriteListInsert(game->sprites, newSprite); - - selectable->state = SELECTABLE_STATE_DEFAULT; - } - break; + selectable->onSelected = &OnSelectedSpawnWorker; + break; default: + selectable->onSelected = &OnSelectedSelectable; printf("\n\n\n\n\n\n WARNING: Unsupported SELECTABLE ID %d \n\n\n\n\n\n", selectable->id); break; } + + return selectable; +} + +void SelectableExecuteSelectable(Selectable *selectable, Game * game){ + // CALL SELECTABLE ONCLICK + selectable->onSelected(game, selectable); } -int SelectableUpdateSelectableState(Selectable * selectable){ +int SelectableUpdateSelectableState(Selectable * selectable, Game *game){ + int mouseOnElement = 0; + if(GetMouseX() > selectable->position.x && + GetMouseX() < selectable->position.x + selectable->backgroundTexture[selectable->state].width && + GetMouseY() > selectable->position.y && + GetMouseY() < selectable->position.y + selectable->backgroundTexture[selectable->state].height + ){ + mouseOnElement = 1; + game->mouseOnUI = 1; + } if(selectable->state == SELECTABLE_STATE_SELECTED){ if(IsMouseButtonDown(MOUSE_BUTTON_RIGHT)){ return selectable->state = SELECTABLE_STATE_DEFAULT; } return SELECTABLE_STATE_SELECTED; } - if(GetMouseX() > selectable->position.x && - GetMouseX() < selectable->position.x + selectable->backgroundTexture[selectable->state].width && - GetMouseY() > selectable->position.y && - GetMouseY() < selectable->position.y + selectable->backgroundTexture[selectable->state].height - ){ + if(mouseOnElement == 1){ if(IsMouseButtonDown(MOUSE_BUTTON_LEFT)){ return selectable->state = SELECTABLE_STATE_SELECTED; } diff --git a/Ui/selectable.h b/Ui/selectable.h index 870cf2a..a9b786e 100644 --- a/Ui/selectable.h +++ b/Ui/selectable.h @@ -4,7 +4,7 @@ #include "raylib.h" #include "../game.h" - +typedef struct Selectable Selectable; typedef struct Selectable{ Vector2 position; // Linke obere Ecke Vector2 centerPosition; // Die Mitte des Selectables @@ -19,6 +19,7 @@ typedef struct Selectable{ // Notiz: Die Selectables können auch in einem 2-Dimensionalen Array im UiContainer gespeichert werden, worüber die Groups auch definiert werden könnten int groupID; // Selectables können gruppiert werden, man kann also mehrere Dinge gleichzeitig selected haben + void (*onSelected)(Game *game, Selectable *selectable); }Selectable; // Textures+backgroundTextures: [0]: Normal | [1]: Hovered | [2]: Selected @@ -29,7 +30,7 @@ Selectable * SelectableInit(Texture2D textures[3], Texture2D backgroundTextures[ void SelectableExecuteSelectable(Selectable *selectable, Game * game); -int SelectableUpdateSelectableState(Selectable * selectable); +int SelectableUpdateSelectableState(Selectable * selectable, Game *game); int SelectableUnselectSelectable(Selectable * selectable); diff --git a/Ui/uiContainer.c b/Ui/uiContainer.c index 8458999..24ba65b 100644 --- a/Ui/uiContainer.c +++ b/Ui/uiContainer.c @@ -130,25 +130,14 @@ UiContainer * UiContainerInitUiContainerForScreenID(int id){ static void UpdateButtons(Game *game, Button **buttons, int buttonCounter){ int i = 0; for(i=0 ; i < buttonCounter; i++){ - int state = ButtonUpdateButtonState(buttons[i]); - if(state == BUTTON_STATE_HOVERED || state == BUTTON_STATE_PRESSED){ - game->mouseOnUI = 1; - } - if(buttons[i]->state == BUTTON_STATE_RELEASED){ - ButtonExecuteButton(buttons[i], game); - } + int state = ButtonUpdateButtonState(buttons[i], game); } } - // 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 oldState = selectables[i]->state; - int setState = SelectableUpdateSelectableState(selectables[i]); - if(setState == SELECTABLE_STATE_HOVERED || (setState == SELECTABLE_STATE_SELECTED && oldState != SELECTABLE_STATE_SELECTED)){ - game->mouseOnUI = 1; - } + int setState = SelectableUpdateSelectableState(selectables[i], game); // Unselecting every selectable if one is selected if(setState == SELECTABLE_STATE_SELECTED){ int j; @@ -158,6 +147,20 @@ static void UpdateSelectables(Game *game, Selectable **selectables, int selectab } } } + } +} + +static void ExecuteButtons(Game *game, Button **buttons, int buttonCounter){ + int i = 0; + for(i=0 ; i < buttonCounter; i++){ + if(buttons[i]->state == BUTTON_STATE_RELEASED){ + ButtonExecuteButton(buttons[i], game); + } + } +} +static void ExecuteSelectables(Game *game, Selectable **selectables, int selectableCounter){ + int i = 0; + for(i=0 ; i < selectableCounter; i++){ if(selectables[i]->state == SELECTABLE_STATE_SELECTED){ SelectableExecuteSelectable(selectables[i], game); } @@ -168,6 +171,8 @@ static void UpdateSelectables(Game *game, Selectable **selectables, int selectab void UiContainerUpdateUiContainer(UiContainer *uiContainer, Game *game){ UpdateButtons(game, uiContainer->buttons, uiContainer->buttonCounter); UpdateSelectables(game, uiContainer->selectables, uiContainer->selectableCounter); + ExecuteButtons(game, uiContainer->buttons, uiContainer->buttonCounter); + ExecuteSelectables(game, uiContainer->selectables, uiContainer->selectableCounter); } // Drawed alle Buttons und Selectables diff --git a/main.c b/main.c index 6425883..198908a 100644 --- a/main.c +++ b/main.c @@ -32,19 +32,9 @@ int main(){ while(!WindowShouldClose()){ // Drawen wir einfach immer den UI Container vom aktuellen Screen? Aktuell hat ja jeder Screen einen, es sollte also keine Probleme geben // Kann man natürlich auch noch oben in die einzelnen Cases schieben falls es mal Probleme machen sollte + game->mouseOnUI = 0; UiContainerUpdateUiContainer(game->UiContainers[game->screen], game); - if(game->mouseOnUI == 1 && frame == 0){ - frame = 1; - } - if(frame > 0){ - frame += GetFrameTime(); - } - if(frame >= 1.25){ - game->mouseOnUI = 0; - frame = 0; - } - // Moving cursor Sprite to Mouse Pos game->cursorSprite->x = GetMousePosition().x; game->cursorSprite->y = GetMousePosition().y;