aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/map.h23
-rw-r--r--include/map_manager.h18
-rw-r--r--src/map.c197
-rw-r--r--src/map_manager.c115
4 files changed, 220 insertions, 133 deletions
diff --git a/include/map.h b/include/map.h
new file mode 100644
index 0000000..6106dc1
--- /dev/null
+++ b/include/map.h
@@ -0,0 +1,23 @@
+#pragma once
+
+#include "raylib.h"
+#include "raytmx.h"
+
+typedef struct {
+ TmxMap *map;
+ TmxLayer *wallLayer;
+ TmxLayer *groundLayer;
+ TmxLayer *decorLayer;
+} Map;
+
+typedef struct Entities Entities;
+
+Map *LoadMap(const char *filename, Entities *entities);
+
+bool isCollision(Map *map, Rectangle bounds);
+
+void DrawMap(Map *map);
+void DrawPickups(Entities *entities, Map *map);
+void DrawKeys(Entities *entities, Map *map);
+
+void UnloadMap(Map *map);
diff --git a/include/map_manager.h b/include/map_manager.h
deleted file mode 100644
index 46ec63e..0000000
--- a/include/map_manager.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#ifndef MAP_MANAGER_H
-#define MAP_MANAGER_H
-
-#include "raytmx.h"
-
-typedef struct MapManager {
- TmxMap *map;
- TmxLayer *wallLayer;
- TmxLayer *solidLayer;
- TmxLayer *pickupLayer;
-} MapManager;
-
-MapManager LoadGameMap(const char *fileName);
-void UnloadGameMap(MapManager *mgr);
-bool IsWallCollision(MapManager *mgr, Rectangle rect);
-void DrawMap(MapManager *mgr);
-
-#endif
diff --git a/src/map.c b/src/map.c
new file mode 100644
index 0000000..398b721
--- /dev/null
+++ b/src/map.c
@@ -0,0 +1,197 @@
+#include "map.h"
+#include "entities.h"
+#include "raylib.h"
+
+#define RAYTMX_IMPLEMENTATION
+#include "raytmx.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+static TmxLayer *FindLayerByName(TmxMap *map, const char *name) {
+ for (uint32_t i = 0; i < map->layersLength; i++) {
+ if (strcmp(map->layers[i].name, name) == 0)
+ return &map->layers[i];
+ }
+ return NULL;
+}
+
+static TmxTileset *FindTileSetByGid(TmxMap *map, int gid) {
+ for (uint32_t i = 0; i < map->tilesetsLength; i++) {
+ if (map->tilesets[i].firstGid <= (uint32_t)gid &&
+ (uint32_t)gid <= map->tilesets[i].lastGid)
+ return &map->tilesets[i];
+ }
+ return NULL;
+}
+
+static PickupType GetPickupTypeByTileId(int tileId) {
+ int count = sizeof(PICKUP_TILE_ID) / sizeof(PICKUP_TILE_ID[0]);
+ for (int i = 0; i < count; i++) {
+ if (PICKUP_TILE_ID[i] == tileId)
+ return (PickupType)i;
+ }
+ return PICKUP_COIN;
+}
+
+static Rectangle GetTileBounds(TmxTileset *tileset, uint32_t tileId, float worldX,
+ float worldY) {
+ for (uint32_t i = 0; i < tileset->tilesLength; i++) {
+ if (tileset->tiles[i].id == tileId) {
+ TmxObjectGroup *og = &tileset->tiles[i].objectGroup;
+ if (og->objectsLength > 0) {
+ TmxObject *obj = &og->objects[0];
+ return (Rectangle){
+ worldX + (float)obj->x,
+ worldY + (float)obj->y,
+ (float)obj->width,
+ (float)obj->height,
+ };
+ }
+ }
+ }
+ return (Rectangle){worldX, worldY, (float)tileset->tileWidth,
+ (float)tileset->tileHeight};
+}
+
+static void LoadPickups(TmxMap *tmxMap, TmxLayer *layer, Entities *entities) {
+ TmxObjectGroup *group = &layer->exact.objectGroup;
+ for (uint32_t i = 0; i < group->objectsLength; i++) {
+ TmxObject *object = &group->objects[i];
+ if (object->type != OBJECT_TYPE_TILE ||
+ entities->pickupsCount >= MAX_ENTITIES)
+ continue;
+
+ TmxTileset *tileset = FindTileSetByGid(tmxMap, object->gid);
+ assert(tileset);
+
+ uint32_t tileId = object->gid - tileset->firstGid;
+ float x = (float)object->x;
+ float y = (float)object->y - (float)tileset->tileHeight;
+
+ Pickup *p = &entities->pickups[entities->pickupsCount++];
+ p->type = GetPickupTypeByTileId((int)tileId);
+ p->position = (Vector2){x, y};
+ p->bounds = GetTileBounds(tileset, tileId, x, y);
+ p->value = 1;
+ p->active = true;
+ p->gid = (uint32_t)object->gid;
+ }
+}
+
+static void LoadKeys(TmxMap *tmxMap, TmxLayer *layer, Entities *entities) {
+ TmxObjectGroup *group = &layer->exact.objectGroup;
+ for (uint32_t i = 0; i < group->objectsLength; i++) {
+ TmxObject *object = &group->objects[i];
+ if (object->type != OBJECT_TYPE_TILE || entities->keysCount >= MAX_ENTITIES)
+ continue;
+
+ TmxTileset *tileset = FindTileSetByGid(tmxMap, object->gid);
+ assert(tileset);
+
+ uint32_t tileId = object->gid - tileset->firstGid;
+ float x = (float)object->x;
+ float y = (float)object->y - (float)tileset->tileHeight;
+
+ Key *k = &entities->keys[entities->keysCount++];
+ k->position = (Vector2){x, y};
+ k->bounds = GetTileBounds(tileset, tileId, x, y);
+ k->uniqueId = (int)object->id;
+ k->active = true;
+ k->gid = (uint32_t)object->gid;
+ }
+}
+
+Map *LoadMap(const char *filename, Entities *entities) {
+ Map *map = (Map *)malloc(sizeof(Map));
+ if (!map)
+ return NULL;
+
+ map->map = LoadTMX(filename);
+ if (!map->map) {
+ free(map);
+ return NULL;
+ }
+
+ map->wallLayer = FindLayerByName(map->map, "Walls");
+ map->groundLayer = FindLayerByName(map->map, "Ground");
+ map->decorLayer = FindLayerByName(map->map, "Decor");
+
+ if (entities) {
+ TmxLayer *pickupsLayer = FindLayerByName(map->map, "Pickups");
+ if (pickupsLayer)
+ LoadPickups(map->map, pickupsLayer, entities);
+
+ TmxLayer *itemsLayer = FindLayerByName(map->map, "Items");
+ if (itemsLayer)
+ LoadKeys(map->map, itemsLayer, entities);
+ }
+
+ return map;
+}
+
+bool isCollision(Map *map, Rectangle bounds) {
+ if (!map || !map->wallLayer || !map->decorLayer)
+ return false;
+ return CheckCollisionTMXTileLayersRec(map->map, map->wallLayer, 1, bounds,
+ NULL) ||
+ CheckCollisionTMXTileLayersRec(map->map, map->decorLayer, 1, bounds,
+ NULL);
+}
+
+void DrawMap(Map *map) {
+ if (!map)
+ return;
+ AnimateTMX(map->map);
+
+ TmxLayer layers[3];
+ uint32_t count = 0;
+ if (map->groundLayer) layers[count++] = *map->groundLayer;
+ if (map->wallLayer) layers[count++] = *map->wallLayer;
+ if (map->decorLayer) layers[count++] = *map->decorLayer;
+ DrawTMXLayers(map->map, NULL, NULL, layers, count, 0, 0, WHITE);
+}
+
+static void DrawTileByGid(TmxMap *tmxMap, uint32_t gid, float x, float y) {
+ if (gid == 0 || gid >= tmxMap->gidsToTilesLength)
+ return;
+ TmxTile tile = tmxMap->gidsToTiles[gid];
+ if (tile.gid == 0)
+ return;
+ if (tile.hasAnimation && tile.frameIndex < tile.animation.framesLength) {
+ uint32_t frameGid = tile.animation.frames[tile.frameIndex].gid;
+ if (frameGid < tmxMap->gidsToTilesLength)
+ tile = tmxMap->gidsToTiles[frameGid];
+ }
+ DrawTextureRec(tile.texture, tile.sourceRect, (Vector2){x, y}, WHITE);
+}
+
+void DrawPickups(Entities *entities, Map *map) {
+ if (!entities || !map)
+ return;
+ for (int i = 0; i < entities->pickupsCount; i++) {
+ Pickup *p = &entities->pickups[i];
+ if (!p->active)
+ continue;
+ DrawTileByGid(map->map, p->gid, p->position.x, p->position.y);
+ }
+}
+
+void DrawKeys(Entities *entities, Map *map) {
+ if (!entities || !map)
+ return;
+ for (int i = 0; i < entities->keysCount; i++) {
+ Key *k = &entities->keys[i];
+ if (!k->active)
+ continue;
+ DrawTileByGid(map->map, k->gid, k->position.x, k->position.y);
+ }
+}
+
+void UnloadMap(Map *map) {
+ if (!map)
+ return;
+ UnloadTMX(map->map);
+ free(map);
+}
diff --git a/src/map_manager.c b/src/map_manager.c
deleted file mode 100644
index bcb9063..0000000
--- a/src/map_manager.c
+++ /dev/null
@@ -1,115 +0,0 @@
-#include "map_manager.h"
-#include "entity.h"
-#include "raytmx.h"
-#include "globals.h"
-
-// Forward declaration of internal raytmx function
-void DrawTMXLayerTile(const TmxMap* map, Rectangle viewport, uint32_t rawGid, Rectangle destRect, Color tint);
-
-MapManager LoadGameMap(const char *fileName) {
- MapManager mgr = {0};
- mgr.map = LoadTMX(fileName);
-
- // Cache layers for faster access
- if (mgr.map) {
- for (uint32_t i = 0; i < mgr.map->layersLength; i++) {
- if (strcmp(mgr.map->layers[i].name, "Walls") == 0 &&
- mgr.map->layers[i].type == LAYER_TYPE_TILE_LAYER) {
- mgr.wallLayer = &mgr.map->layers[i];
- }
- if (strcmp(mgr.map->layers[i].name, "Solid") == 0 &&
- mgr.map->layers[i].type == LAYER_TYPE_TILE_LAYER) {
- mgr.solidLayer = &mgr.map->layers[i];
- }
- if (strcmp(mgr.map->layers[i].name, "Collectible") == 0 ||
- strcmp(mgr.map->layers[i].name, "Pickups") == 0)
- mgr.pickupLayer = &mgr.map->layers[i];
- }
- }
- return mgr;
-}
-
-void UnloadGameMap(MapManager *mgr) {
- if (mgr->map) {
- UnloadTMX(mgr->map);
- mgr->map = NULL;
- }
-}
-
-bool IsWallCollision(MapManager *mgr, Rectangle rect) {
- // Check main walls
- if (mgr->wallLayer && CheckCollisionTMXTileLayersRec(mgr->map, mgr->wallLayer, 1, rect, NULL))
- return true;
-
- // Check additional solid layer (props, etc)
- if (mgr->solidLayer && CheckCollisionTMXTileLayersRec(mgr->map, mgr->solidLayer, 1, rect, NULL))
- return true;
-
- return false;
-}
-
-// Internal helper for debug rendering
-static void DrawDebugTileCollision(TmxMap *map, TmxLayer *layer, Color color) {
- if (!layer || layer->type != LAYER_TYPE_TILE_LAYER) return;
-
- 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 && gid < map->gidsToTilesLength) {
- TmxTile tileData = map->gidsToTiles[gid];
- for (uint32_t objIdx = 0; objIdx < tileData.objectGroup.objectsLength; objIdx++) {
- TmxObject obj = tileData.objectGroup.objects[objIdx];
- DrawRectangleLinesEx((Rectangle){
- (float)x * TILE_SIZE + (float)obj.x,
- (float)y * TILE_SIZE + (float)obj.y,
- (float)obj.width,
- (float)obj.height
- }, 0.5f, color);
- }
- }
- }
- }
-}
-
-void DrawMap(MapManager *mgr) {
- AnimateTMX(mgr->map);
- DrawTMX(mgr->map, NULL, NULL, 0, 0, WHITE);
-
- if (debugMode) {
- DrawDebugTileCollision(mgr->map, mgr->wallLayer, RED);
- DrawDebugTileCollision(mgr->map, mgr->solidLayer, RED);
- }
-}
-
-void DrawEntities(EntityManager *mgr, TmxMap *map) {
- Rectangle drawViewport = {-1000, -1000, 5000, 5000};
-
- for (int i = 0; i < mgr->collectiblesCount; i++) {
- if (mgr->collectibles[i].active) {
- // Pickups are drawn by the map renderer (DrawTMX).
- // We only draw the debug hitbox here.
- if (debugMode) {
- DrawRectangleLinesEx(mgr->collectibles[i].bounds, 0.5f, GREEN);
- }
- }
- }
-
- for (int i = 0; i < mgr->movablesCount; i++) {
- DrawTMXLayerTile(map, drawViewport, mgr->movables[i].gid,
- mgr->movables[i].bounds, WHITE);
- if (debugMode) {
- DrawRectangleLinesEx(mgr->movables[i].bounds, 0.5f, GREEN);
- }
- }
-
- for (int i = 0; i < mgr->enemiesCount; i++) {
- if (mgr->enemies[i].active) {
- DrawTMXLayerTile(map, drawViewport, mgr->enemies[i].gid,
- mgr->enemies[i].bounds, WHITE);
- if (debugMode) {
- DrawRectangleLinesEx(mgr->enemies[i].bounds, 0.5f, RED);
- }
- }
- }
-}