Prepping map stuff

This commit is contained in:
2025-11-11 12:25:46 -06:00
parent 26bfb912f1
commit 5adf8a0773
16 changed files with 249 additions and 175 deletions

View File

@@ -3,4 +3,4 @@
# This software is released under the MIT License.
# https://opensource.org/licenses/MIT
add_asset(MAP untitled.tmx)
add_asset(MAP map.json)

6
assets/map/map.json Normal file
View File

@@ -0,0 +1,6 @@
{
"tiles": [
1, 1, 1,
1, 1, 1
]
}

View File

@@ -1,28 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<map version="1.10" tiledversion="1.11.2" orientation="orthogonal" renderorder="right-down" width="30" height="20" tilewidth="16" tileheight="16" infinite="0" nextlayerid="2" nextobjectid="1">
<tileset firstgid="1" source="../tileset/prarie.tsx"/>
<layer id="1" name="Tile Layer 1" width="30" height="20">
<data encoding="csv">
2,3,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
9,10,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
16,17,18,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
</data>
</layer>
</map>

View File

@@ -9,6 +9,7 @@
#include "type/assetpaletteimage.h"
#include "type/assetalphaimage.h"
#include "type/assetlanguage.h"
#include "type/assetmap.h"
#include <zip.h>
typedef enum {
@@ -17,6 +18,7 @@ typedef enum {
ASSET_TYPE_PALETTE_IMAGE,
ASSET_TYPE_ALPHA_IMAGE,
ASSET_TYPE_LANGUAGE,
ASSET_TYPE_MAP,
ASSET_TYPE_COUNT,
} assettype_t;
@@ -64,5 +66,12 @@ static const assettypedef_t ASSET_TYPE_DEFINITIONS[ASSET_TYPE_COUNT] = {
.header = "DLF",
.loadStrategy = ASSET_LOAD_STRAT_CUSTOM,
.custom = assetLanguageHandler
},
[ASSET_TYPE_MAP] = {
.header = "DMF",
.loadStrategy = ASSET_LOAD_STRAT_ENTIRE,
.dataSize = sizeof(assetmap_t),
.entire = assetMapLoad
}
};

View File

@@ -9,4 +9,5 @@ target_sources(${DUSK_TARGET_NAME}
assetalphaimage.c
assetpaletteimage.c
assetlanguage.c
assetmap.c
)

33
src/asset/type/assetmap.c Normal file
View File

@@ -0,0 +1,33 @@
/**
* Copyright (c) 2025 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "asset/asset.h"
#include "assert/assert.h"
#include "util/memory.h"
errorret_t assetMapLoad(void *data, void *output) {
assertNotNull(data, "Data cannot be NULL");
assertNotNull(output, "Output cannot be NULL");
assetmap_t *mapData = (assetmap_t *)data;
assetmapmodel_t *mesh = (assetmapmodel_t *)output;
memoryCopy(
mesh,
&mapData->models[0],
sizeof(assetmapmodel_t)
);
meshInit(
&mesh->mesh,
MESH_PRIMITIVE_TRIANGLES,
mesh->vertexCount,
mesh->vertices
);
errorOk();
}

35
src/asset/type/assetmap.h Normal file
View File

@@ -0,0 +1,35 @@
/**
* Copyright (c) 2025 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "error/error.h"
#include "rpg/world/map.h"
#include "display/mesh/mesh.h"
typedef struct {
uint32_t vertexCount;
meshvertex_t vertices[36];
mesh_t mesh;
} assetmapmodel_t;
#pragma pack(push, 1)
typedef struct {
uint32_t tileCount;
uint8_t modelCount;
tile_t tiles[CHUNK_TILE_COUNT];
assetmapmodel_t models[1];
} assetmap_t;
#pragma pack(pop)
/**
* Loads a map asset from the given data pointer into the output map structure.
*
* @param data Pointer to the raw assetmap_t data.
* @param output Pointer to the map_t to load the map into.
* @return An error code.
*/
errorret_t assetMapLoad(void *data, void *output);

View File

@@ -81,9 +81,11 @@ void entityWalk(entity_t *entity, const entitydir_t direction) {
// Check one level down for walkable tile (stairs down)
worldpos_t belowPos = newPos;
belowPos.z -= 1;
tile = mapGetTile(belowPos);
tile_t belowTile = mapGetTile(belowPos);
if(tile != TILE_NULL) newPos.z -= 1;
if(belowTile == TILE_STAIRS_UP) {
tile = TILE_STAIRS_DOWN;// Mark current as stairs down
}
}
// Tile walkable?
@@ -98,11 +100,19 @@ void entityWalk(entity_t *entity, const entitydir_t direction) {
return;// Blocked
} while(++other, other < &ENTITIES[ENTITY_COUNT]);
entity->lastPosition = entity->position;
entity->position = newPos;
entity->animation = ENTITY_ANIM_WALK;
entity->animTime = ENTITY_ANIM_WALK_DURATION;// TODO: Running vs walking
// We are comitting, we can run effects here.
if(tile == TILE_STAIRS_DOWN) {
// Moving down a level
entity->position.z -= 1;
} else if(tile == TILE_STAIRS_UP) {
// Moving up a level
entity->position.z += 1;
}
}
entity_t * entityGetAt(const worldpos_t position) {

View File

@@ -23,6 +23,7 @@ typedef struct entity_s {
// Movement
entitydir_t direction;
worldpos_t position;
worldpos_t lastPosition;
entityanim_t animation;
float_t animTime;

View File

@@ -128,12 +128,25 @@ void mapChunkLoad(chunk_t* chunk) {
memoryZero(chunk->tiles, sizeof(tile_t) * CHUNK_TILE_COUNT);
// 3x3 test walkable area
for(int y = 0; y <= 3; y++) {
for(int x = 0; x <= 3; x++) {
chunktileindex_t x, y, z;
z = 0;
for(y = 0; y <= 3; y++) {
for(x = 0; x <= 3; x++) {
chunktileindex_t tileIndex = (y * CHUNK_WIDTH) + x;
chunk->tiles[tileIndex] = TILE_WALKABLE;
}
}
x = 3, y = 3;
chunk->tiles[(z * CHUNK_WIDTH * CHUNK_HEIGHT) + (y * CHUNK_WIDTH) + x] = TILE_STAIRS_UP;
// x = 3, y = 2, z = 1;
// chunk->tiles[(z * CHUNK_WIDTH * CHUNK_HEIGHT) + (y * CHUNK_WIDTH) + x] = TILE_WALKABLE;
// x = 2, y = 2, z = 1;
// chunk->tiles[(z * CHUNK_WIDTH * CHUNK_HEIGHT) + (y * CHUNK_WIDTH) + x] = TILE_WALKABLE;
// x = 4, y = 2, z = 1;
// chunk->tiles[(z * CHUNK_WIDTH * CHUNK_HEIGHT) + (y * CHUNK_WIDTH) + x] = TILE_WALKABLE;
}
chunkindex_t mapGetChunkIndexAt(const chunkpos_t position) {

View File

@@ -8,5 +8,9 @@
#include "tile.h"
bool_t tileIsWalkable(const tile_t tile) {
return tile == TILE_WALKABLE;
return (
tile == TILE_WALKABLE ||
tile == TILE_STAIRS_UP ||
tile == TILE_STAIRS_DOWN
);
}

View File

@@ -13,6 +13,8 @@ typedef uint8_t tile_t;
#define TILE_NULL 0
#define TILE_WALKABLE 1
#define TILE_STAIRS_UP 2
#define TILE_STAIRS_DOWN 3
/**
* Returns whether or not the given tile is walkable.

View File

@@ -21,7 +21,7 @@
typedef int16_t worldunit_t;
typedef int16_t chunkunit_t;
typedef int16_t chunkindex_t;
typedef uint8_t chunktileindex_t;
typedef uint32_t chunktileindex_t;
typedef int32_t worldunits_t;
typedef int32_t chunkunits_t;

View File

@@ -9,6 +9,7 @@
#include "scene/scenedata.h"
#include "display/spritebatch.h"
#include "assert/assert.h"
#include "asset/asset.h"
#include "rpg/entity/entity.h"
#include "rpg/world/map.h"
#include "display/screen.h"
@@ -16,6 +17,7 @@
#include "util/memory.h"
#define TILE_SIZE 16
assetmapmodel_t mesh;
errorret_t sceneMapInit(scenedata_t *data) {
// Init the camera.
@@ -34,6 +36,8 @@ errorret_t sceneMapInit(scenedata_t *data) {
);
data->sceneMap.camera.lookatPixelPerfect.pixelsPerUnit = 1.0f;
errorChain(assetLoad("map/map.dmf", &mesh));
errorOk();
}
@@ -61,15 +65,18 @@ void sceneMapEntityGetPosition(const entity_t *entity, vec3 outPosition) {
float_t animPercentage = entity->animTime / ENTITY_ANIM_WALK_DURATION;
// Get facing rel, we know we moved from the inverse direction.
worldunits_t x, y;
entityDirGetRelative(entity->direction, &x, &y);
x = -x, y = -y;
// Add tile size times percentage to posMin/max
vec3 offset = {
x * TILE_SIZE * animPercentage,
y * TILE_SIZE * animPercentage,
0.0f
(
(float_t)entity->position.x - (float_t)entity->lastPosition.x
) * TILE_SIZE * -animPercentage,
(
(float_t)entity->position.y - (float_t)entity->lastPosition.y
) * TILE_SIZE * -animPercentage,
(
(float_t)entity->position.z - (float_t)entity->lastPosition.z
) * TILE_SIZE * -animPercentage
};
glm_vec3_add(outPosition, offset, outPosition);
break;
@@ -107,7 +114,10 @@ void sceneMapRender(scenedata_t *data) {
cameraPushMatrix(&data->sceneMap.camera);
// Render map probably.
sceneMapRenderMap();
// sceneMapRenderMap();
textureBind(NULL);
meshDraw(&mesh.mesh, -1, -1);
// Render ents
entity_t *ent = ENTITIES;
@@ -125,11 +135,10 @@ void sceneMapRenderEntity(entity_t *entity) {
if(entity->type == ENTITY_TYPE_NULL) return;
vec3 posCenter, posMin, posMax;
vec3 halfSize = { TILE_SIZE / 2.0f, TILE_SIZE / 2.0f, TILE_SIZE / 2.0f };
sceneMapEntityGetPosition(entity, posCenter);
glm_vec3_sub(posCenter, halfSize, posMin);
glm_vec3_add(posCenter, halfSize, posMax);
vec3 posMin, posMax;
vec3 size = { TILE_SIZE, TILE_SIZE, TILE_SIZE };
sceneMapEntityGetPosition(entity, posMin);
glm_vec3_add(posMin, size, posMax);
// TEST: Change color depending on dir.
color_t testColor;
@@ -167,11 +176,6 @@ void sceneMapRenderMap() {
min[1] = chunk->position.y * CHUNK_HEIGHT * TILE_SIZE;
min[2] = chunk->position.z * CHUNK_DEPTH * TILE_SIZE;
// center tile
min[0] -= TILE_SIZE / 2.0f;
min[1] -= TILE_SIZE / 2.0f;
min[2] -= TILE_SIZE / 2.0f;
max[0] = min[0] + (CHUNK_WIDTH * TILE_SIZE);
max[1] = min[1] + (CHUNK_HEIGHT * TILE_SIZE);
max[2] = min[2];
@@ -195,4 +199,5 @@ void sceneMapRenderMap() {
}
void sceneMapDispose(scenedata_t *data) {
meshDispose(&mesh.mesh);
}

View File

@@ -18,7 +18,7 @@ bool_t UI_DEBUG_DRAW = true;
void uiDebugRender(const tileset_t *tileset, texture_t *texture) {
if(!UI_DEBUG_DRAW) return;
char_t buffer[96];
char_t buffer[128];
color_t color;
int32_t w, h, hOffset = 0;
@@ -64,6 +64,7 @@ void uiDebugRender(const tileset_t *tileset, texture_t *texture) {
);
hOffset += h;
// Player position
entity_t *player = NULL;
for(uint8_t i = 0; i < ENTITY_COUNT; i++) {
@@ -77,9 +78,10 @@ void uiDebugRender(const tileset_t *tileset, texture_t *texture) {
snprintf(
buffer,
sizeof(buffer),
"%d,%d/%d/%d",
"%d,%d,%d/%d/%d",
player->position.x,
player->position.y,
player->position.z,
(int32_t)player->direction,
(int32_t)player->animation
);
@@ -87,7 +89,7 @@ void uiDebugRender(const tileset_t *tileset, texture_t *texture) {
uiTextMeasure(buffer, tileset, &w, &h);
uiTextDraw(
SCREEN.width - w, hOffset,
buffer, COLOR_WHITE, tileset, texture
buffer, COLOR_GREEN, tileset, texture
);
hOffset += h;

View File

@@ -1,143 +1,124 @@
import struct
import sys
import os
import json
from args import args
from xml.etree import ElementTree as ET
from processtileset import processTileset
from assetcache import assetCache, assetGetCache
from assethelpers import getAssetRelativePath
CHUNK_WIDTH = 16
CHUNK_HEIGHT = 16
CHUNK_DEPTH = 32
CHUNK_TILE_COUNT = CHUNK_WIDTH * CHUNK_HEIGHT * CHUNK_DEPTH
TILE_SIZE = 16.0
def createQuadForTile(model, tileIndex, x=0, y=0, z=0):
# Only append vertices if z == 0
if z != 0:
return
# Determine color for checkerboard pattern
color = (255,255,255) if (x + y) % 2 == 0 else (0,0,0)
# Use TILE_SIZE for positions
px = x * TILE_SIZE
py = y * TILE_SIZE
pz = z * TILE_SIZE
quad_vertices = [
{'position': (px, py, pz), 'color': color, 'uv': (0,0)}, # 0,0
{'position': (px + TILE_SIZE, py, pz), 'color': color, 'uv': (1,0)}, # 1,0
{'position': (px + TILE_SIZE, py + TILE_SIZE, pz), 'color': color, 'uv': (1,1)}, # 1,1
{'position': (px, py, pz), 'color': color, 'uv': (0,0)}, # 0,0 (repeat)
{'position': (px + TILE_SIZE, py + TILE_SIZE, pz), 'color': color, 'uv': (1,1)}, # 1,1 (repeat)
{'position': (px, py + TILE_SIZE, pz), 'color': color, 'uv': (0,1)} # 0,1
]
base = len(model['vertices'])
quad_indices = [base, base+1, base+2, base+3, base+4, base+5]
model['vertices'].extend(quad_vertices)
model['indices'].extend(quad_indices)
model['vertexCount'] = len(model['vertices'])
model['indexCount'] = len(model['indices'])
def processMap(asset):
cache = assetGetCache(asset['path'])
if cache is not None:
return cache
# Load the TMX file
tree = ET.parse(asset['path'])
root = tree.getroot()
# Read input file as JSON
with open(asset['path'], 'r') as f:
inData = json.load(f)
# Root needs to be "map" element.
if root.tag != 'map':
print(f"Error: TMX file {asset['path']} does not have a <map> root element")
sys.exit(1)
tileIndexes = inData['tiles']
# Root needs to be orientation="orthogonal"
if 'orientation' not in root.attrib or root.attrib['orientation'] != 'orthogonal':
print(f"Error: TMX file {asset['path']} does not have orientation='orthogonal'")
sys.exit(1)
# Create output object 'map' with default tile indexes and models array
map = {
'tiles': [0] * CHUNK_TILE_COUNT,
'models': []
}
# Extract width, height, tilewidth, tileheight attributes
if 'width' not in root.attrib or 'height' not in root.attrib or 'tilewidth' not in root.attrib or 'tileheight' not in root.attrib:
print(f"Error: TMX file {asset['path']} is missing required attributes (width, height, tilewidth, tileheight)")
sys.exit(1)
# Create a simple 3D model object
model = {
'vertices': [],
'indices': [],
'vertexCount': 0,
'indexCount': 0
}
mapWidth = int(root.attrib['width'])
mapHeight = int(root.attrib['height'])
tileWidth = int(root.attrib['tilewidth'])
tileHeight = int(root.attrib['tileheight'])
# Append the model to map.models
map['models'].append(model)
# Find all tileset elements
tilesets = []
for tilesetElement in root.findall('tileset'):
# Tileset must have a source attribute
if 'source' not in tilesetElement.attrib:
print(f"Error: <tileset> element in {asset['path']} is missing a source attribute")
sys.exit(1)
# Must have a firstgid attribute
if 'firstgid' not in tilesetElement.attrib:
print(f"Error: <tileset> element in {asset['path']} is missing a firstgid attribute")
sys.exit(1)
for i, tile in enumerate(tileIndexes):
# Calculate x, y, z from i
x = i % CHUNK_WIDTH
y = (i // CHUNK_WIDTH) % CHUNK_HEIGHT
z = i // (CHUNK_WIDTH * CHUNK_HEIGHT)
createQuadForTile(model, tile, x, y, z)
firstGid = int(tilesetElement.attrib['firstgid'])
source = tilesetElement.attrib['source']
# Generate binary buffer for efficient output
buffer = bytearray()
buffer.extend(b'DMF')# Header
buffer.extend(len(map['tiles']).to_bytes(4, 'little')) # Number of tiles
buffer.extend(len(map['models']).to_bytes(1, 'little')) # Number of models
# Get source path relative to the tmx file's working directory.
# Needs normalizing also since ".." is often used.
source = os.path.normpath(os.path.join(os.path.dirname(asset['path']), source))
tileset = processTileset({ 'path': source, 'type': 'tileset', 'options': {} })
# Buffer tile data as array of uint8_t
for tileIndex in map['tiles']:
buffer.append(tileIndex.to_bytes(1, 'little')[0])
tilesets.append({
'firstGid': firstGid,
'source': source,
'tileset': tileset
})
# Sort tilesets by firstGid, highest first
tilesets.sort(key=lambda x: x['firstGid'], reverse=True)
# Layer types
# objectLayers = [] # Not implemented
tileLayers = []
for layerElement in root.findall('layer'):
# Assume tile layer for now
# Must have id, name, width, height attributes
if 'id' not in layerElement.attrib or 'name' not in layerElement.attrib or 'width' not in layerElement.attrib or 'height' not in layerElement.attrib:
print(f"Error: <layer> element in {asset['path']} is missing required attributes (id, name, width, height)")
sys.exit(1)
id = int(layerElement.attrib['id'])
name = layerElement.attrib['name']
width = int(layerElement.attrib['width'])
height = int(layerElement.attrib['height'])
# Need exactly one data element
dataElements = layerElement.findall('data')
if len(dataElements) != 1:
print(f"Error: <layer> element in {asset['path']} must have exactly one <data> child element")
sys.exit(1)
# Get text, remove whitespace, split by comman and convert to int
dataElement = dataElements[0]
if dataElement.attrib.get('encoding', '') != 'csv':
print(f"Error: <data> element in {asset['path']} must have encoding='csv'")
sys.exit(1)
dataText = dataElement.text.strip()
data = [int(gid) for gid in dataText.split(',') if gid.strip().isdigit()]
# Should be exactly width * height entries
if len(data) != width * height:
print(f"Error: <data> element in {asset['path']} has {len(data)} entries but expected {width * height} (width * height)")
sys.exit(1)
tileLayers.append({
'id': id,
'name': name,
'width': width,
'height': height,
'data': data,
})
# Now we have our layers all parsed out.
data = bytearray()
data += b'DRM' # Dusk RPG Map
data += mapWidth.to_bytes(4, 'little') # Map width in tiles
data += mapHeight.to_bytes(4, 'little') # Map height in tiles
data += len(tilesets).to_bytes(4, 'little') # Number of tilesets
data += len(tileLayers).to_bytes(4, 'little') # Number of layers
# For each layer...
for layer in tileLayers:
for gid in layer['data']:
data += gid.to_bytes(4, 'little') # Tileset index
# For each tileset
for tileset in tilesets:
data += tileset['firstGid'].to_bytes(4, 'little') # First GID
data += tileset['tileset']['tilesetIndex'].to_bytes(4, 'little') # Tileset index
# For each model
for model in map['models']:
# Write vertex count and index count
buffer.extend(model['vertexCount'].to_bytes(4, 'little'))
# buffer.extend(model['indexCount'].to_bytes(4, 'little'))
# For each vertex
for vertex in model['vertices']:
# This is not tightly packed in memory.
# R G B A U V X Y Z
# Color is 4 bytes (RGBA)
# Rest is floats
r, g, b = vertex['color']
a = 255
buffer.extend(r.to_bytes(1, 'little'))
buffer.extend(g.to_bytes(1, 'little'))
buffer.extend(b.to_bytes(1, 'little'))
buffer.extend(a.to_bytes(1, 'little'))
u, v = vertex['uv']
buffer.extend(bytearray(struct.pack('<f', u)))
buffer.extend(bytearray(struct.pack('<f', v)))
x, y, z = vertex['position']
buffer.extend(bytearray(struct.pack('<f', x)))
buffer.extend(bytearray(struct.pack('<f', y)))
buffer.extend(bytearray(struct.pack('<f', z)))
# Write out map file
relative = getAssetRelativePath(asset['path'])
fileNameWithoutExt = os.path.splitext(os.path.basename(asset['path']))[0]
outputFileRelative = os.path.join(os.path.dirname(relative), f"{fileNameWithoutExt}.drm")
outputFileRelative = os.path.join(os.path.dirname(relative), f"{fileNameWithoutExt}.dmf")
outputFilePath = os.path.join(args.output_assets, outputFileRelative)
os.makedirs(os.path.dirname(outputFilePath), exist_ok=True)
with open(outputFilePath, "wb") as f:
f.write(data)
f.write(buffer)
outMap = {
'mapPath': outputFileRelative,
'files': [ outputFilePath ],
'width': mapWidth,
'height': mapHeight,
'map': map
}
return assetCache(asset['path'], outMap)