From 2a8183e9a345b8718f654b5374aea27986902e77 Mon Sep 17 00:00:00 2001 From: Dominic Masters Date: Fri, 20 Jun 2025 00:24:34 -0500 Subject: [PATCH] Read in tile data from tilemap --- data/map project.tiled-session | 12 ++--- src/dusk/entity/entity.c | 10 ++-- src/dusk/world/CMakeLists.txt | 1 - src/dusk/world/tile.c | 8 --- src/dusk/world/tile.h | 28 +---------- tools/CMakeLists.txt | 3 +- tools/mapcompile/mapcompile.py | 3 -- tools/tilecompile/CMakeLists.txt | 13 +++-- tools/tilecompile/tilecompile.py | 84 ++++++++++++++++++++++++++++++-- 9 files changed, 98 insertions(+), 64 deletions(-) delete mode 100644 src/dusk/world/tile.c diff --git a/data/map project.tiled-session b/data/map project.tiled-session index fe9676b..9da6811 100644 --- a/data/map project.tiled-session +++ b/data/map project.tiled-session @@ -1,5 +1,5 @@ { - "activeFile": "map.tmj", + "activeFile": "overworld.tsx", "expandedProjectPaths": [ "templates", "." @@ -13,16 +13,16 @@ "scaleInEditor": 1 }, "map.tmj": { - "scale": 3, + "scale": 4, "selectedLayer": 2, "viewCenter": { - "x": 6665.833333333333, - "y": 6701.5 + "x": 6625.125, + "y": 6667.875 } }, "overworld.tsx": { "scaleInDock": 1, - "scaleInEditor": 8 + "scaleInEditor": 4 } }, "last.externalTilesetPath": "/home/yourwishes/htdocs/dusk/data", @@ -35,8 +35,8 @@ "project": "map project.tiled-project", "property.type": "int", "recentFiles": [ - "overworld.tsx", "map.tmj", + "overworld.tsx", "entities.tsx" ], "tileset.lastUsedFilter": "Tiled tileset files (*.tsx *.xml)", diff --git a/src/dusk/entity/entity.c b/src/dusk/entity/entity.c index 7d186b4..649f8df 100644 --- a/src/dusk/entity/entity.c +++ b/src/dusk/entity/entity.c @@ -9,6 +9,7 @@ #include "assert/assert.h" #include "util/memory.h" #include "world/world.h" +#include "world/tiledata.h" #include "physics/physics.h" entity_t ENTITIES[ENTITY_COUNT_MAX] = {0}; @@ -89,14 +90,10 @@ void entityUpdate(entity_t *entity) { uint8_t chunkTileX = tileX % CHUNK_WIDTH; uint8_t chunkTileY = tileY % CHUNK_HEIGHT; tile_t tile = chunk->tilesBase[chunkTileY * CHUNK_WIDTH + chunkTileX]; - - tilesolidtype_t solidType = ( - tile < TILE_META_DATA_COUNT ? TILE_META_DATA[tile].solidType : - TILE_SOLID_NONE - ); + // Determine tile collision type collisionresult_t collision; - switch(solidType) { + switch(TILE_META_DATA[tile].solidType) { case TILE_SOLID_FULL: collision = physicsCheckCircleAABB( newX, newY, selfCircR, @@ -105,6 +102,7 @@ void entityUpdate(entity_t *entity) { FIXED248(TILE_WIDTH_HEIGHT, 0), FIXED248(TILE_WIDTH_HEIGHT, 0) ); + break; default: continue; diff --git a/src/dusk/world/CMakeLists.txt b/src/dusk/world/CMakeLists.txt index 6fb8d74..446cdbf 100644 --- a/src/dusk/world/CMakeLists.txt +++ b/src/dusk/world/CMakeLists.txt @@ -8,5 +8,4 @@ target_sources(${DUSK_TARGET_NAME} PRIVATE chunk.c overworld.c - tile.c ) \ No newline at end of file diff --git a/src/dusk/world/tile.c b/src/dusk/world/tile.c deleted file mode 100644 index 23aa912..0000000 --- a/src/dusk/world/tile.c +++ /dev/null @@ -1,8 +0,0 @@ -/** - * Copyright (c) 2025 Dominic Masters - * - * This software is released under the MIT License. - * https://opensource.org/licenses/MIT - */ - -#include "tile.h" \ No newline at end of file diff --git a/src/dusk/world/tile.h b/src/dusk/world/tile.h index 755221f..1e285ea 100644 --- a/src/dusk/world/tile.h +++ b/src/dusk/world/tile.h @@ -23,30 +23,4 @@ typedef enum { typedef struct { tilesolidtype_t solidType; -} tilemeta_t; - -static const tilemeta_t TILE_META_DATA[] = { - {TILE_SOLID_NONE}, // 0 - {TILE_SOLID_NONE}, // 1 - {TILE_SOLID_NONE}, // 2 - {TILE_SOLID_NONE}, // 3 - {TILE_SOLID_NONE}, // 4 - {TILE_SOLID_NONE}, // 5 - {TILE_SOLID_NONE}, // 6 - {TILE_SOLID_NONE}, // 7 - {TILE_SOLID_NONE}, // 8 - {TILE_SOLID_NONE}, // 9 - {TILE_SOLID_NONE}, // 10 - {TILE_SOLID_NONE}, // 11 - {TILE_SOLID_NONE}, // 12 - {TILE_SOLID_NONE}, // 13 - {TILE_SOLID_NONE}, // 14 - {TILE_SOLID_NONE}, // 15 - {TILE_SOLID_NONE}, // 16 - {TILE_SOLID_NONE}, // 17 - {TILE_SOLID_FULL}, // 18 - {TILE_SOLID_FULL}, // 19 - {TILE_SOLID_FULL}, // 19 -}; - -#define TILE_META_DATA_COUNT (sizeof(TILE_META_DATA) / sizeof(tilemeta_t)) \ No newline at end of file +} tilemetadata_t; \ No newline at end of file diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 6b9f03a..2698815 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -4,4 +4,5 @@ # https://opensource.org/licenses/MIT # Tools -add_subdirectory(mapcompile) \ No newline at end of file +add_subdirectory(mapcompile) +add_subdirectory(tilecompile) \ No newline at end of file diff --git a/tools/mapcompile/mapcompile.py b/tools/mapcompile/mapcompile.py index 2c65ef3..08a044e 100644 --- a/tools/mapcompile/mapcompile.py +++ b/tools/mapcompile/mapcompile.py @@ -174,9 +174,6 @@ for chunk in firstLayer['chunks']: inputMapHighestX += inputLayerWidthInTiles inputMapHighestY += inputLayerHeightInTiles -print(f"Input map lowest X: {inputMapLowestX}, highest X: {inputMapHighestX}") -print(f"Input map lowest Y: {inputMapLowestY}, highest Y: {inputMapHighestY}") - # We now offset all chunks by the lowest X/Y values to make them start at (0, 0). for layerIndex, layer in enumerate(tileLayers): for chunkIndex, chunk in enumerate(layer['chunks']): diff --git a/tools/tilecompile/CMakeLists.txt b/tools/tilecompile/CMakeLists.txt index 7effe6c..25ce346 100644 --- a/tools/tilecompile/CMakeLists.txt +++ b/tools/tilecompile/CMakeLists.txt @@ -6,16 +6,15 @@ find_package(Python3 COMPONENTS Interpreter REQUIRED) # Custom command to generate all header files -add_custom_target(DUSK_CHUNKS - # OUTPUT ${DUSK_GENERATED_HEADERS_DIR}/world/world.h +add_custom_target(DUSK_TILES COMMAND - ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/mapcompile.py + ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/tilecompile.py --output ${DUSK_GENERATED_HEADERS_DIR} - --input ${DUSK_DATA_DIR}/map.tmj - DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/mapcompile.py - COMMENT "Generating chunk header files" + --input ${DUSK_DATA_DIR}/overworld.tsx + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/tilecompile.py + COMMENT "Generating tile header file" VERBATIM ) # Ensure headers are generated before compiling main -add_dependencies(${DUSK_TARGET_NAME} DUSK_CHUNKS) \ No newline at end of file +add_dependencies(${DUSK_TARGET_NAME} DUSK_TILES) \ No newline at end of file diff --git a/tools/tilecompile/tilecompile.py b/tools/tilecompile/tilecompile.py index bc80fee..e614210 100644 --- a/tools/tilecompile/tilecompile.py +++ b/tools/tilecompile/tilecompile.py @@ -1,13 +1,12 @@ import sys, os import argparse from datetime import datetime -import json -import math +import xml.etree.ElementTree as ET # Check if the script is run with the correct arguments parser = argparse.ArgumentParser(description="Generate chunk header files") parser.add_argument('--output', required=True, help='Dir to output headers') -parser.add_argument('--input', required=True, help='Input JSON file from tiled') +parser.add_argument('--input', required=True, help='Input XML file from tiled') args = parser.parse_args() # Ensure outdir exists @@ -28,5 +27,80 @@ if not os.path.isfile(inputFile): sys.exit(1) with open(inputFile, 'r') as f: - data = json.load(f) - \ No newline at end of file + data = f.read() + +# Parse the XML data +try: + root = ET.fromstring(data) +except ET.ParseError as e: + print(f"Error parsing XML: {e}") + sys.exit(1) + +if root.tag != 'tileset': + print("Error: Input file is not a valid Tiled XML file.") + sys.exit(1) + +if 'tilewidth' not in root.attrib or 'tileheight' not in root.attrib: + print("Error: Missing tilewidth or tileheight attributes in the tileset.") + sys.exit(1) + +if 'tilecount' not in root.attrib or 'columns' not in root.attrib: + print("Error: Missing tilecount or columns attributes in the tileset.") + sys.exit(1) + +tileWidth = int(root.get('tilewidth', 0)) +tileHeight = int(root.get('tileheight', 0)) +tileCount = int(root.get('tilecount', 0)) + 1 # +1 because maps are 1 indexed +columns = int(root.get('columns', 0)) + +tilesById = {} +for tile in root.findall('tile'): + if 'id' not in tile.attrib: + print("Error: Tile element missing 'id' attribute.") + continue + + tileId = int(tile.get('id', -1)) + 1 # +1 because maps are 1 indexed + if tileId < 0 or tileId >= tileCount: + print(f"Error: Invalid tile ID {tileId} in tile element.") + continue + + tilesById[tileId] = tile + +# Create the header file +headerFile = os.path.join(worldDir, "tiledata.h") +with open(headerFile, 'w') as f: + f.write(f"// Generated on {now}\n") + f.write(f"#include \"world/tile.h\"\n\n") + f.write(f"#define TILE_WIDTH {tileWidth}\n") + f.write(f"#define TILE_HEIGHT {tileHeight}\n") + f.write(f"#define TILE_WIDTH_HEIGHT {tileWidth}\n") + f.write(f"#define TILE_COUNT {tileCount}\n") + + f.write("static const tilemetadata_t TILE_META_DATA[TILE_COUNT] = {\n") + for tileId in range(tileCount): + tile = tilesById.get(tileId, None) + if tile is None: + f.write(f" {{ 0 }},\n") + continue + + properties = tile.find('properties') + if properties is None: + f.write(f" {{ 0 }},\n") + continue + + def findProp(name, expectedType=''): + for prop in properties.findall('property'): + if prop.get('name') == name: + if len(expectedType) > 0 and prop.get('type') != expectedType: + continue + return prop.get('value', '') + return None + + f.write(f" {{\n") + + propSolid = findProp('solid', 'int') + if propSolid is not None: + f.write(f" .solidType = {propSolid},\n") + + f.write(f" }},\n") + f.write("};\n\n") \ No newline at end of file