diff --git a/game/game_tileset.h b/game/game_tileset.h
index c42056d..2c55330 100644
--- a/game/game_tileset.h
+++ b/game/game_tileset.h
@@ -251,7 +251,7 @@ static AnimationFrame terrainGetAnimationFrame(BzTileID tile, i32 frameIdx) {
case 4868: return ((AnimationFrame []) {{4868, 100}, {4869, 100}, {4870, 100}, {4871, 100}}) [frameIdx];
default:
BZ_ASSERT(0);
- return (AnimationFrame) {0, 0};
+ return (AnimationFrame) {-1, -1.0f};
}
}
@@ -312,4 +312,68 @@ static BuildingType getBuildingSize(BuildingType type, BzTileID *outWidth, BzTil
}
+typedef enum EntityType {
+ ENTITY_WORKER,
+ ENTITY_COUNT,
+ ENTITY_NONE,
+} EntityType;
+
+typedef enum AnimType {
+ ANIM_IDLE,
+ ANIM_WALK,
+ ANIM_HURT,
+ ANIM_DIE,
+ ANIM_COUNT,
+ ANIM_NONE,
+} AnimType;
+
+static bool entityHasAnimation(EntityType entity, AnimType type) {
+ switch (entity) {
+ case ENTITY_WORKER:
+ switch (type) {
+ case ANIM_IDLE:
+ case ANIM_WALK:
+ case ANIM_HURT:
+ case ANIM_DIE:
+ return true;
+ default:
+ return false;
+ }
+ default:
+ return false;
+ }
+}
+
+static AnimationSequence entityGetAnimationSequence(EntityType entity, AnimType type) {
+ switch (entity) {
+ case ENTITY_WORKER:
+ switch (type) {
+ case ANIM_IDLE: return (AnimationSequence) {.startFrame = 27, .frameCount = 2};
+ case ANIM_WALK: return (AnimationSequence) {.startFrame = 29, .frameCount = 4};
+ case ANIM_HURT: return (AnimationSequence) {.startFrame = 32, .frameCount = 3};
+ case ANIM_DIE: return (AnimationSequence) {.startFrame = 32, .frameCount = 6};
+ default: break;
+ }
+ default: break;
+ }
+ BZ_ASSERT(0);
+ return (AnimationSequence) {0, 0};
+}
+
+static AnimationFrame entityGetAnimationFrame(EntityType entity, AnimType type, i32 frameIdx) {
+ switch (entity) {
+ case ENTITY_WORKER:
+ switch (type) {
+ case ANIM_IDLE: return ((AnimationFrame []) {{27, 200}, {28, 200}}) [frameIdx];
+ case ANIM_WALK: return ((AnimationFrame []) {{29, 180}, {30, 180}, {31, 180}, {30, 180}}) [frameIdx];
+ case ANIM_HURT: return ((AnimationFrame []) {{32, 140}, {33, 140}, {34, 140}}) [frameIdx];
+ case ANIM_DIE: return ((AnimationFrame []) {{32, 140}, {33, 140}, {34, 140}, {36, 150}, {35, 130}, {36, 1400}}) [frameIdx];
+ default: break;
+ }
+ default: break;
+ }
+ BZ_ASSERT(0);
+ return (AnimationFrame) {-1, -1.0f};
+}
+
#endif // GAME_TILESET_H
diff --git a/rawAssets/game.tsj b/rawAssets/game.tsj
index 8b44eab..fdc7487 100644
--- a/rawAssets/game.tsj
+++ b/rawAssets/game.tsj
@@ -237,7 +237,8 @@
"name":"entity",
"type":"string",
"value":""
- }]
+ }],
+ "type":"worker"
},
{
"id":28,
@@ -246,7 +247,8 @@
"name":"entity",
"type":"string",
"value":""
- }]
+ }],
+ "type":"worker"
},
{
"animation":[
@@ -277,7 +279,8 @@
"name":"entity",
"type":"string",
"value":""
- }]
+ }],
+ "type":"worker"
},
{
"id":30,
@@ -286,7 +289,116 @@
"name":"entity",
"type":"string",
"value":""
- }]
+ }],
+ "type":"worker"
+ },
+ {
+ "id":31,
+ "properties":[
+ {
+ "name":"entity",
+ "type":"string",
+ "value":""
+ }],
+ "type":"worker"
+ },
+ {
+ "animation":[
+ {
+ "duration":140,
+ "tileid":32
+ },
+ {
+ "duration":140,
+ "tileid":33
+ },
+ {
+ "duration":140,
+ "tileid":34
+ }],
+ "id":32,
+ "properties":[
+ {
+ "name":"animation",
+ "type":"string",
+ "value":"hurt"
+ },
+ {
+ "name":"entity",
+ "type":"string",
+ "value":""
+ }],
+ "type":"worker"
+ },
+ {
+ "id":33,
+ "properties":[
+ {
+ "name":"entity",
+ "type":"string",
+ "value":""
+ }],
+ "type":"worker"
+ },
+ {
+ "id":34,
+ "properties":[
+ {
+ "name":"entity",
+ "type":"string",
+ "value":""
+ }],
+ "type":"worker"
+ },
+ {
+ "animation":[
+ {
+ "duration":140,
+ "tileid":32
+ },
+ {
+ "duration":140,
+ "tileid":33
+ },
+ {
+ "duration":140,
+ "tileid":34
+ },
+ {
+ "duration":150,
+ "tileid":36
+ },
+ {
+ "duration":130,
+ "tileid":35
+ },
+ {
+ "duration":1400,
+ "tileid":36
+ }],
+ "id":35,
+ "properties":[
+ {
+ "name":"animation",
+ "type":"string",
+ "value":"die"
+ },
+ {
+ "name":"entity",
+ "type":"string",
+ "value":""
+ }],
+ "type":"worker"
+ },
+ {
+ "id":36,
+ "properties":[
+ {
+ "name":"entity",
+ "type":"string",
+ "value":""
+ }],
+ "type":"worker"
},
{
"id":256,
diff --git a/rawAssets/game.tsx b/rawAssets/game.tsx
index 299984d..dcfdf2f 100644
--- a/rawAssets/game.tsx
+++ b/rawAssets/game.tsx
@@ -119,7 +119,7 @@
-
+
@@ -129,12 +129,12 @@
-
+
-
+
@@ -146,14 +146,20 @@
-
+
-
+
+
+
+
+
+
+
@@ -161,7 +167,21 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -171,6 +191,11 @@
+
+
+
+
+
diff --git a/scripts/extract_common.py b/scripts/extract_common.py
index 3624cfd..125ffcb 100644
--- a/scripts/extract_common.py
+++ b/scripts/extract_common.py
@@ -115,9 +115,6 @@ class EnumWriter:
def to_enum(self, name):
return f"{self.prefix.upper()}_{name.upper()}"
- def to_anim_enum(self, name):
- return f"ANIM_{name.upper()}"
-
def output_enum(self):
self.writer.enum_list(self.enum_type, self.enums)
@@ -288,8 +285,146 @@ class EnumWriter:
writer.output("default:\n")
writer.indent()
writer.output("BZ_ASSERT(0);\n")
- writer.output("return (AnimationFrame) {0, 0};\n")
+ writer.output("return (AnimationFrame) {-1, -1.0f};\n")
writer.unindent()
writer.block_end()
writer.block_end()
writer.empty_line()
+
+
+class AnimationWriter(EnumWriter):
+ def __init__(self, writer: ExtractFileWriter, class_prefix, anim_prefix, tiles):
+ super().__init__(writer, class_prefix, tiles)
+ self.writer = writer
+ self.anim_prefix = anim_prefix
+ self.anim_type = f"{anim_prefix.capitalize()}Type"
+ self.anim_map = defaultdict(lambda: defaultdict(list))
+ self.animations = []
+ self.all_tiles = tiles
+
+ animations = []
+
+ for tile in self.all_tiles:
+ if 'animation' not in tile:
+ continue
+ if 'properties' not in tile:
+ continue
+ if 'type' not in tile:
+ continue
+
+ enum = self.to_enum(tile['type'])
+ props = tile['properties']
+ anim_type = [prop['value'] for prop in props if prop['name'] == 'animation'][0]
+ anim_type = self.to_anim_enum(anim_type)
+ animations.append(anim_type)
+
+ self.anim_map[enum][anim_type] = tile['animation']
+
+ animations.append(self.to_anim_enum("count"))
+ animations.append(self.to_anim_enum("none"))
+ anim_seen = set()
+ anim_add = anim_seen.add
+ self.animations = [x for x in animations if not (x in anim_seen or anim_add(x))]
+
+ def to_anim_enum(self, name):
+ return f"{self.anim_prefix.upper()}_{name.upper()}"
+
+ def output_anim_enum(self):
+ writer = self.writer
+ writer.enum_list(self.anim_type, self.animations)
+ pass
+
+ def output_has_anim(self, func_name):
+ writer = self.writer
+ writer.output(f"static bool {func_name}({self.enum_type} entity, {self.anim_type} type) ")
+ writer.block_start()
+
+ writer.output("switch (entity) ")
+ writer.block_start()
+ for entity, anims in self.anim_map.items():
+ writer.output(f"case {entity}:\n")
+ writer.indent()
+ writer.output("switch (type) ")
+ writer.block_start()
+
+ for anim in anims:
+ writer.output(f"case {anim}:\n")
+ writer.indent()
+ writer.output("return true;\n")
+ writer.unindent()
+ writer.output("default:\n")
+ writer.indent()
+ writer.output("return false;\n")
+ writer.unindent()
+
+ writer.block_end()
+ writer.unindent()
+ writer.output("default:\n")
+ writer.indent()
+ writer.output("return false;\n")
+ writer.unindent()
+
+ writer.block_end()
+ writer.block_end()
+ writer.empty_line()
+
+ def output_anim_sequence(self, func_name):
+ writer = self.writer
+ writer.output(f"static AnimationSequence {func_name}({self.enum_type} entity, {self.anim_type} type) ")
+ writer.block_start()
+
+ writer.output("switch (entity) ")
+ writer.block_start()
+ for entity, animation_types in self.anim_map.items():
+ writer.output(f"case {entity}:\n")
+ writer.indent()
+ writer.output("switch (type) ")
+ writer.block_start()
+ for anim_type in animation_types:
+ anim = self.anim_map[entity][anim_type]
+ num_frames = len(anim)
+ anim_id = anim[0]['tileid']
+ ret = f"(AnimationSequence) {{.startFrame = {anim_id}, .frameCount = {num_frames}}}"
+ writer.output(f"case {anim_type}: return {ret};\n")
+ writer.output("default: break;\n")
+ writer.block_end()
+ writer.unindent()
+ writer.output("default: break;\n")
+ writer.block_end()
+
+ writer.output("BZ_ASSERT(0);\n")
+ writer.output("return (AnimationSequence) {0, 0};\n")
+ writer.block_end()
+ writer.empty_line()
+
+ def output_anim_frame(self, func_name):
+ writer = self.writer
+ writer.output(
+ f"static AnimationFrame {func_name}({self.enum_type} entity, {self.anim_type} type, i32 frameIdx) ")
+ writer.block_start()
+
+ writer.output("switch (entity) ")
+ writer.block_start()
+ for entity, animation_types in self.anim_map.items():
+ writer.output(f"case {entity}:\n")
+ writer.indent()
+ writer.output("switch (type) ")
+ writer.block_start()
+ for anim_type in animation_types:
+ anim = self.anim_map[entity][anim_type]
+ frames = [str(x['tileid']) for x in anim]
+ durations = [str(x['duration']) for x in anim]
+
+ anim_frames = [f"{{{frame}, {duration}}}" for frame, duration in zip(frames, durations)]
+ ret = f"((AnimationFrame []) {{{', '.join(anim_frames)}}}) [frameIdx]"
+ writer.output(f"case {anim_type}: return {ret};\n")
+ writer.output("default: break;\n")
+ writer.block_end()
+ writer.unindent()
+ writer.output("default: break;\n")
+ writer.block_end()
+
+ writer.output("BZ_ASSERT(0);\n")
+ writer.output("return (AnimationFrame) {-1, -1.0f};\n")
+ writer.block_end()
+ writer.empty_line()
diff --git a/scripts/extract_tileset.py b/scripts/extract_tileset.py
index 8a143e3..7e0e52e 100644
--- a/scripts/extract_tileset.py
+++ b/scripts/extract_tileset.py
@@ -52,6 +52,14 @@ building_writer.output_enum_to_str("getBuildingStr")
building_writer.output_enum_tile_size("getBuildingSize")
writer.empty_line()
+anim_writer = AnimationWriter(writer, "entity", "anim", entity_tiles)
+
+anim_writer.output_enum()
+anim_writer.output_anim_enum()
+anim_writer.output_has_anim("entityHasAnimation")
+anim_writer.output_anim_sequence("entityGetAnimationSequence")
+anim_writer.output_anim_frame("entityGetAnimationFrame")
+
writer.header_guard_stop()