aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/entities.h126
-rw-r--r--include/entity.h61
-rw-r--r--include/game.h11
-rw-r--r--include/globals.h13
-rw-r--r--src/entity.c202
5 files changed, 126 insertions, 287 deletions
diff --git a/include/entities.h b/include/entities.h
new file mode 100644
index 0000000..7bd38f3
--- /dev/null
+++ b/include/entities.h
@@ -0,0 +1,126 @@
+#pragma once
+
+#include "raylib.h"
+#include "raytmx.h"
+
+#include "map.h"
+#include "player.h"
+
+#define MAX_ENTITIES 120
+
+typedef enum {
+ PICKUP_COIN,
+ PICKUP_POTION,
+ PICKUP_BOMB,
+ PICKUP_FULL_HEART,
+ PICKUP_HALF_HEART,
+ PICKUP_GOLD_BAR,
+ PICKUP_GOLD_NUGGET
+} PickupType;
+
+static const int PICKUP_TILE_ID[] = {0, 4, 8, 12, 16, 20, 24};
+
+typedef enum { STATE_IDLE, STATE_PATROL, STATE_CHASE, STATE_ATTACK } EnemyState;
+
+typedef struct {
+ PickupType type;
+ Vector2 position;
+ Rectangle bounds;
+ int value;
+ bool active;
+ uint32_t gid;
+} Pickup;
+
+typedef struct {
+ Vector2 position;
+ Rectangle bounds;
+ int uniqueId;
+ bool active;
+ uint32_t gid;
+} Key;
+
+typedef struct {
+ Vector2 position;
+ Rectangle bounds;
+ int health;
+ EnemyState state;
+
+ TmxTileset tileset;
+ int currentFrame;
+ float frameTime;
+ bool facingRight;
+
+ bool active;
+} Bat;
+
+typedef struct {
+ Vector2 position;
+ Rectangle bounds;
+ int health;
+ EnemyState state;
+
+ TmxTileset tileset;
+ int currentFrame;
+ float frameTime;
+ bool facingRight;
+
+ bool active;
+} Slime;
+
+typedef struct {
+ Vector2 position;
+ Rectangle bounds;
+ int health;
+ EnemyState state;
+
+ TmxTileset tileset;
+ int currentFrame;
+ float frameTime;
+ bool facingRight;
+
+ bool active;
+} FlyingSkull;
+
+typedef struct {
+ Vector2 position;
+ Rectangle bounds;
+ bool active;
+} Vase;
+
+typedef struct {
+ Vector2 position;
+ Rectangle bounds;
+ bool active;
+} Crate;
+
+struct Entities {
+ Pickup pickups[MAX_ENTITIES];
+ int pickupsCount;
+
+ Key keys[MAX_ENTITIES];
+ int keysCount;
+
+ Bat bats[MAX_ENTITIES];
+ int batsCount;
+
+ Slime slimes[MAX_ENTITIES];
+ int slimesCount;
+
+ FlyingSkull flyingSkulls[MAX_ENTITIES];
+ int flyingSkullsCount;
+
+ Vase vases[MAX_ENTITIES];
+ int vasesCount;
+
+ Crate crates[MAX_ENTITIES];
+ int cratesCount;
+};
+
+void UpdateBat(Bat *bat, Player *player, Map *map);
+void DrawBat(Bat *bat);
+
+void UpdateSlime(Slime *slime, Player *player, Map *map);
+void DrawSlime(Slime *slime);
+
+void UpdateFlyingSkull(FlyingSkull *skull, Player *player, Map *map);
+void DrawFlyingSkull(FlyingSkull *skull);
diff --git a/include/entity.h b/include/entity.h
deleted file mode 100644
index 60467ab..0000000
--- a/include/entity.h
+++ /dev/null
@@ -1,61 +0,0 @@
-#ifndef ENTITY_H
-#define ENTITY_H
-
-#include "raylib.h"
-#include "raytmx.h"
-
-#include "player.h"
-#include "map_manager.h"
-
-typedef struct Enemy {
- Vector2 position;
- Rectangle bounds;
- uint32_t gid;
- int health;
- bool active;
-} Enemy;
-
-typedef struct Static {
- Vector2 position;
- Rectangle bounds;
- uint32_t gid;
- bool active;
-} Static;
-
-typedef struct Collectible {
- Vector2 position;
- Rectangle bounds;
- uint32_t gid;
- bool active;
- int tileX;
- int tileY;
-} Collectible;
-
-typedef struct Movable {
- Vector2 position;
- Rectangle bounds;
- uint32_t gid;
- bool active;
-} Movable;
-
-typedef struct EntityManager {
- Enemy *enemies;
- int enemiesCount;
-
- Collectible *collectibles;
- int collectiblesCount;
-
- Static *statics;
- int staticsCount;
-
- Movable *movables;
- int movablesCount;
-} EntityManager;
-
-EntityManager InitEntityManager(uint32_t capacity);
-void SpawnEntitiesFromMap(EntityManager *mgr, TmxMap *map);
-void UpdateEntities(EntityManager *mgr, Player *player, MapManager *mapMgr);
-void DrawEntities(EntityManager *mgr, TmxMap *map);
-void UnloadEntityManager(EntityManager *mgr);
-
-#endif // ENTITY_H
diff --git a/include/game.h b/include/game.h
deleted file mode 100644
index 6b37293..0000000
--- a/include/game.h
+++ /dev/null
@@ -1,11 +0,0 @@
-#ifndef GAME_H
-#define GAME_H
-
-typedef enum GameScreen {
- SCREEN_TITLE,
- SCREEN_PLAYING,
- SCREEN_PAUSED,
- SCREEN_GAME_OVER
-} GameScreen;
-
-#endif // GAME_H
diff --git a/include/globals.h b/include/globals.h
deleted file mode 100644
index e7830de..0000000
--- a/include/globals.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef GLOBALS_H
-#define GLOBALS_H
-
-#include "raylib.h"
-
-#define TILE_SIZE 16
-#define SCREEN_WIDTH 1280
-#define SCREEN_HEIGHT 720
-#define BACKGROUND_COLOR (Color){ 88, 68, 34, 255 }
-
-extern bool debugMode;
-
-#endif
diff --git a/src/entity.c b/src/entity.c
deleted file mode 100644
index 9fc582c..0000000
--- a/src/entity.c
+++ /dev/null
@@ -1,202 +0,0 @@
-#include "entity.h"
-#include "map_manager.h"
-#include "player.h"
-#include "raymath.h"
-#include "globals.h"
-#include <stdlib.h>
-#include <string.h>
-
-EntityManager InitEntityManager(uint32_t maxPerType) {
- EntityManager mgr;
- mgr.enemies = (Enemy *)calloc(maxPerType, sizeof(Enemy));
- mgr.collectibles = (Collectible *)calloc(maxPerType, sizeof(Collectible));
- mgr.movables = (Movable *)calloc(maxPerType, sizeof(Movable));
- mgr.statics = (Static *)calloc(maxPerType, sizeof(Static));
-
- mgr.enemiesCount = 0;
- mgr.collectiblesCount = 0;
- mgr.movablesCount = 0;
- mgr.staticsCount = 0;
-
- return mgr;
-}
-
-void SpawnEntitiesFromMap(EntityManager *mgr, TmxMap *map) {
- for (uint32_t i = 0; i < map->layersLength; i++) {
- TmxLayer *layer = &map->layers[i];
-
- // Handle Tile Layer Pickups
- if (layer->type == LAYER_TYPE_TILE_LAYER &&
- (strcmp(layer->name, "Pickups") == 0 || strcmp(layer->name, "Collectible") == 0)) {
- TmxTileLayer *tileLayer = &layer->exact.tileLayer;
- for (uint32_t y = 0; y < tileLayer->height; y++) {
- for (uint32_t x = 0; x < tileLayer->width; x++) {
- uint32_t gid = tileLayer->tiles[y * tileLayer->width + x];
- if (gid != 0) {
- float px = (float)x * map->tileWidth;
- float py = (float)y * map->tileHeight;
-
- // Default bounds (whole tile)
- Rectangle customBounds = { px, py, (float)map->tileWidth, (float)map->tileHeight };
-
- // Check if the tile has a custom collision shape from Tileset Editor
- if (gid < map->gidsToTilesLength) {
- TmxTile tileData = map->gidsToTiles[gid];
-
- // Use the first animation frame's collision if it exists
- uint32_t targetGid = gid;
- if (tileData.hasAnimation && tileData.animation.framesLength > 0) {
- targetGid = tileData.animation.frames[0].gid;
- }
-
- // Look up tile data for the frame (accounting for local vs global IDs)
- // Note: raytmx internal gidsToTiles uses global IDs
- if (targetGid < map->gidsToTilesLength) {
- TmxObjectGroup colGroup = map->gidsToTiles[targetGid].objectGroup;
- if (colGroup.objectsLength > 0) {
- TmxObject colObj = colGroup.objects[0];
- customBounds = (Rectangle){
- px + (float)colObj.x,
- py + (float)colObj.y,
- (float)colObj.width,
- (float)colObj.height
- };
- }
- }
- }
-
- mgr->collectibles[mgr->collectiblesCount++] = (Collectible){
- .position = {px, py},
- .bounds = customBounds,
- .active = true,
- .gid = gid,
- .tileX = (int)x,
- .tileY = (int)y
- };
- }
- }
- }
- }
-
- if (layer->type != LAYER_TYPE_OBJECT_GROUP)
- continue;
-
- TmxObjectGroup group = layer->exact.objectGroup;
-
- if (strcmp(layer->name, "Static") == 0) {
- for (uint32_t j = 0; j < group.objectsLength; j++) {
- TmxObject object = group.objects[j];
- mgr->statics[mgr->staticsCount++] =
- (Static){.position = {(float)object.x, (float)object.y},
- .bounds = {(float)object.x, (float)object.y,
- (float)object.width, (float)object.height},
- .active = true,
- .gid = object.gid};
- }
- }
- if (strcmp(layer->name, "Movable") == 0) {
- for (uint32_t j = 0; j < group.objectsLength; j++) {
- TmxObject object = group.objects[j];
- mgr->movables[mgr->movablesCount++] =
- (Movable){.position = {(float)object.x, (float)object.y},
- .bounds = {(float)object.x, (float)object.y,
- (float)object.width, (float)object.height},
- .active = true,
- .gid = object.gid};
- }
- }
- if (strcmp(layer->name, "Collectible") == 0) {
- for (uint32_t j = 0; j < group.objectsLength; j++) {
- TmxObject object = group.objects[j];
- mgr->collectibles[mgr->collectiblesCount++] =
- (Collectible){.position = {(float)object.x, (float)object.y},
- .bounds = {(float)object.x, (float)object.y,
- (float)object.width, (float)object.height},
- .active = true,
- .gid = object.gid};
- }
- }
- if (strcmp(layer->name, "Enemy") == 0) {
- for (uint32_t j = 0; j < group.objectsLength; j++) {
- TmxObject object = group.objects[j];
- mgr->enemies[mgr->enemiesCount++] =
- (Enemy){.position = {(float)object.x, (float)object.y},
- .bounds = {(float)object.x, (float)object.y,
- (float)object.width, (float)object.height},
- .active = true,
- .gid = object.gid};
- }
- }
- }
-}
-
-void UpdateEntities(EntityManager *mgr, Player *player, MapManager *mapMgr) {
- // 1. Update Pickups (Collision only)
- for (int i = 0; i < mgr->collectiblesCount; i++) {
- if (mgr->collectibles[i].active &&
- CheckCollisionRecs(player->bounds, mgr->collectibles[i].bounds)) {
- mgr->collectibles[i].active = false;
-
- // Visually remove from map if it's a tile pickup
- if (mapMgr->pickupLayer && mapMgr->pickupLayer->type == LAYER_TYPE_TILE_LAYER) {
- TmxTileLayer *tileLayer = &mapMgr->pickupLayer->exact.tileLayer;
- int idx = mgr->collectibles[i].tileY * tileLayer->width + mgr->collectibles[i].tileX;
- if (idx >= 0 && idx < (int)tileLayer->tilesLength) {
- tileLayer->tiles[idx] = 0;
- }
- }
- }
- }
-
- // 2. Update Movables (Physics/Pushing)
- for (int i = 0; i < mgr->movablesCount; i++) {
- Movable *m = &mgr->movables[i];
- if (CheckCollisionRecs(player->bounds, m->bounds)) {
- // Push logic: move the block in player's direction if no wall is there
- Vector2 pushDir =
- Vector2Normalize(Vector2Subtract(m->position, player->position));
- Vector2 nextPos = Vector2Add(
- m->position, Vector2Scale(pushDir, player->speed * GetFrameTime()));
- Rectangle nextRect = {nextPos.x, nextPos.y, m->bounds.width,
- m->bounds.height};
-
- if (!IsWallCollision(mapMgr, nextRect)) {
- m->position = nextPos;
- m->bounds.x = nextPos.x;
- m->bounds.y = nextPos.y;
- }
- }
- }
-
- // 3. Update Enemies (AI)
- for (int i = 0; i < mgr->enemiesCount; i++) {
- if (!mgr->enemies[i].active)
- continue;
- // Basic AI: Move toward player if within range
- if (Vector2Distance(mgr->enemies[i].position, player->position) < 100.0f) {
- Vector2 dir = Vector2Normalize(
- Vector2Subtract(player->position, mgr->enemies[i].position));
- mgr->enemies[i].position = Vector2Add(
- mgr->enemies[i].position, Vector2Scale(dir, 50.0f * GetFrameTime()));
- mgr->enemies[i].bounds.x = mgr->enemies[i].position.x;
- mgr->enemies[i].bounds.y = mgr->enemies[i].position.y;
- }
- }
-}
-
-void UnloadEntityManager(EntityManager *mgr) {
- if (mgr->enemies) free(mgr->enemies);
- if (mgr->collectibles) free(mgr->collectibles);
- if (mgr->movables) free(mgr->movables);
- if (mgr->statics) free(mgr->statics);
-
- mgr->enemies = NULL;
- mgr->collectibles = NULL;
- mgr->movables = NULL;
- mgr->statics = NULL;
-
- mgr->enemiesCount = 0;
- mgr->collectiblesCount = 0;
- mgr->movablesCount = 0;
- mgr->staticsCount = 0;
-}