diff --git a/data/map project.tiled-project b/data/map project.tiled-project
index 597da78..bf2dde3 100644
--- a/data/map project.tiled-project
+++ b/data/map project.tiled-project
@@ -22,6 +22,21 @@
"NPC_INTERACT_TYPE_EVENT"
],
"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
}
]
}
diff --git a/data/map project.tiled-session b/data/map project.tiled-session
index 91a7991..d145a65 100644
--- a/data/map project.tiled-session
+++ b/data/map project.tiled-session
@@ -36,7 +36,7 @@
"map.tmj"
],
"project": "map project.tiled-project",
- "property.type": "string",
+ "property.type": "tileSolidType",
"recentFiles": [
"map.tmj",
"minogram.tsx",
diff --git a/data/map.tmj b/data/map.tmj
index 27e0de4..9a48a55 100644
--- a/data/map.tmj
+++ b/data/map.tmj
@@ -437,8 +437,8 @@
"value":"NPC_INTERACT_TYPE_TEXT"
}],
"template":"templates\/NPC.tx",
- "x":6575,
- "y":6837.33333333333
+ "x":6575.625,
+ "y":6816.33333333333
}],
"opacity":1,
"type":"objectgroup",
diff --git a/data/overworld.tsx b/data/overworld.tsx
index eb6d93e..4ddc6bb 100644
--- a/data/overworld.tsx
+++ b/data/overworld.tsx
@@ -13,7 +13,7 @@
-
+
diff --git a/src/dusk/entity/entity.c b/src/dusk/entity/entity.c
index f4eed01..16d3d9b 100644
--- a/src/dusk/entity/entity.c
+++ b/src/dusk/entity/entity.c
@@ -17,29 +17,37 @@ entity_t ENTITIES[ENTITY_COUNT_MAX] = {0};
entitycallback_t ENTITY_CALLBACKS[ENTITY_TYPE_COUNT] = {
{NULL}, // ENTITY_TYPE_NULL
{
- .init = playerNPCInit,
- .update = playerNPCUpdate,
+ .load = playerEntityLoad,
+ .update = playerEntityUpdate,
},
{
- .init = npcInit,
+ .load = npcLoad,
.update = npcUpdate,
.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");
- assertTrue(type != ENTITY_TYPE_NULL, "Entity type NULL");
- assertTrue(type < ENTITY_TYPE_COUNT, "Entity type out of bounds");
+ assertNotNull(source, "Source entity pointer cannot be NULL");
+ assertTrue(source->type != ENTITY_TYPE_NULL, "Source entity type NULL");
+ assertTrue(source->type < ENTITY_TYPE_COUNT, "Source entity type bad");
assertNotNull(
- ENTITY_CALLBACKS[type].init,
+ ENTITY_CALLBACKS[source->type].load,
"Entity type has no i nit callback"
);
memoryZero(entity, sizeof(entity_t));
- entity->type = type;
- ENTITY_CALLBACKS[type].init(entity);
+ entity->type = source->type;
+ 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) {
diff --git a/src/dusk/entity/entity.h b/src/dusk/entity/entity.h
index 28ba757..a9d2ffc 100644
--- a/src/dusk/entity/entity.h
+++ b/src/dusk/entity/entity.h
@@ -45,7 +45,7 @@ typedef struct _entity_t {
} entity_t;
typedef struct {
- void (*init) (entity_t *entity);
+ void (*load) (entity_t *entity, const entity_t *source);
void (*update) (entity_t *entity);
void (*interact)(entity_t *player, entity_t *self);
} entitycallback_t;
@@ -54,12 +54,12 @@ extern entity_t ENTITIES[ENTITY_COUNT_MAX];
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 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.
diff --git a/src/dusk/entity/npc.c b/src/dusk/entity/npc.c
index 88f32a2..ccb8ac0 100644
--- a/src/dusk/entity/npc.c
+++ b/src/dusk/entity/npc.c
@@ -10,8 +10,10 @@
#include "locale/language.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) {
diff --git a/src/dusk/entity/npc.h b/src/dusk/entity/npc.h
index cbc22de..0bb41a7 100644
--- a/src/dusk/entity/npc.h
+++ b/src/dusk/entity/npc.h
@@ -25,8 +25,9 @@ typedef struct {
* Initializes the NPC entity.
*
* @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.
diff --git a/src/dusk/entity/player.c b/src/dusk/entity/player.c
index e79654f..b5c59be 100644
--- a/src/dusk/entity/player.c
+++ b/src/dusk/entity/player.c
@@ -19,21 +19,25 @@ inventory_t PLAYER_INVENTORY;
void playerInit() {
entity_t *ent = &ENTITIES[0];
- entityInit(ent, ENTITY_TYPE_PLAYER);
- ent->id = PLAYER_ENTITY_ID;
-
- ent->x = WORLD_PLAYER_SPAWN_X;
- ent->y = WORLD_PLAYER_SPAWN_Y;
+ entity_t playerEntityData = {
+ .id = PLAYER_ENTITY_ID,
+ .type = ENTITY_TYPE_PLAYER,
+ .x = WORLD_PLAYER_SPAWN_X,
+ .y = WORLD_PLAYER_SPAWN_Y,
+ };
+ entityLoad(ent, &playerEntityData);
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(source, "Source entity pointer cannot be NULL");
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");
assertTrue(entity->type == ENTITY_TYPE_PLAYER, "Entity type must be PLAYER");
diff --git a/src/dusk/entity/player.h b/src/dusk/entity/player.h
index b416bf4..2f30ced 100644
--- a/src/dusk/entity/player.h
+++ b/src/dusk/entity/player.h
@@ -32,15 +32,16 @@ extern inventory_t PLAYER_INVENTORY;
void playerInit(void);
/**
- * Initializes the player entity.
+ * Loads the player entity.
*
* @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.
*
* @param entity The entity to update.
*/
-void playerNPCUpdate(entity_t *entity);
\ No newline at end of file
+void playerEntityUpdate(entity_t *entity);
\ No newline at end of file
diff --git a/src/dusk/world/chunk.c b/src/dusk/world/chunk.c
index 4bf7e6b..47abf71 100644
--- a/src/dusk/world/chunk.c
+++ b/src/dusk/world/chunk.c
@@ -222,7 +222,7 @@ void chunkLoad(chunk_t *chunk, const uint16_t x, const uint16_t y) {
);
// Load chunk entities
- const chunkentity_t *data;
+ const entity_t *data;
entity_t *entity;
data = chunkData->entities;
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++;
};
- // Initialize this entity.
- entityInit(entity, data->type);
- 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
+ // Load this entity.
+ entityLoad(entity, data);
data++;
}
}
diff --git a/src/dusk/world/chunkdata.h b/src/dusk/world/chunkdata.h
index 42b054c..ecd2c31 100644
--- a/src/dusk/world/chunkdata.h
+++ b/src/dusk/world/chunkdata.h
@@ -9,15 +9,8 @@
#include "chunk.h"
#include "entity/entity.h"
-typedef struct {
- uint32_t id;
- entitytype_t type;
- uint8_t x, y;
- entitydir_t dir;
-} chunkentity_t;
-
typedef struct {
uint8_t layerBase[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;
\ No newline at end of file
diff --git a/tools/mapcompile/entityParser.py b/tools/mapcompile/entityParser.py
index 9124811..749fa9c 100644
--- a/tools/mapcompile/entityParser.py
+++ b/tools/mapcompile/entityParser.py
@@ -1,11 +1,12 @@
from constants import TILE_WIDTH_HEIGHT, ENTITY_TYPE_MAP
+from helper import floatToFixed248
def parseEntity(obj, chunkData):
if 'type' in obj and obj['type'] not in ENTITY_TYPE_MAP:
return None
- obj['localX'] = round(obj['x'] - (chunkData['topLeftTileX'] * TILE_WIDTH_HEIGHT))
- obj['localY'] = round(obj['y'] - (chunkData['topLeftTileY'] * TILE_WIDTH_HEIGHT))
+ obj['localX'] = obj['x'] - (chunkData['topLeftTileX'] * TILE_WIDTH_HEIGHT)
+ obj['localY'] = obj['y'] - (chunkData['topLeftTileY'] * TILE_WIDTH_HEIGHT)
obj['dir'] = 'ENTITY_DIR_SOUTH'
obj['type'] = 'ENTITY_TYPE_NPC'
diff --git a/tools/mapcompile/helper.py b/tools/mapcompile/helper.py
index dcffc6a..be93631 100644
--- a/tools/mapcompile/helper.py
+++ b/tools/mapcompile/helper.py
@@ -2,4 +2,4 @@ def floatToFixed248(value):
# Converts a float to the fixed248_t used internally.
high24 = int(value) & 0xFFFFFF
low8 = int((value * 256.0 - high24) * 256.0) & 0xFF
- return (high24 << 8) | low8
\ No newline at end of file
+ return f'((fixed248_t){(high24 << 8) | low8})'
\ No newline at end of file
diff --git a/tools/mapcompile/mapParser.py b/tools/mapcompile/mapParser.py
index 069b86f..d074d78 100644
--- a/tools/mapcompile/mapParser.py
+++ b/tools/mapcompile/mapParser.py
@@ -121,6 +121,10 @@ def parseMap(data):
print(f"Error: Object in object layer does not contain 'x' or 'y' key.")
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['y'] -= mapData['inputMapLowestY'] * TILE_WIDTH_HEIGHT
diff --git a/tools/mapcompile/mapcompile.py b/tools/mapcompile/mapcompile.py
index 87f98b2..c6817f2 100644
--- a/tools/mapcompile/mapcompile.py
+++ b/tools/mapcompile/mapcompile.py
@@ -83,9 +83,12 @@ for chunkY in range(mapData['mapHeightInRealChunks']):
f.write(" {\n")
f.write(f" .id = {entity['id']},\n")
f.write(f" .type = {entity['type']},\n")
- f.write(f" .x = {entity['localX']},\n")
- f.write(f" .y = {entity['localY']},\n")
- f.write(f" .dir = {entity['dir']},\n")
+ f.write(f" .x = {floatToFixed248(entity['x'])},\n")
+ f.write(f" .y = {floatToFixed248(entity['y'])},\n")
+
+ if 'dir' in entity:
+ f.write(f" .dir = {entity['dir']},\n")
+
f.write(" },\n")
f.write(f" }},\n")
diff --git a/tools/tilecompile/tilecompile.py b/tools/tilecompile/tilecompile.py
index e614210..01270ed 100644
--- a/tools/tilecompile/tilecompile.py
+++ b/tools/tilecompile/tilecompile.py
@@ -91,14 +91,17 @@ with open(headerFile, 'w') as f:
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
+ if len(expectedType) > 0:
+ 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 None
f.write(f" {{\n")
- propSolid = findProp('solid', 'int')
+ propSolid = findProp('solidType', 'tileSolidType')
if propSolid is not None:
f.write(f" .solidType = {propSolid},\n")