This commit is contained in:
Vladislav Khorev committed 2026-04-02 21:03:55 +03:00
1 parent 2e4a7ab467
commit 995e2c8e5b
10 files changed
+923706 -167

No files matched your search

+97
View File
@@ -0,0 +1,97 @@
#include "Character.h"
#include <cmath>
namespace ZL {
void Character::loadAnimation(AnimationState state, const std::string& filename, const std::string& zipFile) {
auto& data = animations[state];
data.model.LoadFromFile(filename, zipFile);
if (!data.model.animations.empty() && !data.model.animations[0].keyFrames.empty()) {
data.totalFrames = data.model.animations[0].keyFrames.back().frame + 1;
} else {
data.totalFrames = 1;
}
}
void Character::setTexture(std::shared_ptr<Texture> tex) {
texture = tex;
}
void Character::setTarget(const Eigen::Vector3f& target) {
walkTarget = target;
}
AnimationState Character::resolveActiveState() const {
if (animations.count(currentState)) return currentState;
return AnimationState::IDLE;
}
void Character::update(int64_t deltaMs) {
// Move toward walk target on the XZ plane
Eigen::Vector3f toTarget = walkTarget - position;
toTarget.y() = 0.f;
float dist = toTarget.norm();
if (dist > WALK_THRESHOLD) {
Eigen::Vector3f dir = toTarget / dist;
float moveAmount = walkSpeed * static_cast<float>(deltaMs) / 1000.f;
if (moveAmount >= dist) {
position = walkTarget;
position.y() = 0.f;
} else {
position += dir * moveAmount;
}
targetFacingAngle = atan2(dir.x(), -dir.z());
currentState = AnimationState::WALK;
} else {
currentState = AnimationState::IDLE;
}
// Rotate toward target facing angle at constant angular speed
float angleDiff = targetFacingAngle - facingAngle;
while (angleDiff > static_cast<float>(M_PI)) angleDiff -= 2.f * static_cast<float>(M_PI);
while (angleDiff < -static_cast<float>(M_PI)) angleDiff += 2.f * static_cast<float>(M_PI);
float rotStep = rotationSpeed * static_cast<float>(deltaMs) / 1000.f;
if (std::fabs(angleDiff) <= rotStep) {
facingAngle = targetFacingAngle;
} else {
facingAngle += (angleDiff > 0.f ? rotStep : -rotStep);
}
// Advance active animation frame
AnimationState animState = resolveActiveState();
auto it = animations.find(animState);
if (it == animations.end()) return;
auto& anim = it->second;
anim.currentFrame += static_cast<float>(deltaMs) / 24.f;
if (static_cast<int>(anim.currentFrame) >= anim.totalFrames-1) {
anim.currentFrame = anim.model.startingFrame;
}
if (static_cast<int>(anim.currentFrame) != anim.lastFrame) {
anim.model.Interpolate(static_cast<int>(anim.currentFrame));
anim.lastFrame = static_cast<int>(anim.currentFrame);
}
}
void Character::draw(Renderer& renderer) {
AnimationState drawState = resolveActiveState();
auto it = animations.find(drawState);
if (it == animations.end() || !texture) return;
renderer.PushMatrix();
renderer.TranslateMatrix({ position.x(), position.y(), position.z() });
renderer.RotateMatrix(Eigen::Quaternionf(Eigen::AngleAxisf(-facingAngle, Eigen::Vector3f::UnitY())).toRotationMatrix());
renderer.ScaleMatrix(modelScale);
renderer.RotateMatrix(modelCorrectionRotation.toRotationMatrix());
auto& anim = it->second;
anim.modelMutable.AssignFrom(anim.model.mesh);
anim.modelMutable.RefreshVBO();
glBindTexture(GL_TEXTURE_2D, texture->getTexID());
renderer.DrawVertexRenderStruct(anim.modelMutable);
renderer.PopMatrix();
}
} // namespace ZL