Add idle animation

This commit is contained in:
2023-12-05 11:25:56 +01:00
parent abc8cf2b48
commit 0d137ffb25
14 changed files with 344 additions and 30 deletions

View File

@@ -65,7 +65,7 @@ ecs_entity_t placeBuilding(BzTileMap *map, BuildingType type, BzTile tileX, BzTi
bzTileLayerSetTile(buildingLayer, layerTile, x, y, 1, 1);
buildingTile++;
bzTileMapUpdateCollisions(map, x, y, map->tileWidth, map->tileHeight);
bzTileMapUpdateCollisions(map, x, y, 1, 1);
}
buildingTile += buildingTileset->width - sizeX;
}

View File

@@ -22,8 +22,8 @@ ECS_COMPONENT_DECLARE(AngularVelocity);
ECS_COMPONENT_DECLARE(SteeringOutput);
ECS_COMPONENT_DECLARE(TextureRegion);
ECS_COMPONENT_DECLARE(AnimationType);
ECS_COMPONENT_DECLARE(Animation);
ECS_COMPONENT_DECLARE(AnimationType);
ECS_COMPONENT_DECLARE(Path);
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, TextureRegion);
ECS_COMPONENT_DEFINE(ecs, AnimationType);
ECS_COMPONENT_DEFINE(ecs, Animation);
ECS_COMPONENT_DEFINE(ecs, AnimationType);
ECS_COMPONENT_DEFINE(ecs, Path);
}

View File

@@ -5,6 +5,7 @@
#include <flecs.h>
#include "utils/building_types.h"
#include "utils/entity_types.h"
extern ECS_TAG_DECLARE(TextureTerrain);
extern ECS_TAG_DECLARE(TextureBuildings);
@@ -67,22 +68,19 @@ typedef struct TextureRegion {
} TextureRegion;
extern ECS_COMPONENT_DECLARE(TextureRegion);
typedef enum AnimationType {
ANIMATION_IDLE,
ANIMATION_WALK,
} AnimationType;
extern ECS_COMPONENT_DECLARE(AnimationType);
typedef struct Animation {
TextureRegion firstFrame;
AnimationType currAnimation;
i32 currFrame;
i32 frameCount;
EntityType entityType;
AnimationType animType;
AnimationSequence sequence;
BzTileset *tileset;
i32 curFrame;
f32 frameDuration;
f32 elapsed;
} Animation;
extern ECS_COMPONENT_DECLARE(Animation);
extern ECS_COMPONENT_DECLARE(AnimationType);
#define PATH_DATA_SIZE 8
typedef struct PathData {
Position waypoints[PATH_DATA_SIZE];

View File

@@ -134,6 +134,11 @@ bool init(void *userData) {
.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_TREES2, initTreesLayer);
@@ -142,13 +147,12 @@ bool init(void *userData) {
bzTileMapOverrideObjectGroup(&game->map, OBJECTS_GAME, initGameObjectsLayer);
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, entityUpdateKinematic, EcsOnUpdate, Position, Rotation, Velocity, AngularVelocity, SteeringOutput);
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, renderTerrain, EcsOnUpdate, Position, Size, Rotation, TextureRegion, TextureTerrain);

View File

@@ -40,15 +40,13 @@ bool initEntityObjectsLayer(BzTileMap *map, BzTileObjectGroup *objectGroup) {
ecs_set(ECS, e, SteeringOutput, {});
ecs_set(ECS, e, TextureRegion, {objectTileset->tiles, bzTilesetGetTileRegion(objectTileset, object.gid)});
ecs_set(ECS, e, Animation, {
.firstFrame=(TextureRegion) {
objectTileset->tiles,
bzTilesetGetTileRegion(objectTileset, object.gid + 1)
},
.currAnimation=ANIMATION_IDLE,
.currFrame=0,
.frameCount=4,
.frameDuration=0.20f
.entityType=ENTITY_WORKER,
.tileset = objectTileset,
.curFrame=0,
.frameDuration=0.6f + (i % 10) * 0.05f,
.elapsed=i * 0.1f,
});
ecs_set(ECS, e, AnimationType, {ANIM_IDLE});
}
return true;

View File

@@ -21,7 +21,13 @@ void entitySpatialRemoved(ecs_iter_t *it);
* 0: Game (singleton) for object pool
* 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
@@ -53,6 +59,13 @@ void entityUpdateKinematic(ecs_iter_t *it);
*/
void entityFollowPath(ecs_iter_t *it);
/*
* 0:
* 1: Animation
* 2: TextureRegion
*/
void entityUpdateAnimation(ecs_iter_t *it);
/*
* 0:
*/

View File

@@ -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);
BzObjectPool *pool = game->pools.pathData;
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) {
Game *game = ecs_singleton_get_mut(ECS, Game);
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);
Animation *anim = ecs_field(it, Animation, 1);
TextureRegion *t = ecs_field(it, TextureRegion, 2);
@@ -121,9 +133,11 @@ void updateAnimations(ecs_iter_t *it) {
anim[i].elapsed += dt;
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;
t[i].rec.x = anim[i].firstFrame.rec.x + anim[i].currFrame * t[i].rec.width;
}
}

47
game/utils/entity_types.h Normal file
View 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