Update parsers to use more real C data.

This commit is contained in:
2025-06-23 22:23:18 -05:00
parent 22af9d1507
commit 24eab84f4f
17 changed files with 85 additions and 57 deletions

View File

@ -22,6 +22,21 @@
"NPC_INTERACT_TYPE_EVENT" "NPC_INTERACT_TYPE_EVENT"
], ],
"valuesAsFlags": false "valuesAsFlags": false
},
{
"id": 2,
"name": "tileSolidType",
"storageType": "string",
"type": "enum",
"values": [
"TILE_SOLID_NONE",
"TILE_SOLID_FULL",
"TILE_SOLID_TRIANGLE_TOP_RIGHT",
"TILE_SOLID_TRIANGLE_TOP_LEFT",
"TILE_SOLID_TRIANGLE_BOTTOM_RIGHT",
"TILE_SOLID_TRIANGLE_BOTTOM_LEFT"
],
"valuesAsFlags": false
} }
] ]
} }

View File

@ -36,7 +36,7 @@
"map.tmj" "map.tmj"
], ],
"project": "map project.tiled-project", "project": "map project.tiled-project",
"property.type": "string", "property.type": "tileSolidType",
"recentFiles": [ "recentFiles": [
"map.tmj", "map.tmj",
"minogram.tsx", "minogram.tsx",

View File

@ -437,8 +437,8 @@
"value":"NPC_INTERACT_TYPE_TEXT" "value":"NPC_INTERACT_TYPE_TEXT"
}], }],
"template":"templates\/NPC.tx", "template":"templates\/NPC.tx",
"x":6575, "x":6575.625,
"y":6837.33333333333 "y":6816.33333333333
}], }],
"opacity":1, "opacity":1,
"type":"objectgroup", "type":"objectgroup",

View File

@ -13,7 +13,7 @@
</tile> </tile>
<tile id="18"> <tile id="18">
<properties> <properties>
<property name="solid" type="int" value="1"/> <property name="solidType" propertytype="tileSolidType" value="TILE_SOLID_FULL"/>
</properties> </properties>
</tile> </tile>
<tile id="33"> <tile id="33">

View File

@ -17,29 +17,37 @@ entity_t ENTITIES[ENTITY_COUNT_MAX] = {0};
entitycallback_t ENTITY_CALLBACKS[ENTITY_TYPE_COUNT] = { entitycallback_t ENTITY_CALLBACKS[ENTITY_TYPE_COUNT] = {
{NULL}, // ENTITY_TYPE_NULL {NULL}, // ENTITY_TYPE_NULL
{ {
.init = playerNPCInit, .load = playerEntityLoad,
.update = playerNPCUpdate, .update = playerEntityUpdate,
}, },
{ {
.init = npcInit, .load = npcLoad,
.update = npcUpdate, .update = npcUpdate,
.interact = npcInteract, .interact = npcInteract,
}, },
}; };
void entityInit(entity_t *entity, const entitytype_t type) { void entityLoad(entity_t *entity, const entity_t *source) {
assertNotNull(entity, "Entity pointer cannot be NULL"); assertNotNull(entity, "Entity pointer cannot be NULL");
assertTrue(type != ENTITY_TYPE_NULL, "Entity type NULL"); assertNotNull(source, "Source entity pointer cannot be NULL");
assertTrue(type < ENTITY_TYPE_COUNT, "Entity type out of bounds"); assertTrue(source->type != ENTITY_TYPE_NULL, "Source entity type NULL");
assertTrue(source->type < ENTITY_TYPE_COUNT, "Source entity type bad");
assertNotNull( assertNotNull(
ENTITY_CALLBACKS[type].init, ENTITY_CALLBACKS[source->type].load,
"Entity type has no i nit callback" "Entity type has no i nit callback"
); );
memoryZero(entity, sizeof(entity_t)); memoryZero(entity, sizeof(entity_t));
entity->type = type; entity->type = source->type;
ENTITY_CALLBACKS[type].init(entity); entity->x = source->x;
entity->y = source->y;
entity->vx = source->vx;
entity->vy = source->vy;
entity->dir = source->dir;
entity->id = source->id;
ENTITY_CALLBACKS[entity->type].load(entity, source);
} }
void entityUpdate(entity_t *entity) { void entityUpdate(entity_t *entity) {

View File

@ -45,7 +45,7 @@ typedef struct _entity_t {
} entity_t; } entity_t;
typedef struct { typedef struct {
void (*init) (entity_t *entity); void (*load) (entity_t *entity, const entity_t *source);
void (*update) (entity_t *entity); void (*update) (entity_t *entity);
void (*interact)(entity_t *player, entity_t *self); void (*interact)(entity_t *player, entity_t *self);
} entitycallback_t; } entitycallback_t;
@ -54,12 +54,12 @@ extern entity_t ENTITIES[ENTITY_COUNT_MAX];
extern entitycallback_t ENTITY_CALLBACKS[ENTITY_TYPE_COUNT]; extern entitycallback_t ENTITY_CALLBACKS[ENTITY_TYPE_COUNT];
/** /**
* Initializes an entity with the given type. * Loads an entity from the generated entity data.
* *
* @param entity Pointer to the entity to initialize. * @param entity Pointer to the entity to initialize.
* @param type The type of the entity to initialize. * @param source Pointer to the source entity data.
*/ */
void entityInit(entity_t *entity, const entitytype_t type); void entityLoad(entity_t *entity, const entity_t *source);
/** /**
* Updates the entity's state. * Updates the entity's state.

View File

@ -10,8 +10,10 @@
#include "locale/language.h" #include "locale/language.h"
#include "assert/assert.h" #include "assert/assert.h"
void npcInit(entity_t *entity) { void npcLoad(entity_t *entity, const entity_t *source) {
assertNotNull(entity, "Entity pointer cannot be NULL");
assertNotNull(source, "Source entity pointer cannot be NULL");
assertTrue(source->type == ENTITY_TYPE_NPC, "Source entity type must be NPC");
} }
void npcUpdate(entity_t *entity) { void npcUpdate(entity_t *entity) {

View File

@ -25,8 +25,9 @@ typedef struct {
* Initializes the NPC entity. * Initializes the NPC entity.
* *
* @param entity The entity to initialize. * @param entity The entity to initialize.
* @param source The source entity to copy data from.
*/ */
void npcInit(entity_t *entity); void npcLoad(entity_t *entity, const entity_t *source);
/** /**
* Updates the NPC entity. * Updates the NPC entity.

View File

@ -19,21 +19,25 @@ inventory_t PLAYER_INVENTORY;
void playerInit() { void playerInit() {
entity_t *ent = &ENTITIES[0]; entity_t *ent = &ENTITIES[0];
entityInit(ent, ENTITY_TYPE_PLAYER); entity_t playerEntityData = {
ent->id = PLAYER_ENTITY_ID; .id = PLAYER_ENTITY_ID,
.type = ENTITY_TYPE_PLAYER,
ent->x = WORLD_PLAYER_SPAWN_X; .x = WORLD_PLAYER_SPAWN_X,
ent->y = WORLD_PLAYER_SPAWN_Y; .y = WORLD_PLAYER_SPAWN_Y,
};
entityLoad(ent, &playerEntityData);
inventoryInit(&PLAYER_INVENTORY, INVENTORY_SIZE_MAX); inventoryInit(&PLAYER_INVENTORY, INVENTORY_SIZE_MAX);
} }
void playerNPCInit(entity_t *entity) { void playerEntityLoad(entity_t *entity, const entity_t *source) {
assertNotNull(entity, "Entity pointer cannot be NULL"); assertNotNull(entity, "Entity pointer cannot be NULL");
assertNotNull(source, "Source entity pointer cannot be NULL");
assertTrue(entity->type == ENTITY_TYPE_PLAYER, "Entity type must be PLAYER"); assertTrue(entity->type == ENTITY_TYPE_PLAYER, "Entity type must be PLAYER");
assertTrue(source->type == entity->type, "Source/Entity type mismatch");
} }
void playerNPCUpdate(entity_t *entity) { void playerEntityUpdate(entity_t *entity) {
assertNotNull(entity, "Entity pointer cannot be NULL"); assertNotNull(entity, "Entity pointer cannot be NULL");
assertTrue(entity->type == ENTITY_TYPE_PLAYER, "Entity type must be PLAYER"); assertTrue(entity->type == ENTITY_TYPE_PLAYER, "Entity type must be PLAYER");

View File

@ -32,15 +32,16 @@ extern inventory_t PLAYER_INVENTORY;
void playerInit(void); void playerInit(void);
/** /**
* Initializes the player entity. * Loads the player entity.
* *
* @param entity The entity to initialize. * @param entity The entity to initialize.
* @param source The source entity to copy data from.
*/ */
void playerNPCInit(entity_t *entity); void playerEntityLoad(entity_t *entity, const entity_t *source);
/** /**
* Updates the player entity. * Updates the player entity.
* *
* @param entity The entity to update. * @param entity The entity to update.
*/ */
void playerNPCUpdate(entity_t *entity); void playerEntityUpdate(entity_t *entity);

View File

@ -222,7 +222,7 @@ void chunkLoad(chunk_t *chunk, const uint16_t x, const uint16_t y) {
); );
// Load chunk entities // Load chunk entities
const chunkentity_t *data; const entity_t *data;
entity_t *entity; entity_t *entity;
data = chunkData->entities; data = chunkData->entities;
while(data < chunkData->entities + CHUNK_ENTITY_COUNT_MAX) { while(data < chunkData->entities + CHUNK_ENTITY_COUNT_MAX) {
@ -257,15 +257,8 @@ void chunkLoad(chunk_t *chunk, const uint16_t x, const uint16_t y) {
entity++; entity++;
}; };
// Initialize this entity. // Load this entity.
entityInit(entity, data->type); entityLoad(entity, data);
entity->id = data->id;
// Positions are chunk-relative.
entity->x = fx248Fromu32((chunk->x * CHUNK_WIDTH * TILE_WIDTH_HEIGHT) + data->x);
entity->y = fx248Fromu32((chunk->y * CHUNK_HEIGHT * TILE_WIDTH_HEIGHT)+data->y);
// Next entity
data++; data++;
} }
} }

View File

@ -9,15 +9,8 @@
#include "chunk.h" #include "chunk.h"
#include "entity/entity.h" #include "entity/entity.h"
typedef struct {
uint32_t id;
entitytype_t type;
uint8_t x, y;
entitydir_t dir;
} chunkentity_t;
typedef struct { typedef struct {
uint8_t layerBase[CHUNK_TILE_COUNT]; uint8_t layerBase[CHUNK_TILE_COUNT];
uint8_t layerBaseOverlay[CHUNK_TILE_COUNT]; uint8_t layerBaseOverlay[CHUNK_TILE_COUNT];
chunkentity_t entities[CHUNK_ENTITY_COUNT_MAX]; entity_t entities[CHUNK_ENTITY_COUNT_MAX];
} chunkdata_t; } chunkdata_t;

View File

@ -1,11 +1,12 @@
from constants import TILE_WIDTH_HEIGHT, ENTITY_TYPE_MAP from constants import TILE_WIDTH_HEIGHT, ENTITY_TYPE_MAP
from helper import floatToFixed248
def parseEntity(obj, chunkData): def parseEntity(obj, chunkData):
if 'type' in obj and obj['type'] not in ENTITY_TYPE_MAP: if 'type' in obj and obj['type'] not in ENTITY_TYPE_MAP:
return None return None
obj['localX'] = round(obj['x'] - (chunkData['topLeftTileX'] * TILE_WIDTH_HEIGHT)) obj['localX'] = obj['x'] - (chunkData['topLeftTileX'] * TILE_WIDTH_HEIGHT)
obj['localY'] = round(obj['y'] - (chunkData['topLeftTileY'] * TILE_WIDTH_HEIGHT)) obj['localY'] = obj['y'] - (chunkData['topLeftTileY'] * TILE_WIDTH_HEIGHT)
obj['dir'] = 'ENTITY_DIR_SOUTH' obj['dir'] = 'ENTITY_DIR_SOUTH'
obj['type'] = 'ENTITY_TYPE_NPC' obj['type'] = 'ENTITY_TYPE_NPC'

View File

@ -2,4 +2,4 @@ def floatToFixed248(value):
# Converts a float to the fixed248_t used internally. # Converts a float to the fixed248_t used internally.
high24 = int(value) & 0xFFFFFF high24 = int(value) & 0xFFFFFF
low8 = int((value * 256.0 - high24) * 256.0) & 0xFF low8 = int((value * 256.0 - high24) * 256.0) & 0xFF
return (high24 << 8) | low8 return f'((fixed248_t){(high24 << 8) | low8})'

View File

@ -121,6 +121,10 @@ def parseMap(data):
print(f"Error: Object in object layer does not contain 'x' or 'y' key.") print(f"Error: Object in object layer does not contain 'x' or 'y' key.")
sys.exit(1) sys.exit(1)
if 'id' not in ob:
print(f"Error: Object in object layer does not contain 'id' key.")
sys.exit(1)
ob['x'] -= mapData['inputMapLowestX'] * TILE_WIDTH_HEIGHT ob['x'] -= mapData['inputMapLowestX'] * TILE_WIDTH_HEIGHT
ob['y'] -= mapData['inputMapLowestY'] * TILE_WIDTH_HEIGHT ob['y'] -= mapData['inputMapLowestY'] * TILE_WIDTH_HEIGHT

View File

@ -83,9 +83,12 @@ for chunkY in range(mapData['mapHeightInRealChunks']):
f.write(" {\n") f.write(" {\n")
f.write(f" .id = {entity['id']},\n") f.write(f" .id = {entity['id']},\n")
f.write(f" .type = {entity['type']},\n") f.write(f" .type = {entity['type']},\n")
f.write(f" .x = {entity['localX']},\n") f.write(f" .x = {floatToFixed248(entity['x'])},\n")
f.write(f" .y = {entity['localY']},\n") f.write(f" .y = {floatToFixed248(entity['y'])},\n")
f.write(f" .dir = {entity['dir']},\n")
if 'dir' in entity:
f.write(f" .dir = {entity['dir']},\n")
f.write(" },\n") f.write(" },\n")
f.write(f" }},\n") f.write(f" }},\n")

View File

@ -91,14 +91,17 @@ with open(headerFile, 'w') as f:
def findProp(name, expectedType=''): def findProp(name, expectedType=''):
for prop in properties.findall('property'): for prop in properties.findall('property'):
if prop.get('name') == name: if prop.get('name') == name:
if len(expectedType) > 0 and prop.get('type') != expectedType: if len(expectedType) > 0:
continue if 'type' in prop.attrib and prop.get('type') != expectedType:
continue
if 'propertytype' in prop.attrib and prop.get('propertytype') != expectedType:
continue
return prop.get('value', '') return prop.get('value', '')
return None return None
f.write(f" {{\n") f.write(f" {{\n")
propSolid = findProp('solid', 'int') propSolid = findProp('solidType', 'tileSolidType')
if propSolid is not None: if propSolid is not None:
f.write(f" .solidType = {propSolid},\n") f.write(f" .solidType = {propSolid},\n")