import sys from constants import CHUNK_WIDTH, CHUNK_HEIGHT, CHUNK_TILE_COUNT, TILE_WIDTH_HEIGHT import math def parseChunkLayerData(layer, mapData, chunkData): layerData = [] for y in range(CHUNK_HEIGHT): for x in range(CHUNK_WIDTH): inputTileIndex = chunkGetTileIndex(x, y, mapData, chunkData) outputTileIndex = chunkGetOutputTileIndex(x, y) layerData.append(layer['data'][inputTileIndex]) if len(layerData) != CHUNK_TILE_COUNT: print(f"Error: Layer data length {len(layerData)} does not match expected chunk tile count {CHUNK_TILE_COUNT}.") sys.exit(1) return layerData def parseChunk(chunkX, chunkY, mapData): chunkData = { } chunkData['topLeftTileX'] = chunkX * CHUNK_WIDTH chunkData['topLeftTileY'] = chunkY * CHUNK_HEIGHT chunkData['inputTopLeftTileX'] = math.floor( float(chunkData['topLeftTileX']) / float(mapData['inputLayerWidthInTiles']) ) * mapData['inputLayerWidthInTiles'] chunkData['inputTopLeftTileY'] = math.floor( float(chunkData['topLeftTileY']) / float(mapData['inputLayerHeightInTiles']) ) * mapData['inputLayerHeightInTiles'] # Get the data for this chunk out of the map data. chunkData['layers'] = [] for layer in mapData['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'] != chunkData['inputTopLeftTileX'] or chunk['y'] != chunkData['inputTopLeftTileY']: continue foundChunk = chunk break if foundChunk is None: chunkData['layers'].append(None) continue # Is layer empty? layerEmpty = True for tile in foundChunk['data']: if tile == 0: continue layerEmpty = False break if layerEmpty: chunkData['layers'].append(None) else: chunkData['layers'].append(foundChunk) # Any layers for this chunk? if all(chunk is None for chunk in chunkData['layers']): return None if len(chunkData['layers']) == 0: return None # Parse Layer Data chunkData['layerBase'] = chunkData['layers'][0] chunkData['layerBaseOverlay'] = None if len(chunkData['layers']) > 1: chunkData['layerBaseOverlay'] = chunkData['layers'][1] chunkData['layerBaseData'] = parseChunkLayerData(chunkData['layerBase'], mapData, chunkData) if chunkData['layerBaseOverlay'] is not None: chunkData['layerBaseOverlayData'] = parseChunkLayerData(chunkData['layerBaseOverlay'], mapData, chunkData) else: chunkData['layerBaseOverlayData'] = [] # Parse chunk entities. chunkData['entities'] = [] for ob in mapData['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'] < chunkData['topLeftTileX'] * TILE_WIDTH_HEIGHT: continue if ob['x'] >= (chunkData['topLeftTileX'] + CHUNK_WIDTH) * TILE_WIDTH_HEIGHT: continue if ob['y'] < chunkData['topLeftTileY'] * TILE_WIDTH_HEIGHT: continue if ob['y'] >= (chunkData['topLeftTileY'] + CHUNK_HEIGHT) * TILE_WIDTH_HEIGHT: continue chunkData['entities'].append(ob) return chunkData def chunkGetLocalTileX(absoluteTileX, mapData): return absoluteTileX % mapData['inputLayerWidthInTiles'] def chunkGetLocalTileY(absoluteTileY, mapData): return absoluteTileY % mapData['inputLayerHeightInTiles'] def chunkGetTileIndex(localX, localY, mapData, chunkData): absoluteTileX = chunkData['topLeftTileX'] + localX absoluteTileY = chunkData['topLeftTileY'] + localY inputLocalTileX = chunkGetLocalTileX(absoluteTileX, mapData) inputLocalTileY = chunkGetLocalTileY(absoluteTileY, mapData) return inputLocalTileY * mapData['inputLayerWidthInTiles'] + inputLocalTileX def chunkGetOutputTileIndex(localX, localY): return localY * CHUNK_WIDTH + localX