Add idle animation
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -7,5 +7,6 @@ cmake-build-debug/
|
|||||||
cmake-build-release/
|
cmake-build-release/
|
||||||
tiled/PixelDefense.tiled-session
|
tiled/PixelDefense.tiled-session
|
||||||
venv/
|
venv/
|
||||||
|
scripts/__pycache__/
|
||||||
|
|
||||||
imgui.ini
|
imgui.ini
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ add_subdirectory(engine/)
|
|||||||
|
|
||||||
add_executable(PixelDefense
|
add_executable(PixelDefense
|
||||||
game/utils/building_types.h
|
game/utils/building_types.h
|
||||||
|
game/utils/entity_types.h
|
||||||
|
|
||||||
game/buildings.c
|
game/buildings.c
|
||||||
game/buildings.h
|
game/buildings.h
|
||||||
|
|||||||
@@ -49,6 +49,26 @@
|
|||||||
}],
|
}],
|
||||||
"type":"worker"
|
"type":"worker"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id":4,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"animation",
|
||||||
|
"type":"string",
|
||||||
|
"value":"walk_2"
|
||||||
|
}],
|
||||||
|
"type":"worker"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id":5,
|
||||||
|
"properties":[
|
||||||
|
{
|
||||||
|
"name":"animation",
|
||||||
|
"type":"string",
|
||||||
|
"value":"walk_3"
|
||||||
|
}],
|
||||||
|
"type":"worker"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id":64,
|
"id":64,
|
||||||
"type":"axe"
|
"type":"axe"
|
||||||
|
|||||||
@@ -504,5 +504,5 @@ bool bzTileMapHasCollision(BzTileMap *map, i32 x, i32 y) {
|
|||||||
|
|
||||||
void bzTileMapUpdateCollisions(BzTileMap *map, i32 x, i32 y, i32 sizeX, i32 sizeY) {
|
void bzTileMapUpdateCollisions(BzTileMap *map, i32 x, i32 y, i32 sizeX, i32 sizeY) {
|
||||||
if (!map->collisionMap) return;
|
if (!map->collisionMap) return;
|
||||||
updateCollisionMap(map, x, y, sizeX, sizeY);
|
updateCollisionMap(map, x, y, x + sizeX, y + sizeY);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ ecs_entity_t placeBuilding(BzTileMap *map, BuildingType type, BzTile tileX, BzTi
|
|||||||
bzTileLayerSetTile(buildingLayer, layerTile, x, y, 1, 1);
|
bzTileLayerSetTile(buildingLayer, layerTile, x, y, 1, 1);
|
||||||
buildingTile++;
|
buildingTile++;
|
||||||
|
|
||||||
bzTileMapUpdateCollisions(map, x, y, map->tileWidth, map->tileHeight);
|
bzTileMapUpdateCollisions(map, x, y, 1, 1);
|
||||||
}
|
}
|
||||||
buildingTile += buildingTileset->width - sizeX;
|
buildingTile += buildingTileset->width - sizeX;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,8 +22,8 @@ ECS_COMPONENT_DECLARE(AngularVelocity);
|
|||||||
ECS_COMPONENT_DECLARE(SteeringOutput);
|
ECS_COMPONENT_DECLARE(SteeringOutput);
|
||||||
|
|
||||||
ECS_COMPONENT_DECLARE(TextureRegion);
|
ECS_COMPONENT_DECLARE(TextureRegion);
|
||||||
ECS_COMPONENT_DECLARE(AnimationType);
|
|
||||||
ECS_COMPONENT_DECLARE(Animation);
|
ECS_COMPONENT_DECLARE(Animation);
|
||||||
|
ECS_COMPONENT_DECLARE(AnimationType);
|
||||||
ECS_COMPONENT_DECLARE(Path);
|
ECS_COMPONENT_DECLARE(Path);
|
||||||
|
|
||||||
void initComponentIDs(ecs_world_t *ecs) {
|
void initComponentIDs(ecs_world_t *ecs) {
|
||||||
@@ -49,7 +49,7 @@ void initComponentIDs(ecs_world_t *ecs) {
|
|||||||
ECS_COMPONENT_DEFINE(ecs, SteeringOutput);
|
ECS_COMPONENT_DEFINE(ecs, SteeringOutput);
|
||||||
|
|
||||||
ECS_COMPONENT_DEFINE(ecs, TextureRegion);
|
ECS_COMPONENT_DEFINE(ecs, TextureRegion);
|
||||||
ECS_COMPONENT_DEFINE(ecs, AnimationType);
|
|
||||||
ECS_COMPONENT_DEFINE(ecs, Animation);
|
ECS_COMPONENT_DEFINE(ecs, Animation);
|
||||||
|
ECS_COMPONENT_DEFINE(ecs, AnimationType);
|
||||||
ECS_COMPONENT_DEFINE(ecs, Path);
|
ECS_COMPONENT_DEFINE(ecs, Path);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include <flecs.h>
|
#include <flecs.h>
|
||||||
|
|
||||||
#include "utils/building_types.h"
|
#include "utils/building_types.h"
|
||||||
|
#include "utils/entity_types.h"
|
||||||
|
|
||||||
extern ECS_TAG_DECLARE(TextureTerrain);
|
extern ECS_TAG_DECLARE(TextureTerrain);
|
||||||
extern ECS_TAG_DECLARE(TextureBuildings);
|
extern ECS_TAG_DECLARE(TextureBuildings);
|
||||||
@@ -67,22 +68,19 @@ typedef struct TextureRegion {
|
|||||||
} TextureRegion;
|
} TextureRegion;
|
||||||
extern ECS_COMPONENT_DECLARE(TextureRegion);
|
extern ECS_COMPONENT_DECLARE(TextureRegion);
|
||||||
|
|
||||||
typedef enum AnimationType {
|
|
||||||
ANIMATION_IDLE,
|
|
||||||
ANIMATION_WALK,
|
|
||||||
} AnimationType;
|
|
||||||
extern ECS_COMPONENT_DECLARE(AnimationType);
|
|
||||||
|
|
||||||
typedef struct Animation {
|
typedef struct Animation {
|
||||||
TextureRegion firstFrame;
|
EntityType entityType;
|
||||||
AnimationType currAnimation;
|
AnimationType animType;
|
||||||
i32 currFrame;
|
AnimationSequence sequence;
|
||||||
i32 frameCount;
|
BzTileset *tileset;
|
||||||
|
i32 curFrame;
|
||||||
f32 frameDuration;
|
f32 frameDuration;
|
||||||
f32 elapsed;
|
f32 elapsed;
|
||||||
} Animation;
|
} Animation;
|
||||||
extern ECS_COMPONENT_DECLARE(Animation);
|
extern ECS_COMPONENT_DECLARE(Animation);
|
||||||
|
|
||||||
|
extern ECS_COMPONENT_DECLARE(AnimationType);
|
||||||
|
|
||||||
#define PATH_DATA_SIZE 8
|
#define PATH_DATA_SIZE 8
|
||||||
typedef struct PathData {
|
typedef struct PathData {
|
||||||
Position waypoints[PATH_DATA_SIZE];
|
Position waypoints[PATH_DATA_SIZE];
|
||||||
|
|||||||
10
game/main.c
10
game/main.c
@@ -134,6 +134,11 @@ bool init(void *userData) {
|
|||||||
.userDataSize=sizeof(ecs_entity_t)
|
.userDataSize=sizeof(ecs_entity_t)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ECS_OBSERVER(ECS, entitySpatialRemoved, EcsOnRemove, Position, SpatialGridID);
|
||||||
|
ECS_OBSERVER(ECS, entityPathRemoved, EcsOnRemove, Path);
|
||||||
|
|
||||||
|
ECS_OBSERVER(ECS, entitySetAnimationState, EcsOnSet, Animation, AnimationType);
|
||||||
|
|
||||||
bzTileMapOverrideLayer(&game->map, LAYER_TREES, initTreesLayer);
|
bzTileMapOverrideLayer(&game->map, LAYER_TREES, initTreesLayer);
|
||||||
bzTileMapOverrideLayer(&game->map, LAYER_TREES2, initTreesLayer);
|
bzTileMapOverrideLayer(&game->map, LAYER_TREES2, initTreesLayer);
|
||||||
|
|
||||||
@@ -142,13 +147,12 @@ bool init(void *userData) {
|
|||||||
bzTileMapOverrideObjectGroup(&game->map, OBJECTS_GAME, initGameObjectsLayer);
|
bzTileMapOverrideObjectGroup(&game->map, OBJECTS_GAME, initGameObjectsLayer);
|
||||||
bzTileMapOverrideObjectGroup(&game->map, OBJECTS_ENTITIES, initEntityObjectsLayer);
|
bzTileMapOverrideObjectGroup(&game->map, OBJECTS_ENTITIES, initEntityObjectsLayer);
|
||||||
|
|
||||||
ECS_OBSERVER(ECS, entitySpatialRemoved, EcsOnRemove, Position, SpatialGridID);
|
|
||||||
ECS_OBSERVER(ECS, pathRemoved, EcsOnRemove, Path);
|
|
||||||
|
|
||||||
ECS_SYSTEM(ECS, entityUpdateSpatialID, EcsOnUpdate, Position, Size, Velocity, SpatialGridID);
|
ECS_SYSTEM(ECS, entityUpdateSpatialID, EcsOnUpdate, Position, Size, Velocity, SpatialGridID);
|
||||||
ECS_SYSTEM(ECS, entityUpdateKinematic, EcsOnUpdate, Position, Rotation, Velocity, AngularVelocity, SteeringOutput);
|
ECS_SYSTEM(ECS, entityUpdateKinematic, EcsOnUpdate, Position, Rotation, Velocity, AngularVelocity, SteeringOutput);
|
||||||
ECS_SYSTEM(ECS, entityFollowPath, EcsOnUpdate, Position, Rotation, Velocity, AngularVelocity, SteeringOutput, Path);
|
ECS_SYSTEM(ECS, entityFollowPath, EcsOnUpdate, Position, Rotation, Velocity, AngularVelocity, SteeringOutput, Path);
|
||||||
|
|
||||||
|
ECS_SYSTEM(ECS, entityUpdateAnimation, EcsOnUpdate, Animation, TextureRegion);
|
||||||
|
|
||||||
ECS_SYSTEM(ECS, renderDebugPath, EcsOnUpdate, Path);
|
ECS_SYSTEM(ECS, renderDebugPath, EcsOnUpdate, Path);
|
||||||
|
|
||||||
ECS_SYSTEM(ECS, renderTerrain, EcsOnUpdate, Position, Size, Rotation, TextureRegion, TextureTerrain);
|
ECS_SYSTEM(ECS, renderTerrain, EcsOnUpdate, Position, Size, Rotation, TextureRegion, TextureTerrain);
|
||||||
|
|||||||
@@ -40,15 +40,13 @@ bool initEntityObjectsLayer(BzTileMap *map, BzTileObjectGroup *objectGroup) {
|
|||||||
ecs_set(ECS, e, SteeringOutput, {});
|
ecs_set(ECS, e, SteeringOutput, {});
|
||||||
ecs_set(ECS, e, TextureRegion, {objectTileset->tiles, bzTilesetGetTileRegion(objectTileset, object.gid)});
|
ecs_set(ECS, e, TextureRegion, {objectTileset->tiles, bzTilesetGetTileRegion(objectTileset, object.gid)});
|
||||||
ecs_set(ECS, e, Animation, {
|
ecs_set(ECS, e, Animation, {
|
||||||
.firstFrame=(TextureRegion) {
|
.entityType=ENTITY_WORKER,
|
||||||
objectTileset->tiles,
|
.tileset = objectTileset,
|
||||||
bzTilesetGetTileRegion(objectTileset, object.gid + 1)
|
.curFrame=0,
|
||||||
},
|
.frameDuration=0.6f + (i % 10) * 0.05f,
|
||||||
.currAnimation=ANIMATION_IDLE,
|
.elapsed=i * 0.1f,
|
||||||
.currFrame=0,
|
|
||||||
.frameCount=4,
|
|
||||||
.frameDuration=0.20f
|
|
||||||
});
|
});
|
||||||
|
ecs_set(ECS, e, AnimationType, {ANIM_IDLE});
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,13 @@ void entitySpatialRemoved(ecs_iter_t *it);
|
|||||||
* 0: Game (singleton) for object pool
|
* 0: Game (singleton) for object pool
|
||||||
* 1: Path
|
* 1: Path
|
||||||
*/
|
*/
|
||||||
void pathRemoved(ecs_iter_t *it);
|
void entityPathRemoved(ecs_iter_t *it);
|
||||||
|
|
||||||
|
/* Observer (for updating animation state)
|
||||||
|
* 1: Animation
|
||||||
|
* 2: EntityState
|
||||||
|
*/
|
||||||
|
void entitySetAnimationState(ecs_iter_t *it);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 0: Game (singleton) for entity map
|
* 0: Game (singleton) for entity map
|
||||||
@@ -53,6 +59,13 @@ void entityUpdateKinematic(ecs_iter_t *it);
|
|||||||
*/
|
*/
|
||||||
void entityFollowPath(ecs_iter_t *it);
|
void entityFollowPath(ecs_iter_t *it);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 0:
|
||||||
|
* 1: Animation
|
||||||
|
* 2: TextureRegion
|
||||||
|
*/
|
||||||
|
void entityUpdateAnimation(ecs_iter_t *it);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 0:
|
* 0:
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ void entitySpatialRemoved(ecs_iter_t *it) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void pathRemoved(ecs_iter_t *it) {
|
void entityPathRemoved(ecs_iter_t *it) {
|
||||||
Game *game = ecs_singleton_get_mut(ECS, Game);
|
Game *game = ecs_singleton_get_mut(ECS, Game);
|
||||||
BzObjectPool *pool = game->pools.pathData;
|
BzObjectPool *pool = game->pools.pathData;
|
||||||
Path *path = ecs_field(it, Path, 1);
|
Path *path = ecs_field(it, Path, 1);
|
||||||
@@ -34,6 +34,18 @@ void pathRemoved(ecs_iter_t *it) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void entitySetAnimationState(ecs_iter_t *it) {
|
||||||
|
Animation *anim = ecs_field(it, Animation, 1);
|
||||||
|
AnimationType *animType = ecs_field(it, AnimationType , 2);
|
||||||
|
for (i32 i = 0; i < it->count; i++) {
|
||||||
|
EntityType entityType = anim[i].entityType;
|
||||||
|
AnimationType type = animType[i];
|
||||||
|
BZ_ASSERT(entityHasAnimation(entityType, type));
|
||||||
|
anim[i].animType = type;
|
||||||
|
anim[i].sequence = getEntityAnimation(entityType, type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void entityUpdateSpatialID(ecs_iter_t *it) {
|
void entityUpdateSpatialID(ecs_iter_t *it) {
|
||||||
Game *game = ecs_singleton_get_mut(ECS, Game);
|
Game *game = ecs_singleton_get_mut(ECS, Game);
|
||||||
Position *position = ecs_field(it, Position, 1);
|
Position *position = ecs_field(it, Position, 1);
|
||||||
@@ -109,7 +121,7 @@ void entityFollowPath(ecs_iter_t *it) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateAnimations(ecs_iter_t *it) {
|
void entityUpdateAnimation(ecs_iter_t *it) {
|
||||||
Game *game = ecs_singleton_get_mut(ECS, Game);
|
Game *game = ecs_singleton_get_mut(ECS, Game);
|
||||||
Animation *anim = ecs_field(it, Animation, 1);
|
Animation *anim = ecs_field(it, Animation, 1);
|
||||||
TextureRegion *t = ecs_field(it, TextureRegion, 2);
|
TextureRegion *t = ecs_field(it, TextureRegion, 2);
|
||||||
@@ -121,9 +133,11 @@ void updateAnimations(ecs_iter_t *it) {
|
|||||||
anim[i].elapsed += dt;
|
anim[i].elapsed += dt;
|
||||||
if (anim[i].elapsed < anim[i].frameDuration) continue;
|
if (anim[i].elapsed < anim[i].frameDuration) continue;
|
||||||
|
|
||||||
anim[i].currFrame = (anim[i].currFrame + 1) % anim[i].frameCount;
|
anim[i].curFrame = (anim[i].curFrame + 1) % anim[i].sequence.frameCount;
|
||||||
|
|
||||||
|
BzTile tile = anim[i].sequence.startFrame + anim[i].curFrame + anim[i].tileset->startID;
|
||||||
|
t[i].rec = bzTilesetGetTileRegion(anim[i].tileset, tile);
|
||||||
anim[i].elapsed = 0.0f;
|
anim[i].elapsed = 0.0f;
|
||||||
t[i].rec.x = anim[i].firstFrame.rec.x + anim[i].currFrame * t[i].rec.width;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
47
game/utils/entity_types.h
Normal file
47
game/utils/entity_types.h
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
#ifndef ENTITY_TYPES
|
||||||
|
#define ENTITY_TYPES
|
||||||
|
|
||||||
|
#include <breeze.h>
|
||||||
|
|
||||||
|
typedef enum EntityType {
|
||||||
|
ENTITY_WORKER = 0,
|
||||||
|
ENTITY_AXE = 64,
|
||||||
|
} EntityType;
|
||||||
|
|
||||||
|
typedef enum AnimationType {
|
||||||
|
ANIM_WALK,
|
||||||
|
ANIM_IDLE,
|
||||||
|
} AnimationType;
|
||||||
|
|
||||||
|
typedef struct AnimationSequence {
|
||||||
|
i32 startFrame;
|
||||||
|
i32 frameCount;
|
||||||
|
} AnimationSequence;
|
||||||
|
|
||||||
|
static bool entityHasAnimation(EntityType entity, AnimationType anim) {
|
||||||
|
switch (entity) {
|
||||||
|
case ENTITY_WORKER: {
|
||||||
|
switch (anim) {
|
||||||
|
case ANIM_IDLE:
|
||||||
|
case ANIM_WALK:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static AnimationSequence getEntityAnimation(EntityType entity, AnimationType anim) {
|
||||||
|
switch (entity) {
|
||||||
|
case ENTITY_WORKER: {
|
||||||
|
switch (anim) {
|
||||||
|
case ANIM_IDLE: return (AnimationSequence) {0, 2};
|
||||||
|
case ANIM_WALK: return (AnimationSequence) {2, 4};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BZ_ASSERT(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // ENTITY_TYPES
|
||||||
64
scripts/extract_common.py
Normal file
64
scripts/extract_common.py
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
class ExtractFileWriter:
|
||||||
|
indent_width = 4
|
||||||
|
indent_level = 0
|
||||||
|
indention = ""
|
||||||
|
|
||||||
|
def __init__(self, name):
|
||||||
|
self.name = name.upper()
|
||||||
|
|
||||||
|
def indent(self):
|
||||||
|
self.indent_level += self.indent_width
|
||||||
|
self.indention = " " * self.indent_level
|
||||||
|
|
||||||
|
def unindent(self):
|
||||||
|
self.indent_level -= self.indent_width
|
||||||
|
self.indention = " " * self.indent_level
|
||||||
|
|
||||||
|
def header_guard_start(self):
|
||||||
|
print(f"#ifndef {self.name}")
|
||||||
|
print(f"#define {self.name}")
|
||||||
|
print()
|
||||||
|
|
||||||
|
def header_guard_stop(self):
|
||||||
|
print(f"#endif // {self.name}")
|
||||||
|
|
||||||
|
def include(self, header):
|
||||||
|
print(f"#include {header}")
|
||||||
|
|
||||||
|
def enum_start(self, name):
|
||||||
|
print(f"{self.indention}typedef enum {name} {{")
|
||||||
|
self.indent()
|
||||||
|
|
||||||
|
def enum_stop(self, name):
|
||||||
|
self.unindent()
|
||||||
|
print(f"}} {name};")
|
||||||
|
print()
|
||||||
|
|
||||||
|
def enum_list(self, name, enums):
|
||||||
|
self.enum_start(name)
|
||||||
|
for enum in enums:
|
||||||
|
print(f"{self.indention}{enum},")
|
||||||
|
self.enum_stop(name)
|
||||||
|
|
||||||
|
def enum_dict(self, name, enums):
|
||||||
|
self.enum_start(name)
|
||||||
|
for enum, v in enums.items():
|
||||||
|
print(f"{self.indention}{enum} = {v},")
|
||||||
|
self.enum_stop(name)
|
||||||
|
|
||||||
|
def output(self, out):
|
||||||
|
print(f"{self.indention}{out}", end="")
|
||||||
|
|
||||||
|
def output_line(self):
|
||||||
|
print()
|
||||||
|
|
||||||
|
def only_output(self, out):
|
||||||
|
print(out, end="")
|
||||||
|
|
||||||
|
def block_start(self):
|
||||||
|
print(f"{{")
|
||||||
|
self.indent()
|
||||||
|
|
||||||
|
def block_end(self):
|
||||||
|
self.unindent()
|
||||||
|
print(f"{self.indention}}}")
|
||||||
154
scripts/extract_entities.py
Normal file
154
scripts/extract_entities.py
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
"""
|
||||||
|
Utility script that extracts entities tileset with animations
|
||||||
|
"""
|
||||||
|
|
||||||
|
import json
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
from collections import defaultdict
|
||||||
|
from extract_common import *
|
||||||
|
|
||||||
|
raw_entities = defaultdict(list)
|
||||||
|
entities = defaultdict(list)
|
||||||
|
|
||||||
|
content = open("../assets/entities.tsj").read()
|
||||||
|
tiles = json.loads(content)["tiles"]
|
||||||
|
|
||||||
|
for tile in tiles:
|
||||||
|
if "type" not in tile:
|
||||||
|
continue
|
||||||
|
raw_entities[tile["type"]].append(tile)
|
||||||
|
|
||||||
|
entity_enum_prefix = "ENTITY_"
|
||||||
|
animation_enum_prefix = "ANIM_"
|
||||||
|
|
||||||
|
entity_enums = {}
|
||||||
|
animations = set()
|
||||||
|
entity_animations = {}
|
||||||
|
|
||||||
|
|
||||||
|
def entity_enum(type):
|
||||||
|
return f"{entity_enum_prefix}{type.upper()}"
|
||||||
|
|
||||||
|
|
||||||
|
def animation_enum(value):
|
||||||
|
value = value.split("_")[0]
|
||||||
|
return f"{animation_enum_prefix}{value.upper()}"
|
||||||
|
|
||||||
|
|
||||||
|
def simple_entity(entity):
|
||||||
|
type = entity["type"]
|
||||||
|
id = entity["id"]
|
||||||
|
entity_enums[entity_enum(type)] = id
|
||||||
|
|
||||||
|
|
||||||
|
def animated_entity(entity):
|
||||||
|
simple_entity(entity[0])
|
||||||
|
entity_name = entity_enum(entity[0]["type"])
|
||||||
|
cur_animations = defaultdict(list)
|
||||||
|
for frame in entity:
|
||||||
|
assert entity_name == entity_enum(frame["type"])
|
||||||
|
for prop in frame["properties"]:
|
||||||
|
if prop["name"] != "animation":
|
||||||
|
continue
|
||||||
|
animation_name = animation_enum(prop["value"])
|
||||||
|
animations.add(animation_name)
|
||||||
|
cur_animations[animation_name].append(frame["id"])
|
||||||
|
break
|
||||||
|
entity_animations[entity_name] = cur_animations
|
||||||
|
|
||||||
|
|
||||||
|
for k, v in raw_entities.items():
|
||||||
|
num_frames = len(v)
|
||||||
|
if num_frames == 1:
|
||||||
|
simple_entity(v[0])
|
||||||
|
else:
|
||||||
|
animated_entity(v)
|
||||||
|
|
||||||
|
|
||||||
|
writer = ExtractFileWriter("entity_types")
|
||||||
|
writer.header_guard_start()
|
||||||
|
|
||||||
|
writer.include("<breeze.h>")
|
||||||
|
|
||||||
|
writer.output_line()
|
||||||
|
|
||||||
|
# ============================
|
||||||
|
|
||||||
|
writer.enum_dict("EntityType", entity_enums)
|
||||||
|
writer.enum_list("AnimationType", animations)
|
||||||
|
|
||||||
|
# ============================
|
||||||
|
|
||||||
|
writer.output("typedef struct AnimationSequence {\n")
|
||||||
|
writer.indent()
|
||||||
|
writer.output("i32 startFrame;\n")
|
||||||
|
writer.output("i32 frameCount;\n")
|
||||||
|
writer.unindent()
|
||||||
|
writer.output("} AnimationSequence;\n")
|
||||||
|
writer.output_line()
|
||||||
|
|
||||||
|
# ============================
|
||||||
|
|
||||||
|
# ============================
|
||||||
|
|
||||||
|
writer.output("static bool entityHasAnimation(EntityType entity, AnimationType anim) ")
|
||||||
|
writer.block_start()
|
||||||
|
|
||||||
|
writer.output("switch (entity) ")
|
||||||
|
writer.block_start()
|
||||||
|
|
||||||
|
for entity, anims in entity_animations.items():
|
||||||
|
writer.output(f"case {entity}: ")
|
||||||
|
writer.block_start()
|
||||||
|
|
||||||
|
writer.output("switch (anim) ")
|
||||||
|
writer.block_start()
|
||||||
|
for anim in anims:
|
||||||
|
writer.output(f"case {anim}:")
|
||||||
|
writer.output_line()
|
||||||
|
writer.indent()
|
||||||
|
writer.output("return true;\n")
|
||||||
|
writer.unindent()
|
||||||
|
writer.block_end()
|
||||||
|
|
||||||
|
writer.output("break;\n")
|
||||||
|
writer.block_end()
|
||||||
|
|
||||||
|
writer.block_end()
|
||||||
|
|
||||||
|
writer.output("return false;\n")
|
||||||
|
writer.block_end()
|
||||||
|
|
||||||
|
writer.output_line()
|
||||||
|
# ============================
|
||||||
|
|
||||||
|
writer.output("static AnimationSequence getEntityAnimation(EntityType entity, AnimationType anim) ")
|
||||||
|
writer.block_start()
|
||||||
|
writer.output("switch (entity) ")
|
||||||
|
writer.block_start()
|
||||||
|
for entity, anims in entity_animations.items():
|
||||||
|
writer.output(f"case {entity}: ")
|
||||||
|
writer.block_start()
|
||||||
|
|
||||||
|
writer.output("switch (anim) ")
|
||||||
|
writer.block_start()
|
||||||
|
for anim in anims:
|
||||||
|
ids = sorted(anims[anim])
|
||||||
|
for id0, id1 in zip(ids, ids[1:]):
|
||||||
|
assert id1 - id0 == 1
|
||||||
|
writer.output(f"case {anim}: return (AnimationSequence) {{{min(ids)}, {len(ids)}}};")
|
||||||
|
writer.output_line()
|
||||||
|
writer.block_end()
|
||||||
|
|
||||||
|
writer.block_end()
|
||||||
|
writer.block_end()
|
||||||
|
writer.output("BZ_ASSERT(0);\n")
|
||||||
|
writer.block_end()
|
||||||
|
writer.output_line()
|
||||||
|
|
||||||
|
# ============================
|
||||||
|
|
||||||
|
writer.header_guard_stop()
|
||||||
|
|
||||||
Reference in New Issue
Block a user