Add idle animation
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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];
|
||||
|
||||
10
game/main.c
10
game/main.c
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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:
|
||||
*/
|
||||
|
||||
@@ -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
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
|
||||
Reference in New Issue
Block a user