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()