Files
factorygame/player/player.c
2025-06-10 21:59:51 +02:00

300 lines
13 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//
// Created by bruno on 4/24/25.
//
#include <SDL2/SDL_rect.h>
#include "player.h"
#include "../tiles/tile.h"
#include "../util/font.h"
#include "../util/atlas.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 playerTextureRect;
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 < tileTypeIndex ||
(activeSlotIndex < itemRegistryIndex && activeSlotIndex >= ITEMREGISTRY_SIZE / 2)) && activeSlotIndex > 0) {
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) break;
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 tileRect) {
// if (isInbounds(tileRect.x, tileRect.y)) {
// return true;
// }
// if (tileRect.x < 0) {
// tileRect.x += tileRect.w;
// }
// if (tileRect.y < 0) {
// tileRect.y += tileRect.h;
// }
// if (isInbounds(tileRect.x, tileRect.y)) {
// return true;
// }
// if (tileRect.x > DISPLAY_WIDTH) {
// tileRect.x -= tileRect.w;
// }
// if (tileRect.y > DISPLAY_HEIGHT) {
// tileRect.y -= tileRect.h;
// }
// return isInbounds(tileRect.x, tileRect.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);
playerTextureRect = allocate_32x32(PlayerTexture, mainRenderer);
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 = 1; ui < tileTypeIndex; ui++) {
plr->inventory.slotCounts[ui] = 32;
}
for (ItemType ui = ITEMREGISTRY_SIZE / 2; ui < itemRegistryIndex; ui++) {
plr->inventory.slotCounts[ui] = 0;
}
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 + fonts[2].size * 2;
targetItemBGRect.x = 0;
targetItemBGRect.y = DISPLAY_HEIGHT - TILE_SIZE - fonts[2].size * 2;
targetItemRect.w = TILE_SIZE;
targetItemRect.h = TILE_SIZE;
plr->cursor.heldItemRect.w = TILE_SIZE;
plr->cursor.heldItemRect.h = TILE_SIZE;
}
void updatePlayer(Player *plr) {
if (plr->health == plr->prevHealth) {
if (plr->healthIdle < neededHealthIdle)
plr->healthIdle++;
} else {
plr->healthIdle = 0; // Reset if health changed (e.g., took damage or regen happened)
}
if (plr->health < playerMaxHealth && plr->healthIdle >= neededHealthIdle) {
plr->health++;
// Dont reset healthIdle here — only reset if something changes externally
}
plr->prevHealth = plr->health;
if (plr->health <= 0) {
plr->rect.x = DISPLAY_WIDTH / 2;
plr->rect.y = DISPLAY_HEIGHT / 2;
}
}
void renderPlayer(Player *plr) {
SDL_Texture *originalTarget = SDL_GetRenderTarget(mainRenderer);
SDL_SetRenderDrawColor(mainRenderer, 0, 0, 0, 0);
SDL_SetRenderTarget(mainRenderer, entityTexture);
SDL_RenderCopy(mainRenderer, atlasTexture, &playerTextureRect, &PlayerRect);
//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 < tileTypeIndex || (itemIndex < itemRegistryIndex && itemIndex >= ITEMREGISTRY_SIZE / 2)) &&
itemIndex > 0) {
plr->cursor.heldItemRect.x = plr->cursor.windowX;
plr->cursor.heldItemRect.y = plr->cursor.windowY;
//itemTex = ItemRegistry[itemIndex].textureOnBelt[plr->cursor.direction];
SDL_Rect itemAtlasRect = ItemRegistry[itemIndex].animation.atlasRects[plr->cursor.direction][(
(animationStep /
ItemRegistry[itemIndex].beltAnimation.divisor) %
(
ItemRegistry[itemIndex].beltAnimation.frameCount -
ItemRegistry[itemIndex].beltAnimation.startFrame)) +
ItemRegistry[itemIndex].beltAnimation.startFrame];
if (itemAtlasRect.w == 0 || itemAtlasRect.h == 0) {
itemAtlasRect = ItemRegistry[itemIndex].animation.atlasRects[ORIENT_LEFT][(
(animationStep /
ItemRegistry[itemIndex].beltAnimation.divisor) %
(
ItemRegistry[itemIndex].beltAnimation.frameCount -
ItemRegistry[itemIndex].beltAnimation.startFrame)) +
ItemRegistry[itemIndex].beltAnimation.startFrame];
}
if (itemAtlasRect.w != 0 && itemAtlasRect.h != 0) {
if (plr->inventory.slotCounts[itemIndex] <= 0) {
// Set a red tint (255, 0, 0)
SDL_SetTextureColorMod(atlasTexture, 128, 128, 255);
SDL_SetTextureAlphaMod(atlasTexture, 230);
} else {
SDL_SetTextureColorMod(atlasTexture, 255, 255, 255);
SDL_SetTextureAlphaMod(atlasTexture, 255);
}
// SDL_RenderCopy(mainRenderer, itemTex, NULL,
// &plr->cursor.heldItemRect);
char nameItem[80];
snprintf(nameItem, 80, "%s\n%s", ItemRegistry[itemIndex].name, OrientStrings[plr->cursor.direction]);
SDL_RenderCopy(mainRenderer, atlasTexture, &itemAtlasRect, &plr->cursor.heldItemRect);
renderText(mainRenderer, fonts[2], nameItem, plr->cursor.heldItemRect.x,
plr->cursor.heldItemRect.y - (fonts[2].size * 3 / 2));
}
SDL_SetTextureAlphaMod(atlasTexture, 255);
SDL_SetTextureColorMod(atlasTexture, 255, 255, 255);
}
renderBar(mainRenderer, (DISPLAY_WIDTH / 2) - 128, DISPLAY_HEIGHT - 70, 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 - 110, 200, 8,
tempko, tempko2, breakingBarColor, 4);
}
SDL_SetRenderDrawColor(mainRenderer, 0, 0, 0, 255);
SDL_RenderFillRect(mainRenderer, &targetItemBGRect);
targetItemRect.y = DISPLAY_HEIGHT - TILE_SIZE;
targetItemRect.x = TILE_SIZE / 4;
SDL_SetTextureBlendMode(atlasTexture, SDL_BLENDMODE_ADD);
for (ItemType i = 0; i < ITEMREGISTRY_SIZE; i++) {
if (ItemRegistry[i].name[0] == 0x00) {
continue;
}
SDL_Rect itemAtlasRectd = ItemRegistry[i].animation.atlasRects[plr->cursor.direction][(
(animationStep /
ItemRegistry[i].beltAnimation.divisor) %
(
ItemRegistry[i].beltAnimation.frameCount -
ItemRegistry[i].beltAnimation.startFrame)) +
ItemRegistry[i].beltAnimation.startFrame];
if (itemAtlasRectd.w == 0 || itemAtlasRectd.h == 0) {
itemAtlasRectd = ItemRegistry[i].animation.atlasRects[ORIENT_LEFT][(
(animationStep /
ItemRegistry[i].beltAnimation.divisor) %
(
ItemRegistry[i].beltAnimation.frameCount -
ItemRegistry[i].beltAnimation.startFrame)) +
ItemRegistry[i].beltAnimation.startFrame];
}
if (itemAtlasRectd.w != 0 && itemAtlasRectd.h != 0) {
if (plr->inventory.slotCounts[i] <= 0) {
// Set a red tint (255, 0, 0)
SDL_SetTextureColorMod(atlasTexture, 128, 128, 255);
}
SDL_RenderCopy(mainRenderer, atlasTexture, &itemAtlasRectd, &targetItemRect);
SDL_SetTextureColorMod(atlasTexture, 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 / 2 * 3;
}
}
SDL_SetTextureBlendMode(atlasTexture, SDL_BLENDMODE_BLEND);
SDL_SetRenderTarget(mainRenderer, originalTarget);
}