// // Created by bruno on 4/24/25. // #include #include "player.h" #include "../tiles/tile.h" #include "../util/font.h" #define HEALTH_MARGIN 4 int playerSpeed = 2; int playerReach = DISPLAY_MAP_HEIGHT / 2 - 2; SDL_Texture *entityTexture; SDL_Texture *hudTexture; SDL_Texture *PlayerTexture; SDL_Rect PlayerRect; SDL_Rect targetItemBGRect; SDL_Rect targetItemRect; SDL_Color healthBarColor = {0, 240, 0, 255}; SDL_Color breakingBarColor = {128, 128, 0, 255}; void setActivePlayerSlot(Player *plr, ItemType activeSlotIndex) { activeSlotIndex = activeSlotIndex % itemRegistryIndex; if (activeSlotIndex <= 0) { activeSlotIndex = 1; } plr->inventory.activeSlotIndex = activeSlotIndex; } void moveActivePlayerSlot(Player *plr, bool up, bool seek) { ItemType prevSlot = plr->inventory.activeSlotIndex; ItemType newSlot = prevSlot; do { newSlot = (newSlot + (up ? 1 : ITEMREGISTRY_SIZE - 1)) % ITEMREGISTRY_SIZE; // Stop if we've looped all the way around if (newSlot == prevSlot) break; // Stop if we found a slot with count > 0 if (!strlen(ItemRegistry[newSlot].name)) continue; if (newSlot == 0) continue; if (seek) { if (plr->inventory.slotCounts[newSlot] > 0) break; } else { break; } } while (true); plr->inventory.activeSlotIndex = newSlot; } inline void adjustRect(SDL_Rect *rect, SDL_Rect playerRect) { rect->x -= playerRect.x; rect->y -= playerRect.y; rect->x += DISPLAY_WIDTH / 2; rect->y += DISPLAY_HEIGHT / 2; } //bool isInboundsTile(int x, int y) { // return (playerX / TILE_SIZE) - (DISPLAY_MAP_WIDTH / 2) < x && // (playerY / TILE_SIZE) - (DISPLAY_MAP_HEIGHT / 2) < y && // (playerX / TILE_SIZE) + (DISPLAY_MAP_WIDTH / 2) > x && (playerX / TILE_SIZE) + (DISPLAY_MAP_WIDTH / 2) > y; //} // //bool isInbounds(int x, int y) { // return x > 0 && y > 0 && x < DISPLAY_WIDTH && y < DISPLAY_HEIGHT; //} //bool isInboundsRect(SDL_Rect rect) { // if (isInbounds(rect.x, rect.y)) { // return true; // } // if (rect.x < 0) { // rect.x += rect.w; // } // if (rect.y < 0) { // rect.y += rect.h; // } // if (isInbounds(rect.x, rect.y)) { // return true; // } // if (rect.x > DISPLAY_WIDTH) { // rect.x -= rect.w; // } // if (rect.y > DISPLAY_HEIGHT) { // rect.y -= rect.h; // } // return isInbounds(rect.x, rect.y); //} void initPlayer(Player *plr) { plr->cursor.direction = ORIENT_UP; setActivePlayerSlot(plr, 1); PlayerTexture = IMG_LoadTexture(mainRenderer, "assets/player.png"); SDL_QueryTexture(PlayerTexture, NULL, NULL, &PlayerRect.w, &PlayerRect.h); PlayerRect.x = (DISPLAY_WIDTH / 2) - (PlayerRect.w / 2); PlayerRect.y = (DISPLAY_HEIGHT / 2) - (PlayerRect.h / 2); plr->health = 64; plr->healthIdle = 0; plr->rect.x = DISPLAY_WIDTH / 2; plr->rect.y = DISPLAY_HEIGHT / 2; plr->rect.w = TILE_SIZE; plr->rect.h = TILE_SIZE; for (ItemType ui = 0; ui < tileTypeIndex; ui++) { plr->inventory.slotCounts[ui] = 64; } for (ItemType ui = ITEMREGISTRY_SIZE / 2; ui < itemRegistryIndex; ui++) { plr->inventory.slotCounts[ui] = 64; } hudTexture = SDL_CreateTexture(mainRenderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, screenRect.w, screenRect.h); entityTexture = SDL_CreateTexture(mainRenderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, screenRect.w, screenRect.h); SDL_SetTextureBlendMode(entityTexture, SDL_BLENDMODE_BLEND); SDL_SetTextureBlendMode(hudTexture, SDL_BLENDMODE_BLEND); plr->cursor.targetTileRect.w = TILE_SIZE; plr->cursor.targetTileRect.h = TILE_SIZE; plr->cursor.targetTileRect.w = TILE_SIZE; plr->cursor.targetTileRect.h = TILE_SIZE; targetItemBGRect.w = DISPLAY_WIDTH; targetItemBGRect.h = TILE_SIZE; targetItemBGRect.x = 0; targetItemBGRect.y = DISPLAY_HEIGHT - 32; targetItemRect.w = TILE_SIZE / 2; targetItemRect.h = TILE_SIZE / 2; plr->cursor.heldItemRect.w = TILE_SIZE; plr->cursor.heldItemRect.h = TILE_SIZE; } void updatePlayer(Player *plr) { if (plr->health == plr->prevHealth && plr->healthIdle < neededHealthIdle) { plr->healthIdle++; } if (plr->health < playerMaxHealth && plr->healthIdle >= neededHealthIdle) { plr->health++; } plr->prevHealth = plr->health; } void renderPlayer(Player *plr) { SDL_Texture *originalTarget = SDL_GetRenderTarget(mainRenderer); SDL_SetRenderDrawColor(mainRenderer, 0, 0, 0, 0); SDL_SetRenderTarget(mainRenderer, entityTexture); SDL_RenderClear(mainRenderer); SDL_RenderCopy(mainRenderer, PlayerTexture, NULL, &PlayerRect); SDL_SetRenderTarget(mainRenderer, hudTexture); SDL_RenderClear(mainRenderer); SDL_SetRenderDrawColor(mainRenderer, plr->cursor.canReach ? 0 : 255, plr->cursor.canReach ? 255 : 0, 0, 128); DrawThickRect(mainRenderer, plr->cursor.targetTileRect, 4); ItemType itemIndex = plr->inventory.activeSlotIndex; SDL_Texture *itemTex; char itemStringCount[6]; if (itemIndex < itemRegistryIndex) { plr->cursor.heldItemRect.x = plr->cursor.windowX; plr->cursor.heldItemRect.y = plr->cursor.windowY; itemTex = ItemRegistry[itemIndex].textureOnBelt[plr->cursor.direction]; if (itemTex == NULL) { itemTex = ItemRegistry[itemIndex].textureOnBelt[ORIENT_LEFT]; } if (itemTex != NULL) { if (plr->inventory.slotCounts[itemIndex] <= 0) { // Set a red tint (255, 0, 0) SDL_SetTextureColorMod(itemTex, 128, 128, 255); SDL_SetTextureAlphaMod(itemTex, 192); } else { SDL_SetTextureColorMod(itemTex, 255, 255, 255); SDL_SetTextureAlphaMod(itemTex, 255); } SDL_RenderCopy(mainRenderer, itemTex, NULL, &plr->cursor.heldItemRect); renderText(mainRenderer, fonts[2], ItemRegistry[itemIndex].name, plr->cursor.heldItemRect.x, plr->cursor.heldItemRect.y - (fonts[2].size * 3 / 2)); } } renderBar(mainRenderer, (DISPLAY_WIDTH / 2) - 128, DISPLAY_HEIGHT - 50, 200, 8, playerMaxHealth, plr->health, healthBarColor, 4); if (plr->cursor.targetTile) { uint16_t tempko = getBreakTime(plr->cursor.targetTile->type); uint16_t tempko2 = plr->cursor.breakingProgress; renderBar(mainRenderer, (DISPLAY_WIDTH / 2) - 128, DISPLAY_HEIGHT - 70, 200, 8, tempko, tempko2, breakingBarColor, 4); } SDL_SetRenderDrawColor(mainRenderer, 0, 0, 0, 255); SDL_RenderFillRect(mainRenderer, &targetItemBGRect); targetItemRect.y = DISPLAY_HEIGHT - 30 + TILE_SIZE / 4 + 3; targetItemRect.x = TILE_SIZE / 4; for (ItemType i = 1; i < ITEMREGISTRY_SIZE; i++) { itemTex = ItemRegistry[i].textureOnBelt[plr->cursor.direction]; if (itemTex == NULL) { itemTex = ItemRegistry[i].textureOnBelt[ORIENT_LEFT]; } if (itemTex != NULL) { if (plr->inventory.slotCounts[i] <= 0) { // Set a red tint (255, 0, 0) SDL_SetTextureColorMod(itemTex, 128, 128, 255); } SDL_RenderCopy(mainRenderer, itemTex, NULL, &targetItemRect); SDL_SetTextureColorMod(itemTex, 255, 255, 255); if (plr->inventory.activeSlotIndex == i) { SDL_SetRenderDrawColor(mainRenderer, 16, plr->inventory.slotCounts[i] > 0 ? 128 : 16, plr->inventory.slotCounts[i] > 0 ? 32 : 128, 255); DrawThickRect(mainRenderer, targetItemRect, 4); } sprintf(itemStringCount, "%d", plr->inventory.slotCounts[i]); renderText(mainRenderer, fonts[2], itemStringCount, targetItemRect.x - 3, targetItemRect.y - (fonts[2].size * 3 / 2)); //targetItemRect.x += (TILE_SIZE / 2) + (TILE_SIZE / 4); targetItemRect.x += TILE_SIZE; } } SDL_SetRenderTarget(mainRenderer, originalTarget); }