NPC code
This commit is contained in:
1 parent
2e4a7ab467
commit
995e2c8e5b
10 files changed
+923706
-167
No files matched your search
@@ -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
|
||||
Reference in new issue
Block a user