mirror of
https://github.com/zhenyan121/Cubed.git
synced 2026-08-09 02:07:04 +08:00
feat(creatures): animate creature walk cycles
Add a Gait component synchronized over the network and procedural animation for model nodes. Load animation parameters from assets/model/creature/pig/animation.json and apply leg swing, body bob, and head motion based on gait. Refactor Gait into its own header for reuse.
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
#include "Cubed/gameplay/ecs/entity.hpp"
|
||||
#include "Cubed/gameplay/gait.hpp"
|
||||
#include "glm/ext/vector_float3.hpp"
|
||||
#include "world/entity.pb.h"
|
||||
|
||||
@@ -13,7 +14,7 @@ public:
|
||||
enum class Command { CREATE, DESTORY, UPDATE };
|
||||
|
||||
ClientEntityManager(ClientWorld& world);
|
||||
void update();
|
||||
void update(float dt);
|
||||
void init();
|
||||
|
||||
void receive_entity_create(S2CEntityCreate& msg);
|
||||
@@ -36,6 +37,7 @@ private:
|
||||
EntityID id;
|
||||
glm::vec3 pos;
|
||||
glm::vec3 direction;
|
||||
Gait gait;
|
||||
};
|
||||
|
||||
using EntityMap = tbb::concurrent_hash_map<EntityID, entt::entity>;
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
#include "Cubed/gameplay/ecs/animation.hpp"
|
||||
#include "Cubed/gameplay/ecs/identity.hpp"
|
||||
#include "Cubed/gameplay/ecs/transform.hpp"
|
||||
#include "Cubed/gameplay/player.hpp"
|
||||
namespace Cubed {
|
||||
|
||||
struct ClientPlayer {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "Cubed/gameplay/player.hpp"
|
||||
#include "Cubed/gameplay/gait.hpp"
|
||||
namespace Cubed {
|
||||
|
||||
struct WalkPose {
|
||||
|
||||
21
include/Cubed/gameplay/gait.hpp
Normal file
21
include/Cubed/gameplay/gait.hpp
Normal file
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
|
||||
namespace Cubed {
|
||||
enum class Gait { STOP = 0, WALK = 1, RUN = 2 };
|
||||
constexpr int get_gait_id(Gait gait) { return std::to_underlying(gait); }
|
||||
|
||||
inline Gait get_gait_from_id(int id) {
|
||||
switch (id) {
|
||||
case std::to_underlying(Gait::STOP):
|
||||
return Gait::STOP;
|
||||
case std::to_underlying(Gait::WALK):
|
||||
return Gait::WALK;
|
||||
case std::to_underlying(Gait::RUN):
|
||||
return Gait::RUN;
|
||||
default:
|
||||
throw std::runtime_error("Unknown Gait");
|
||||
}
|
||||
}
|
||||
} // namespace Cubed
|
||||
@@ -11,7 +11,6 @@
|
||||
#include "Cubed/gameplay/game_time.hpp"
|
||||
#include "Cubed/gameplay/hitbox.hpp"
|
||||
#include "Cubed/gameplay/item_stack.hpp"
|
||||
#include "Cubed/gameplay/player.hpp"
|
||||
#include "Cubed/input/event.hpp"
|
||||
#include "Cubed/input/input.hpp"
|
||||
|
||||
|
||||
@@ -1,23 +1,7 @@
|
||||
#pragma once
|
||||
#include "glm/ext/vector_float3.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
namespace Cubed {
|
||||
enum class Gait { STOP = 0, WALK = 1, RUN = 2 };
|
||||
constexpr int get_gait_id(Gait gait) { return std::to_underlying(gait); }
|
||||
|
||||
inline Gait get_gait_from_id(int id) {
|
||||
switch (id) {
|
||||
case std::to_underlying(Gait::STOP):
|
||||
return Gait::STOP;
|
||||
case std::to_underlying(Gait::WALK):
|
||||
return Gait::WALK;
|
||||
case std::to_underlying(Gait::RUN):
|
||||
return Gait::RUN;
|
||||
default:
|
||||
throw std::runtime_error("Unknown Gait");
|
||||
}
|
||||
}
|
||||
static constexpr glm::vec3 PLAYER_SIZE{0.6f, 1.8f, 0.6f};
|
||||
} // namespace Cubed
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
#include "Cubed/gameplay/chunk_pos.hpp"
|
||||
#include "Cubed/gameplay/gait.hpp"
|
||||
#include "Cubed/gameplay/game_time.hpp"
|
||||
#include "Cubed/gameplay/player.hpp"
|
||||
|
||||
#include <absl/container/flat_hash_set.h>
|
||||
#include <atomic>
|
||||
|
||||
@@ -41,5 +41,6 @@ private:
|
||||
IDMap m_id_map;
|
||||
NameMap m_name_map;
|
||||
Handle load_model(std::string_view model_name);
|
||||
void load_anim_config(ModelNode& node, const std::string& path);
|
||||
};
|
||||
} // namespace Cubed
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <glm/glm.hpp>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
namespace Cubed {
|
||||
|
||||
struct Mesh {
|
||||
@@ -32,11 +33,47 @@ struct Mesh {
|
||||
(void*)offsetof(Vertex3D, nx));
|
||||
};
|
||||
};
|
||||
struct NodeAnimRule {
|
||||
enum class Role { NONE, LEG, HEAD };
|
||||
std::string node;
|
||||
Role role = Role::NONE;
|
||||
float phase = 0.0f;
|
||||
};
|
||||
|
||||
struct ModelAnimConfig {
|
||||
float walk_speed = 6.0f;
|
||||
float walk_amp = 25.0f;
|
||||
float run_speed = 12.0f;
|
||||
float run_amp = 40.0f;
|
||||
float body_bob = 0.05f;
|
||||
float head_amp = 4.0f;
|
||||
std::vector<NodeAnimRule> nodes;
|
||||
|
||||
const NodeAnimRule* rule_for(std::string_view name) const {
|
||||
for (const auto& r : nodes) {
|
||||
if (r.node == name) {
|
||||
return &r;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool has_role(NodeAnimRule::Role role) const {
|
||||
for (const auto& r : nodes) {
|
||||
if (r.role == role) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
struct ModelNode {
|
||||
std::string name;
|
||||
glm::mat4 transform{1.0f};
|
||||
|
||||
std::vector<Mesh> meshes;
|
||||
std::vector<ModelNode> children;
|
||||
ModelAnimConfig anim;
|
||||
};
|
||||
|
||||
} // namespace Cubed
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "Cubed/gameplay/ecs/animation.hpp"
|
||||
#include "Cubed/gameplay/model.hpp"
|
||||
#include "Cubed/render/model_node.hpp"
|
||||
#include "Cubed/shader.hpp"
|
||||
@@ -12,15 +13,18 @@ class ModelRender {
|
||||
public:
|
||||
ModelRender(Renderer& renderer);
|
||||
void render_model(ModelID id, const glm::vec3& pos, float yaw,
|
||||
Camera& camera);
|
||||
Camera& camera, const WalkPose& pose);
|
||||
|
||||
void shadow_pass(ModelID id, const glm::vec3& pos, float yaw,
|
||||
Camera& camera);
|
||||
Camera& camera, const WalkPose& pose);
|
||||
|
||||
private:
|
||||
Renderer& m_renderer;
|
||||
void render_node(const ModelNode& node, const glm::mat4& parent,
|
||||
const glm::mat4& view, const Shader& shader, bool shadow);
|
||||
const glm::mat4& view, const Shader& shader, bool shadow,
|
||||
const WalkPose& pose, const ModelAnimConfig& cfg);
|
||||
glm::mat4 pose_node(const ModelNode& node, const ModelAnimConfig& cfg,
|
||||
const WalkPose& pose);
|
||||
void render_mesh(const Mesh& mesh, bool shadow);
|
||||
};
|
||||
} // namespace Cubed
|
||||
Reference in New Issue
Block a user