Testing
This commit is contained in:
187
entity/entity.c
Normal file
187
entity/entity.c
Normal file
@@ -0,0 +1,187 @@
|
||||
//
|
||||
// Created by bruno on 7.6.2025.
|
||||
//
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
#include <dirent.h>
|
||||
#include "entity.h"
|
||||
#include "../player/player.h"
|
||||
#include "../util/pathfinding.h"
|
||||
|
||||
EntityArray entities;
|
||||
|
||||
EntityTypeReg EntityRegistry[ENTITY_MAX_COUNT];
|
||||
|
||||
void renderEntities(SDL_Renderer *renderer, SDL_Rect playerRect) {
|
||||
SDL_Texture *oldTarget = SDL_GetRenderTarget(renderer);
|
||||
SDL_SetRenderTarget(renderer, entityTexture);
|
||||
SDL_RenderClear(mainRenderer);
|
||||
for (int i = 0; i < entities.activeCount; i++) {
|
||||
Entity *ent = &entities.entities[i];
|
||||
SDL_Rect renderRect = ent->renderRect;
|
||||
adjustRect(&renderRect, playerRect);
|
||||
if (!checkCollision(renderRect, screenRect)) {
|
||||
continue;
|
||||
}
|
||||
EntityTypeReg entType = EntityRegistry[ent->type];
|
||||
char animationFrame = (animationStep / entType.animation.divisor) % entType.animation.frameCount;
|
||||
SDL_RenderCopy(renderer, atlasTexture, &entType.animation.atlasRects[animationFrame], &renderRect);
|
||||
}
|
||||
SDL_SetRenderTarget(renderer, oldTarget);
|
||||
}
|
||||
|
||||
void updateEntities() {
|
||||
for (int i = 0; i < entities.activeCount; i++) {
|
||||
Entity *ent = &entities.entities[i];
|
||||
EntityTypeReg entT = EntityRegistry[ent->type];
|
||||
|
||||
// Step 1: If no path, or we're at the end of a path, check for re-path
|
||||
bool atTargetSnapshot = ent->tileRect.x == ent->targetSnapshot.x &&
|
||||
ent->tileRect.y == ent->targetSnapshot.y;
|
||||
|
||||
bool needsPath = ent->path.length == 0 || ent->path.stepIndex >= ent->path.length;
|
||||
|
||||
if (needsPath && (atTargetSnapshot || ent->path.length == 0)) {
|
||||
if (ent->tileRect.x != ent->target.x || ent->tileRect.y != ent->target.y) {
|
||||
if (isWalkable(ent->target) && find_path(ent->tileRect, ent->target)) {
|
||||
ent->path = reconstruct_path(ent->target);
|
||||
ent->path.stepIndex = 0;
|
||||
ent->targetSnapshot = ent->target; // snapshot the current target
|
||||
ent->fromTile = ent->tileRect;
|
||||
ent->toTile = ent->path.steps[0];
|
||||
ent->interpolateTick = 0;
|
||||
ent->entityNextTick = animationStep + entT.entityTickRate;
|
||||
} else {
|
||||
// No path found — freeze
|
||||
ent->path.length = 0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Step 2: If it's time to move to the next tile
|
||||
if (ent->path.length > 0 && ent->path.stepIndex < ent->path.length &&
|
||||
animationStep >= ent->entityNextTick) {
|
||||
ent->fromTile = ent->tileRect;
|
||||
ent->toTile = ent->path.steps[ent->path.stepIndex];
|
||||
ent->tileRect = ent->toTile;
|
||||
ent->entityNextTick = animationStep + entT.entityTickRate;
|
||||
ent->interpolateTick = 0;
|
||||
ent->path.stepIndex++;
|
||||
}
|
||||
|
||||
// Step 3: Interpolate renderRect between fromTile and toTile
|
||||
MiniRect from = {
|
||||
.x = ent->fromTile.x * TILE_SIZE,
|
||||
.y = ent->fromTile.y * TILE_SIZE
|
||||
};
|
||||
MiniRect to = {
|
||||
.x = ent->toTile.x * TILE_SIZE,
|
||||
.y = ent->toTile.y * TILE_SIZE
|
||||
};
|
||||
|
||||
float t = (float)ent->interpolateTick / entT.entityTickRate;
|
||||
ent->renderRect.x = (int)(from.x + (to.x - from.x) * t);
|
||||
ent->renderRect.y = (int)(from.y + (to.y - from.y) * t);
|
||||
|
||||
if (ent->interpolateTick < entT.entityTickRate) {
|
||||
ent->interpolateTick++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void registerEntity(char fname[20], SDL_Renderer *renderer) {
|
||||
char name[21];
|
||||
|
||||
// Load animation frames
|
||||
int frame = 0;
|
||||
int indexEntity = 0;
|
||||
char texturePath[80];
|
||||
|
||||
if (sscanf(fname, "%d_%20[^_]_%d.png", &indexEntity, name, &frame) == 3) {
|
||||
// Success: you now have index, fname, and frame
|
||||
} else {
|
||||
fprintf(stderr, "Invalid format: %s\n", fname);
|
||||
}
|
||||
strcpy(EntityRegistry[indexEntity].name, name);
|
||||
snprintf(texturePath, sizeof(texturePath), "./assets/entities/%s", fname);
|
||||
SDL_Texture *texture = IMG_LoadTexture(renderer, texturePath);
|
||||
if (!texture) {
|
||||
if (frame == 0) {
|
||||
fprintf(stderr, "Failed to load entity texture %s: %s\n", texturePath, IMG_GetError());
|
||||
}
|
||||
}
|
||||
|
||||
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_NONE);
|
||||
|
||||
printf("Ent %s to %d\n", fname, indexEntity);
|
||||
|
||||
EntityRegistry[indexEntity].animation.textures[frame] = texture;
|
||||
EntityRegistry[indexEntity].animation.atlasRects[frame] = allocate_32x32(texture, renderer);
|
||||
|
||||
EntityRegistry[indexEntity].type = indexEntity;
|
||||
EntityRegistry[indexEntity].animation.frameCount = frame + 1;
|
||||
EntityRegistry[indexEntity].animation.divisor = 1;
|
||||
EntityRegistry[indexEntity].entityTickRate = 8;
|
||||
|
||||
if (indexEntity + 1 > backgroundTileTypeIndex) {
|
||||
backgroundTileTypeIndex = indexEntity + 1;
|
||||
}
|
||||
}
|
||||
|
||||
void loadEntities(SDL_Renderer *renderer) {
|
||||
DIR *dir = opendir("./assets/entities");
|
||||
if (!dir) {
|
||||
perror("Failed to open entities directory");
|
||||
return;
|
||||
}
|
||||
|
||||
char *entityNames[ENTITY_MAX_COUNT];
|
||||
int entityCount = 0;
|
||||
|
||||
struct dirent *entry;
|
||||
while ((entry = readdir(dir))) {
|
||||
char *dot = strrchr(entry->d_name, '.');
|
||||
if (!dot || strcmp(dot, ".png") != 0) continue;
|
||||
|
||||
// Check if baseName already stored
|
||||
int found = 0;
|
||||
for (int i = 0; i < entityCount; ++i) {
|
||||
if (strcmp(entityNames[i], entry->d_name) == 0) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found && entityCount < ENTITY_MAX_COUNT) {
|
||||
entityNames[entityCount++] = strdup(entry->d_name); // Only store base, not full file name
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
|
||||
qsort(entityNames, entityCount, sizeof(char *), compareStrings);
|
||||
|
||||
// Call registerEntity on each base name
|
||||
for (int i = 0; i < entityCount; ++i) {
|
||||
char fileName[64];
|
||||
snprintf(fileName, sizeof(fileName), "%s", entityNames[i]);
|
||||
registerEntity(fileName, renderer);
|
||||
free(entityNames[i]);
|
||||
}
|
||||
}
|
||||
|
||||
int add_entity(EntityArray *arr, Entity t) {
|
||||
if (arr->activeCount >= ENTITY_MAX_COUNT) return 0;
|
||||
arr->entities[arr->activeCount] = t;
|
||||
arr->activeCount++;
|
||||
return arr->activeCount - 1;
|
||||
}
|
||||
|
||||
void remove_entity(EntityArray *arr, int index) {
|
||||
if (index < 0 || index >= arr->activeCount) return;
|
||||
arr->activeCount--;
|
||||
arr->entities[index] = arr->entities[arr->activeCount]; // swap with last active
|
||||
}
|
55
entity/entity.h
Normal file
55
entity/entity.h
Normal file
@@ -0,0 +1,55 @@
|
||||
//
|
||||
// Created by bruno on 7.6.2025.
|
||||
//
|
||||
|
||||
#ifndef FACTORYGAME_ENTITY_H
|
||||
#define FACTORYGAME_ENTITY_H
|
||||
|
||||
#include "../tiles/tile.h"
|
||||
#include "../util/pathfinding.h"
|
||||
|
||||
#define ENTITY_MAX_COUNT 1024
|
||||
|
||||
typedef enum EntityType {
|
||||
GHOST,
|
||||
} EntityType;
|
||||
|
||||
typedef struct EntityTypeReg {
|
||||
EntityType type;
|
||||
Animation animation;
|
||||
char name[20];
|
||||
int speed;
|
||||
int entityTickRate;
|
||||
} EntityTypeReg;
|
||||
|
||||
typedef struct Entity {
|
||||
MiniRect tileRect;
|
||||
SDL_Rect renderRect;
|
||||
EntityType type;
|
||||
uint16_t health;
|
||||
MiniRect target;
|
||||
Path path;
|
||||
int entityNextTick;
|
||||
unsigned char interpolateTick;
|
||||
MiniRect fromTile;
|
||||
MiniRect toTile;
|
||||
MiniRect targetSnapshot;
|
||||
} Entity;
|
||||
|
||||
typedef struct EntityArray {
|
||||
Entity entities[ENTITY_MAX_COUNT];
|
||||
int activeCount;
|
||||
} EntityArray;
|
||||
|
||||
extern EntityArray entities;
|
||||
|
||||
void remove_entity(EntityArray *arr, int index);
|
||||
|
||||
int add_entity(EntityArray *arr, Entity t);
|
||||
|
||||
void renderEntities(SDL_Renderer *renderer, SDL_Rect playerRect);
|
||||
void updateEntities();
|
||||
void registerEntity(char fname[20], SDL_Renderer *renderer);
|
||||
void loadEntities(SDL_Renderer *renderer);
|
||||
|
||||
#endif //FACTORYGAME_ENTITY_H
|
Reference in New Issue
Block a user