diff --git a/Input/inputHandler.c b/Input/inputHandler.c index 36b416c..550f029 100644 --- a/Input/inputHandler.c +++ b/Input/inputHandler.c @@ -11,18 +11,18 @@ #include "../definitions.h" #include "../MapObject/staticobjects.h" -void DrawRect(Vector2 rectStart, Vector2 *mousePosition){ - float width = GetMousePosition().x - rectStart.x; - float height = GetMousePosition().y - rectStart.y; +void DrawRect(Vector2 rectStart, Vector2 mousePosition){ + float width = abs(mousePosition.x - rectStart.x); + float height = abs(mousePosition.y - rectStart.y); + rectStart = GetRectangle(rectStart, mousePosition); - rectStart = GetRectangle(rectStart); - - DrawRectangleLines(rectStart.x, rectStart.y, abs(width), abs(height), GREEN); + DrawRectangleLines(rectStart.x, rectStart.y, width, height, GREEN); } -Vector2 GetRectangle(Vector2 rectStart){ - float width = GetMousePosition().x - rectStart.x; - float height = GetMousePosition().y - rectStart.y; +// RETURNS UPPER LEFT CORNER OF THE RECTANGLE USING CURRENT MOUSE POS +Vector2 GetRectangle(Vector2 rectStart, Vector2 mousePos){ + float width = mousePos.x - rectStart.x; + float height = mousePos.y - rectStart.y; if(width < 0 && height >= 0){ width *= -1; @@ -41,178 +41,150 @@ Vector2 GetRectangle(Vector2 rectStart){ return rectStart; } +static void SelectEntitiesInsideSelectionRect(Game *game){ + // UNSELECTING EVERY ENTITY FIRST, IF NOT HOLDING SHIFT + Entity *current = game->entities->head; + if(!IsKeyDown(KEY_LEFT_SHIFT)){ + while (current != 0){ + current->selected = 0; + current = current->next; + } + } + + Vector2 rect = GetRectangle(game->inputHandler->rectStart, game->inputHandler->cursorPos); + float rectWidth = abs(GetMousePosition().x - game->inputHandler->rectStart.x); + float rectHeight = abs(GetMousePosition().y - game->inputHandler->rectStart.y); + + current = game->entities->head; + float deltaX; + float deltaY; + // THEN SELECTING ENTITIES + while (current != 0){ + Vector2 currPos = {current->sprite->x + current->sprite->texture->width, current->sprite->y + current->sprite->texture->height/2}; + IsometricMapUnproject(game->map, game->camera, currPos.x, currPos.y, current->sprite->z, &currPos); + + deltaX = currPos.x - game->camera->target.x - (rect.x + game->camera->target.x); + deltaY = currPos.y - game->camera->target.y - (rect.y + game->camera->target.y); + + if(deltaX > 0 && deltaX < rectWidth && deltaY > 0 && deltaY < rectHeight){ + current->selected = 1; + } + current = current->next; + } +} + void mouseInput(Game *game){ - InputHandler *inputHandler = game->inputHandler; - EntityList *entities = game->entities; - Camera2D *camera = game->camera; - IsometricMap *map = game->map; - Texture2D *texture = game->worker +4; + /* --- UPDATING INPUT VECTOR VARIABLES --- */ - inputHandler->cursorPos.x = GetMousePosition().x; - inputHandler->cursorPos.y = GetMousePosition().y; + game->inputHandler->cursorPos.x = GetMousePosition().x; + game->inputHandler->cursorPos.y = GetMousePosition().y; + // resetting last selected Tile to grass texture + IsometricMapChangeTextureIdOfTile(game->map, (int) game->inputHandler->cursorWorldTile.x, (int) game->inputHandler->cursorWorldTile.y, 0); - // bissl Kamera Zoom - float maxZoom = 5.0f; - float minZoom = 0.2f; - if(IsKeyPressed(KEY_I)){ - if(camera->zoom < maxZoom){ - camera->zoom += 0.2f; - } - } - if(IsKeyPressed(KEY_K)){ - if(camera->zoom > minZoom){ - camera->zoom -= 0.2f; - } - } + // Updating cursorWorldPos + IsometricMapProject(game->map, game->camera, + (game->inputHandler->cursorPos.x / game->camera->zoom) - (game->map->textureWidth / 2), + (game->inputHandler->cursorPos.y / game->camera->zoom) - (game->map->textureHeight / 4), + &game->inputHandler->cursorWorldPos); - // Temp code for testing HOLZHACKERLEUTE, weil ich net versteh wie die iButtons hmmpf. früher bescheid wisse! - if(IsKeyPressed(KEY_G)){ - //Baum - StaticObject *tree = StaticObjectInit(game, SO_PINETREE, inputHandler->cursorWorldPos.x, inputHandler->cursorWorldPos.y); - StaticObjectListInsert(game->objects, tree); + // Updating cursorWorldTile + Tile *currentlySelectedTile = IsometricMapGetTileFromWorldCoordinates(game->map, game->inputHandler->cursorWorldPos.x, game->inputHandler->cursorWorldPos.y); + if(currentlySelectedTile != 0){ + game->inputHandler->cursorWorldTile.x = currentlySelectedTile->x; + game->inputHandler->cursorWorldTile.y = currentlySelectedTile->y; + // setting the currently selected Tile to "selected" Texture + IsometricMapChangeTextureIdOfTile(game->map, (int) game->inputHandler->cursorWorldTile.x, (int) game->inputHandler->cursorWorldTile.y, 1); } - if(IsKeyPressed(KEY_H)){ - //Holzkacker - Entity *lumberjack = EntityInit(game, PR_LUMBERJACK, inputHandler->cursorWorldPos.x, inputHandler->cursorWorldPos.y); - EntityListInsert(game->entities, lumberjack); - } + /* --- CURSOR SPRITE --- */ - // resetting last selected Tile to grass texture - if(inputHandler->selectedLayer != -1){ - IsometricMapChangeTextureIdOfTile(map, (int) inputHandler->cursorWorldTile.x, (int) inputHandler->cursorWorldTile.y, 0); + if(IsMouseButtonPressed(MOUSE_BUTTON_LEFT)){ + game->cursorSprite->texture = &game->textures->textures[TE_CURSOR][1]; } - - // hardcoded layer amount - float tileWidthHalf = map->tileTextures[0].width / 2; - float tileHeightQuarter = map->tileTextures[0].height / 4; - int mouseAdjustmentX = -tileWidthHalf; - int mouseAdjustmentY = -tileHeightQuarter; - - // Updating inputHandler->cursorWorldPos Vector2D - IsometricMapProject(map, camera, - (inputHandler->cursorPos.x / camera->zoom) + mouseAdjustmentX, - (inputHandler->cursorPos.y / camera->zoom) + mouseAdjustmentY, - &inputHandler->cursorWorldPos); - - Tile *selectedTile = IsometricMapGetTileFromWorldCoordinates(game->map, inputHandler->cursorWorldPos.x, inputHandler->cursorWorldPos.y); - - if(selectedTile != 0){ - inputHandler->selectedLayer = 0; - inputHandler->cursorWorldTile.x = selectedTile->x; - inputHandler->cursorWorldTile.y = selectedTile->y; - // setting currently selected tile to tower - IsometricMapChangeTextureIdOfTile(map, inputHandler->cursorWorldTile.x, inputHandler->cursorWorldTile.y, 1); + else if(IsMouseButtonReleased(MOUSE_BUTTON_LEFT)){ + game->cursorSprite->texture = &game->textures->textures[TE_CURSOR][0]; } - if(game->mouseOnUI == 0){ - if(IsMouseButtonPressed(MOUSE_BUTTON_LEFT)){ - if(inputHandler->pressed == 0){ - inputHandler->rectStart.x = GetMousePosition().x; - inputHandler->rectStart.y = GetMousePosition().y; - inputHandler->pressed = 1; + /* --- SELECTION RECT --- */ - // Cursorsprite is changed to "down" - game->cursorSprite->texture = &game->textures->textures[TE_CURSOR][1]; + // Creating new Selection Rect + if(IsMouseButtonPressed(MOUSE_BUTTON_LEFT)){ + if(game->mouseOnUI == 0){ + if(game->inputHandler->selectionRectActive == 0){ + game->inputHandler->rectStart.x = GetMousePosition().x; + game->inputHandler->rectStart.y = GetMousePosition().y; + game->inputHandler->selectionRectActive = 1; } } } + // Drawing Rect while selectionRectActive + if(game->inputHandler->selectionRectActive == 1){ + DrawRect(game->inputHandler->rectStart, game->inputHandler->cursorPos); + } + if(IsMouseButtonReleased(MOUSE_BUTTON_LEFT)){ + game->inputHandler->selectionRectActive = 0; + SelectEntitiesInsideSelectionRect(game); + } - if(inputHandler->pressed){ - DrawRect(inputHandler->rectStart, &(inputHandler->cursorPos)); - } - - if(game->mouseOnUI == 0){ - if(IsMouseButtonReleased(MOUSE_BUTTON_LEFT)){ - inputHandler->pressed = 0; - // Cursorsprite is changed back to normal - game->cursorSprite->texture = &game->textures->textures[TE_CURSOR][0]; - float width = GetMousePosition().x - inputHandler->rectStart.x; - float height = GetMousePosition().y - inputHandler->rectStart.y; - - - // Add Sprite - if(abs(width) + abs(height) < 20){ - int maxWidth = (game->map->width) * game->map->textureWidth; - int maxHeight = (game->map->height) * game->map->textureHeight; - if(inputHandler->cursorWorldPos.x < 0){ printf("OutOfBoundsDestination Spawn\n");} - else if(inputHandler->cursorWorldPos.y < 0){ printf("OutOfBoundsDestination Spawn\n");} - else if(inputHandler->cursorWorldPos.x > maxWidth){ printf("OutOfBoundsDestination Spawn\n");} - else if(inputHandler->cursorWorldPos.y > maxHeight){ printf("OutOfBoundsDestination Spawn\n");} - else { - //Sprite *newSprite = SpriteCreate(game->textures, TE_WORKER, inputHandler->cursorWorldPos.x, inputHandler->cursorWorldPos.y); - //Entity *entity = EntityInit(newSprite, PR_BUILDER, game->textures); - //EntityListInsert(game->entities, entity); - //SpriteListInsert(game->sprites, newSprite); - //ListPrintForward(sprites); - //ListInsertSorted(sprites, SpriteCreate(game->textures, 1, inputHandler->cursorWorldPos.x, inputHandler->cursorWorldPos.y)); - } - } else{ - // Berechnung, welche Sprites ausgewählt wurden - Vector2 rect = GetRectangle(inputHandler->rectStart); - width = abs(width); - height = abs(height); - - float deltaX; - float deltaY; - Entity *current = game->entities->head; - while (current != 0){ - Vector2 currPos = {current->sprite->x + current->sprite->texture->width, current->sprite->y + current->sprite->texture->height/2}; - IsometricMapUnproject(map, camera, currPos.x, currPos.y, current->sprite->z, &currPos); - - deltaX = currPos.x - camera->target.x - (rect.x + camera->target.x); - deltaY = currPos.y - camera->target.y - (rect.y + camera->target.y); - - if(deltaX > 0 && deltaX < width && deltaY > 0 && deltaY < height){ - current->selected = 1; - } - else{ - current->selected = 0; - } - current = current->next; - } - } - } + /* --- SETTING DESTINATION FOR SELECTED ENTITIES --- */ - if(IsMouseButtonPressed(MOUSE_BUTTON_RIGHT)){ + if(IsMouseButtonPressed(MOUSE_BUTTON_RIGHT)){ + float destX = game->inputHandler->cursorWorldPos.x; + float destY = game->inputHandler->cursorWorldPos.y; + int maxWidth = (game->map->width) * game->map->textureWidth; + int maxHeight = (game->map->height) * game->map->textureHeight; + if(destX < 0 || destY < 0 || destX > maxWidth || destY > maxHeight){ + printf("OutOfBoundsDestination\n"); + } + else{ Entity *current = game->entities->head; - while (current != 0){ if(current->selected){ current->hasDestination = 1; - float destX = inputHandler->cursorWorldPos.x; - float destY = inputHandler->cursorWorldPos.y; - int maxWidth = (game->map->width-1) * game->map->textureWidth; - int maxHeight = (game->map->height-1) * game->map->textureHeight; - if(destX < 0){ printf("OutOfBoundsDestination\n"); goto skip; } - if(destY < 0){ printf("OutOfBoundsDestination\n"); goto skip; } - if(destX > maxWidth){ printf("OutOfBoundsDestination\n"); goto skip; } - if(destY > maxHeight){ printf("OutOfBoundsDestination\n"); goto skip; } - current->destX = destX; current->destY = destY; } - -skip: current = current->next; + current = current->next; } } } } -void keyboardInput(InputHandler *inputHandler, Camera2D *camera){ +void keyboardInput(Game *game){ + // Kamera Movement float camSpeed = 1000.0f; if(IsKeyDown(KEY_W)){ - (*camera).target.y -= camSpeed * GetFrameTime(); + game->camera->target.y -= camSpeed * GetFrameTime(); } if(IsKeyDown(KEY_S)){ - (*camera).target.y += camSpeed * GetFrameTime(); + game->camera->target.y += camSpeed * GetFrameTime(); } if(IsKeyDown(KEY_D)){ - (*camera).target.x += camSpeed * GetFrameTime(); + game->camera->target.x += camSpeed * GetFrameTime(); } if(IsKeyDown(KEY_A)){ - (*camera).target.x -= camSpeed * GetFrameTime(); + game->camera->target.x -= camSpeed * GetFrameTime(); + } + + // bissl Kamera Zoom + float maxZoom = 5.0f; + float minZoom = 0.2f; + if(IsKeyPressed(KEY_I)){ + if(game->camera->zoom < maxZoom){ + game->camera->zoom += 0.2f; + } + } + if(IsKeyPressed(KEY_K)){ + if(game->camera->zoom > minZoom){ + game->camera->zoom -= 0.2f; + } + } + // Temp code for testing HOLZHACKERLEUTE, weil ich net versteh wie die iButtons hmmpf. früher bescheid wisse! + if(IsKeyPressed(KEY_G)){ + //Baum + StaticObject *tree = StaticObjectInit(game, SO_PINETREE, game->inputHandler->cursorWorldPos.x, game->inputHandler->cursorWorldPos.y); + StaticObjectListInsert(game->objects, tree); } } diff --git a/Input/inputHandler.h b/Input/inputHandler.h index b718cb8..6fe2405 100644 --- a/Input/inputHandler.h +++ b/Input/inputHandler.h @@ -6,20 +6,19 @@ #include "../game.h" typedef struct InputHandler{ - int pressed; - Vector2 rectStart; - Vector2 cursorPos; - Vector2 cursorWorldPos; - Vector2 cursorWorldTile; - int selectedLayer; + Vector2 rectStart; // hmm + Vector2 cursorPos; // position of cursor on Screen + Vector2 cursorWorldPos; // position of cursor in World + Vector2 cursorWorldTile; // Selected Tile + int selectionRectActive; //0: not active | 1: active } InputHandler; void mouseInput(Game *game); -void keyboardInput(InputHandler *inputHandler, Camera2D *camera); +void keyboardInput(Game *game); -void DrawRect(Vector2 rectStart, Vector2 *mousePosition); +void DrawRect(Vector2 rectStart, Vector2 mousePosition); -Vector2 GetRectangle(Vector2 rectStart); +Vector2 GetRectangle(Vector2 rectStart, Vector2 mousePos); #endif diff --git a/Ui/debug.c b/Ui/debug.c index ec7b602..8b59d7f 100644 --- a/Ui/debug.c +++ b/Ui/debug.c @@ -20,8 +20,7 @@ void DebugDraw(Game *game){ 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++], "DEPTH: %d", (int)(game->inputHandler->cursorWorldPos.x + game->inputHandler->cursorWorldPos.y)); sprintf(strings[lineamount++], "Camera Zoom: %f", game->camera->zoom); sprintf(strings[lineamount++], "Sprite Amount: %d", game->sprites->spriteAmount); diff --git a/Ui/onClickFunctions.c b/Ui/onClickFunctions.c index d1d1412..1d95ba6 100644 --- a/Ui/onClickFunctions.c +++ b/Ui/onClickFunctions.c @@ -23,7 +23,16 @@ void OnClickStartButton(Game *game, Button *button){ game->screen = SCREEN_GAME; } - +// RETURNS 1 IF COORDS INSIDE MAP +static int InsideMapBounds(Vector2 coords, IsometricMap *map){ + int maxWidth = map->width * map->textureWidth; + int maxHeight = map->height * map->textureHeight; + if(coords.x < 0 || coords.y < 0 || coords.x > maxWidth || coords.y > maxHeight){ + printf("OutOfBoundsDestination Spawn\n"); + return 0; + } + return 1; +} // 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 @@ -34,6 +43,12 @@ void OnSelectedSelectable(Game *game, Selectable *selectable){ } void OnSelectedSpawnBuilding(Game *game, Selectable *selectable){ if(IsMouseButtonDown(MOUSE_BUTTON_LEFT) && game->mouseOnUI == 0){ + + // Can only be spawned inside map bounds + if(InsideMapBounds(game->inputHandler->cursorWorldPos, game->map) == 0){ + return; + } + Building *newObject = BuildingInit(game, BU_HOUSE, game->inputHandler->cursorWorldPos.x, game->inputHandler->cursorWorldPos.y); BuildingListInsert(game->buildings, newObject); @@ -42,7 +57,23 @@ void OnSelectedSpawnBuilding(Game *game, Selectable *selectable){ } void OnSelectedSpawnWorker(Game *game, Selectable *selectable){ if(IsMouseButtonDown(MOUSE_BUTTON_LEFT) && game->mouseOnUI == 0){ - Entity *lumberjack = EntityInit(game, PR_BUILDER, game->inputHandler->cursorWorldPos.x, game->inputHandler->cursorWorldPos.y); + if(InsideMapBounds(game->inputHandler->cursorWorldPos, game->map) == 0){ + return; + } + + Entity *builder = EntityInit(game, PR_BUILDER, game->inputHandler->cursorWorldPos.x, game->inputHandler->cursorWorldPos.y); + EntityListInsert(game->entities, builder); + + selectable->state = SELECTABLE_STATE_DEFAULT; + } +} +void OnSelectedSpawnLumberjack(Game *game, Selectable *selectable){ + if(IsMouseButtonDown(MOUSE_BUTTON_LEFT) && game->mouseOnUI == 0){ + if(InsideMapBounds(game->inputHandler->cursorWorldPos, game->map) == 0){ + return; + } + + Entity *lumberjack = EntityInit(game, PR_LUMBERJACK, game->inputHandler->cursorWorldPos.x, game->inputHandler->cursorWorldPos.y); EntityListInsert(game->entities, lumberjack); selectable->state = SELECTABLE_STATE_DEFAULT; diff --git a/Ui/onClickFunctions.h b/Ui/onClickFunctions.h index 489600b..3b34320 100644 --- a/Ui/onClickFunctions.h +++ b/Ui/onClickFunctions.h @@ -12,5 +12,6 @@ void OnClickStartButton(Game *game, Button *button); void OnSelectedSelectable(Game *game, Selectable *selectable); void OnSelectedSpawnBuilding(Game *game, Selectable *selectable); void OnSelectedSpawnWorker(Game *game, Selectable *selectable); +void OnSelectedSpawnLumberjack(Game *game, Selectable *selectable); #endif \ No newline at end of file diff --git a/Ui/selectable.c b/Ui/selectable.c index d565088..9161ac0 100644 --- a/Ui/selectable.c +++ b/Ui/selectable.c @@ -43,6 +43,9 @@ Selectable * SelectableInit(Texture2D textures[3], Texture2D backgroundTextures[ case SELECTABLE_ID_SPAWN_WORKER: selectable->onSelected = &OnSelectedSpawnWorker; break; + case SELECTABLE_ID_SPAWN_LUMBERJACK: + selectable->onSelected = &OnSelectedSpawnLumberjack; + 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); diff --git a/Ui/uiContainer.c b/Ui/uiContainer.c index 24ba65b..705c2a2 100644 --- a/Ui/uiContainer.c +++ b/Ui/uiContainer.c @@ -98,14 +98,20 @@ static UiContainer * UiContainerInitGameUiContainer(){ Selectable *selectable1 = SelectableInit(textures, backgroundTextures, hasBackground , &position, "Building", showDescription, 9, fontSize, SELECTABLE_ID_SPAWN_BUILDING, groupOne); position.y += 100; + Selectable *selectable2 = SelectableInit(textures2, backgroundTextures, hasBackground,&position, "Worker", - showDescription, 10, fontSize, SELECTABLE_ID_SPAWN_WORKER, groupOne); + showDescription, 7, fontSize, SELECTABLE_ID_SPAWN_WORKER, groupOne); + position.y += 100; + + Selectable *selectable3 = SelectableInit(textures2, backgroundTextures, hasBackground,&position, "Lumberjack", + showDescription, 11, fontSize, SELECTABLE_ID_SPAWN_LUMBERJACK, groupOne); position.y += 100; int selectableCounter = 0; uiContainer->selectables[selectableCounter++] = selectable1; uiContainer->selectables[selectableCounter++] = selectable2; + uiContainer->selectables[selectableCounter++] = selectable3; uiContainer->selectableCounter = selectableCounter; diff --git a/definitions.h b/definitions.h index 9165b78..8f38632 100644 --- a/definitions.h +++ b/definitions.h @@ -71,6 +71,7 @@ #define SELECTABLE_ID_SPAWN_BUILDING 0 #define SELECTABLE_ID_SPAWN_WORKER 1 +#define SELECTABLE_ID_SPAWN_LUMBERJACK 2 diff --git a/game.c b/game.c index 5424167..ccb040a 100644 --- a/game.c +++ b/game.c @@ -20,7 +20,6 @@ Game *GameInit() game->cursorSprite = SpriteCreate(game->textures, TE_CURSOR, 450, 225); game->inputHandler = malloc(sizeof(InputHandler)); - game->inputHandler->pressed = 0; game->inputHandler->rectStart.x = 0; game->inputHandler->rectStart.y = 0; game->inputHandler->cursorPos.x = 0; @@ -29,7 +28,6 @@ Game *GameInit() game->inputHandler->cursorWorldPos.y = 0; game->inputHandler->cursorWorldTile.x = 0; game->inputHandler->cursorWorldTile.y = 0; - game->inputHandler->selectedLayer = -1; game->screen = SCREEN_MAINMENU; game->mouseOnUI = 0; diff --git a/main.c b/main.c index 2bf30b6..aa20644 100644 --- a/main.c +++ b/main.c @@ -54,7 +54,9 @@ int main(){ return 0; case SCREEN_GAME: // Updating Entities + EntityListActAllEntities(game); + // Drawing IsometricMap BeginMode2D(*(game->camera)); // Sorgt dafür, dass die Kameraposition beachtet wird @@ -65,7 +67,7 @@ int main(){ // User Input Handling mouseInput(game); - keyboardInput(game->inputHandler, game->camera); + keyboardInput(game); if(IsKeyPressed(KEY_P)){ @@ -78,8 +80,9 @@ int main(){ // Still drawing isometric map, which is not updated atm BeginMode2D(*(game->camera)); // Sorgt dafür, dass die Kameraposition beachtet wird IsometricMapDraw(game); + SpriteListDrawAllSprites(game->sprites, game->map, game->camera); EndMode2D(); - + UiContainerDrawUiContainer(game->UiContainers[SCREEN_GAME]); // darkened background + "Paused" Text DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), (Color){0, 0, 0, 150}); int textWidthHalf = MeasureText("Paused", 28) / 2;