Moved a bit more code out of mapcompile

This commit is contained in:
2025-06-23 16:00:38 -05:00
parent be5e972b32
commit 39ac4b9fb9
5 changed files with 292 additions and 288 deletions

View File

@ -4,8 +4,8 @@ from datetime import datetime
import math
from helper import floatToFixed248
from inputParser import parseInputFile
from layerParser import parseLayers
from entityParse import parseEntities
from mapParser import parseMap
from chunkParser import chunkGetLocalTileX, chunkGetLocalTileY, chunkGetTileIndex, chunkGetOutputTileIndex, parseChunk
from constants import CHUNK_WIDTH, CHUNK_HEIGHT, TILE_WIDTH_HEIGHT, ENTITY_TYPE_MAP, CHUNK_TILE_COUNT
# Check if the script is run with the correct arguments
@ -31,128 +31,19 @@ now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
# Read the input JSON file
data = parseInputFile(args.input)
layers = parseLayers(data)
entityData = parseEntities(layers)
mapData = parseMap(data)
# For each output chunk.
worldWidth = 0
worldHeight = 0
chunksDone = set()
for chunkY in range(layers['mapHeightInRealChunks']):
for chunkX in range(layers['mapWidthInRealChunks']):
# Top left X/Y based on real chunk size
topLeftTileX = chunkX * CHUNK_WIDTH
topLeftTileY = chunkY * CHUNK_HEIGHT
# Top left coordinates based on input layer size
inputTopLeftTileX = math.floor(float(topLeftTileX) / float(layers['inputLayerWidthInTiles'])) * layers['inputLayerWidthInTiles']
inputTopLeftTileY = math.floor(float(topLeftTileY) / float(layers['inputLayerHeightInTiles'])) * layers['inputLayerHeightInTiles']
# Get the layers for this chunk.
chunkLayers = []
for layer in layers['tileLayers']:
foundChunk = None
if 'chunks' not in layer or not isinstance(layer['chunks'], list):
print(f"Error: Layer '{layer['name']}' does not contain 'chunks' key or it is not a list.")
sys.exit(1)
for chunk in layer['chunks']:
if 'x' not in chunk or 'y' not in chunk:
print(f"Error: Chunk in layer '{layer['name']}' does not contain 'x' or 'y' key.")
sys.exit(1)
# Check if this chunk is within the bounds of the top left tile.
if chunk['x'] != inputTopLeftTileX or chunk['y'] != inputTopLeftTileY:
continue
foundChunk = chunk
break
if foundChunk is None:
chunkLayers.append(None)
continue
# Is layer empty?
layerEmpty = True
for tile in foundChunk['data']:
if tile == 0:
continue
layerEmpty = False
break
if layerEmpty:
chunkLayers.append(None)
else:
chunkLayers.append(foundChunk)
# Now we have a chunkLayers list with the found chunks for each layer.
if all(chunk is None for chunk in chunkLayers) or len(chunkLayers) == 0:
for chunkY in range(mapData['mapHeightInRealChunks']):
for chunkX in range(mapData['mapWidthInRealChunks']):
chunkData = parseChunk(chunkX, chunkY, mapData)
if chunkData is None:
continue
entities = []
for ob in layers['objectLayer']['objects']:
if 'x' not in ob or 'y' not in ob:
print(f"Error: Object in object layer does not contain 'x' or 'y' key.")
sys.exit(1)
# Is this object within the chunk?
if ob['x'] < topLeftTileX * TILE_WIDTH_HEIGHT:
continue
if ob['x'] >= (topLeftTileX + CHUNK_WIDTH) * TILE_WIDTH_HEIGHT:
continue
if ob['y'] < topLeftTileY * TILE_WIDTH_HEIGHT:
continue
if ob['y'] >= (topLeftTileY + CHUNK_HEIGHT) * TILE_WIDTH_HEIGHT:
continue
entities.append(ob)
# Shorthand functions
def getInputLocalTileX(absoluteTileX):
return absoluteTileX % layers['inputLayerWidthInTiles']
def getInputLocalTileY(absoluteTileY):
return absoluteTileY % layers['inputLayerHeightInTiles']
def getInputTileIndex(localX, localY):
absoluteTileX = topLeftTileX + localX
absoluteTileY = topLeftTileY + localY
inputLocalTileX = getInputLocalTileX(absoluteTileX)
inputLocalTileY = getInputLocalTileY(absoluteTileY)
return inputLocalTileY * layers['inputLayerWidthInTiles'] + inputLocalTileX
def getOutputTileIndex(localX, localY):
return localY * CHUNK_WIDTH + localX
# Determine the layer base.
layerBase = chunkLayers[0]
layerBaseOverlay = None
if len(chunkLayers) > 1:
layerBaseOverlay = chunkLayers[1]
# Determine base layer data.
layerBaseData = []
for y in range(CHUNK_HEIGHT):
for x in range(CHUNK_WIDTH):
inputTileIndex = getInputTileIndex(x, y)
outputTileIndex = getOutputTileIndex(x, y)
layerBaseData.append(layerBase['data'][inputTileIndex])
if len(layerBaseData) != CHUNK_TILE_COUNT:
print(f"Error: Layer base data length {len(layerBaseData)} does not match expected chunk tile count {CHUNK_TILE_COUNT}.")
sys.exit(1)
# Layer base overlay.
layerOverlayData = []
if layerBaseOverlay is not None:
for y in range(CHUNK_HEIGHT):
for x in range(CHUNK_WIDTH):
inputTileIndex = getInputTileIndex(x, y)
outputTileIndex = getOutputTileIndex(x, y)
layerOverlayData.append(layerBaseOverlay['data'][inputTileIndex])
# This is a valid chunk.
worldWidth = max(worldWidth, chunkX + 1)
worldHeight = max(worldHeight, chunkY + 1)
@ -170,27 +61,27 @@ for chunkY in range(layers['mapHeightInRealChunks']):
f.write(f" ")
for x in range(CHUNK_WIDTH):
i = y * CHUNK_WIDTH + x
byte = layerBaseData[i]
byte = chunkData['layerBaseData'][i]
f.write(f"0x{byte:02x}, ")
f.write(f"\n")
f.write(" },\n\n")
f.write(" .layerBaseOverlay = {\n")
if layerBaseOverlay is not None:
if chunkData['layerBaseOverlay'] is not None:
for y in range(CHUNK_HEIGHT):
f.write(f" ")
for x in range(CHUNK_WIDTH):
i = y * CHUNK_WIDTH + x
byte = layerOverlayData[i]
byte = chunkData['layerBaseOverlayData'][i]
f.write(f"0x{byte:02x}, ")
f.write(f"\n")
f.write(" },\n\n")
f.write(f" .entities = {{\n")
for entity in entities:
for entity in chunkData['entities']:
# Entities are center aligned in tiled.
localX = round(entity['x'] - (topLeftTileX * TILE_WIDTH_HEIGHT))
localY = round(entity['y'] - (topLeftTileY * TILE_WIDTH_HEIGHT))
localX = round(entity['x'] - (chunkData['topLeftTileX'] * TILE_WIDTH_HEIGHT))
localY = round(entity['y'] - (chunkData['topLeftTileY'] * TILE_WIDTH_HEIGHT))
if 'type' in entity and entity['type'] not in ENTITY_TYPE_MAP:
continue
@ -231,7 +122,7 @@ with open(headerPath, 'w') as f:
f.write("NULL, ")
f.write("\n")
f.write("};\n\n")
f.write(f"#define WORLD_PLAYER_SPAWN_X ((fixed248_t){floatToFixed248(entityData['playerSpawnX'])})\n")
f.write(f"#define WORLD_PLAYER_SPAWN_Y ((fixed248_t){floatToFixed248(entityData['playerSpawnY'])})\n")
f.write(f"#define WORLD_PLAYER_SPAWN_X ((fixed248_t){floatToFixed248(mapData['playerSpawnX'])})\n")
f.write(f"#define WORLD_PLAYER_SPAWN_Y ((fixed248_t){floatToFixed248(mapData['playerSpawnY'])})\n")
print(f"chunks.h generated at: {headerPath}")