Working on battle animation

This commit is contained in:
Vladislav Khorev 2026-04-13 23:19:03 +03:00
parent 422ff1fbe3
commit 493eb5a5d7
13 changed files with 946723 additions and 25 deletions

BIN
resources/w/Zombie_BaseColor.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
resources/w/gg/IMG_20260413_182354_992.png (Stored with Git LFS) Normal file

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

215505
resources/w/zombie_idle001.txt Normal file

File diff suppressed because it is too large Load Diff

View File

@ -25,8 +25,9 @@ void Character::setTarget(const Eigen::Vector3f& target,
}
AnimationState Character::resolveActiveState() const {
if (animations.count(currentState)) return currentState;
return AnimationState::IDLE;
return AnimationState::STAND;
}
void Character::update(int64_t deltaMs) {
@ -46,9 +47,17 @@ void Character::update(int64_t deltaMs) {
position += dir * moveAmount;
}
targetFacingAngle = atan2(dir.x(), -dir.z());
if (battle_state == 0 && currentState == AnimationState::STAND)
{
currentState = AnimationState::WALK;
}
} else {
currentState = AnimationState::IDLE;
if (battle_state == 0 &&
currentState == AnimationState::WALK
)
{
currentState = AnimationState::STAND;
}
if (onArrivedCallback) {
auto cb = std::move(onArrivedCallback);
onArrivedCallback = nullptr;
@ -67,17 +76,66 @@ void Character::update(int64_t deltaMs) {
facingAngle += (angleDiff > 0.f ? rotStep : -rotStep);
}
// Advance active animation frame
AnimationState animState = resolveActiveState();
auto it = animations.find(animState);
if (battle_state == 1)
{
if (currentState == AnimationState::STAND || currentState == AnimationState::WALK) {
currentState = AnimationState::STAND_TO_ACTION;
resetAnim = true;
}
if (attack == 1 && currentState == AnimationState::ACTION_IDLE)
{
currentState = AnimationState::ACTION_ATTACK;
resetAnim = true;
}
}
else
{
if (currentState == AnimationState::STAND_TO_ACTION
|| currentState == AnimationState::ACTION_IDLE
|| currentState == AnimationState::ACTION_ATTACK
) {
currentState = AnimationState::ACTION_TO_STAND;
resetAnim = true;
}
}
auto it = animations.find(currentState);
if (it == animations.end()) return;
auto& anim = it->second;
if (resetAnim)
{
resetAnim = false;
anim.currentFrame = 0;
}
anim.currentFrame += static_cast<float>(deltaMs) / 24.f;
//std::cout << "Current animation frame: " << anim.currentFrame << " / " << anim.totalFrames << " -- " << anim.lastFrame << std::endl;
if (static_cast<int>(anim.currentFrame) >= anim.totalFrames-1) {
int frms = anim.model.animations[0].keyFrames[anim.model.animations[0].keyFrames.size() - 1].frame;
if (static_cast<int>(anim.currentFrame) >= frms) {
anim.currentFrame = anim.model.startingFrame;
if (currentState == AnimationState::STAND_TO_ACTION)
{
currentState = AnimationState::ACTION_IDLE;
resetAnim = true;
}
if (currentState == AnimationState::ACTION_TO_STAND)
{
currentState = AnimationState::STAND;
resetAnim = true;
}
if (currentState == AnimationState::ACTION_ATTACK)
{
currentState = AnimationState::ACTION_IDLE;
resetAnim = true;
attack = 0;
}
}
if (static_cast<int>(anim.currentFrame) != anim.lastFrame) {
anim.model.Interpolate(static_cast<int>(anim.currentFrame));
anim.lastFrame = static_cast<int>(anim.currentFrame);

View File

@ -12,8 +12,12 @@
namespace ZL {
enum class AnimationState {
IDLE = 0,
WALK = 1
STAND = 0,
WALK = 1,
STAND_TO_ACTION = 2,
ACTION_ATTACK = 3,
ACTION_IDLE = 4,
ACTION_TO_STAND = 5
};
class Character {
@ -47,6 +51,11 @@ public:
std::string npcName;
bool giftReceived = false;
int battle_state = 0;
bool resetAnim = false;
int attack = 0;
AnimationState currentState = AnimationState::STAND;
private:
struct AnimationData {
BoneSystem model;
@ -57,7 +66,6 @@ private:
};
std::map<AnimationState, AnimationData> animations;
AnimationState currentState = AnimationState::IDLE;
std::shared_ptr<Texture> texture;
Eigen::Vector3f walkTarget = Eigen::Vector3f(0.f, 0.f, 0.f);

View File

@ -154,19 +154,26 @@ namespace ZL
// Load interactive objects
interactiveObjects = GameObjectLoader::loadAndCreateInteractiveObjects("resources/config2/gameobjects.json", renderer, CONST_ZIP_FILE);
auto violaTexture = std::make_shared<Texture>(CreateTextureDataFromPng("resources/viola.png", CONST_ZIP_FILE));
auto violaTexture = std::make_shared<Texture>(CreateTextureDataFromPng("resources/w/gg/IMG_20260413_182354_992.png", CONST_ZIP_FILE));
// Player (Viola)
player = std::make_unique<Character>();
player->loadAnimation(AnimationState::IDLE, "resources/idleviola_uv010.txt", CONST_ZIP_FILE);
player->loadAnimation(AnimationState::WALK, "resources/walkviola_uv010.txt", CONST_ZIP_FILE);
player->loadAnimation(AnimationState::STAND, "resources/w/gg/gg_stand_idle001.txt", CONST_ZIP_FILE);
player->loadAnimation(AnimationState::WALK, "resources/w/gg/gg_walking001.txt", CONST_ZIP_FILE);
player->loadAnimation(AnimationState::STAND_TO_ACTION, "resources/w/gg/gg_stand_to_action002.txt", CONST_ZIP_FILE);
player->loadAnimation(AnimationState::ACTION_ATTACK, "resources/w/gg/gg_action_attack001.txt", CONST_ZIP_FILE);
player->loadAnimation(AnimationState::ACTION_IDLE, "resources/w/gg/gg_action_idle001.txt", CONST_ZIP_FILE);
player->loadAnimation(AnimationState::ACTION_TO_STAND, "resources/w/gg/gg_action_to_stand001.txt", CONST_ZIP_FILE);
player->setTexture(violaTexture);
player->walkSpeed = 3.0f;
player->rotationSpeed = 8.0f;
player->modelScale = 0.12f;
player->modelCorrectionRotation =
Eigen::Quaternionf(Eigen::AngleAxisf(-M_PI * 0.5f, Eigen::Vector3f::UnitX())) *
Eigen::Quaternionf(Eigen::AngleAxisf(M_PI, Eigen::Vector3f::UnitZ()));
player->modelScale = 1.f;
player->modelCorrectionRotation = Eigen::Quaternionf(Eigen::AngleAxisf(M_PI, Eigen::Vector3f::UnitY()));
//Eigen::Quaternionf::Identity();
/*Eigen::Quaternionf(Eigen::AngleAxisf(-M_PI * 0.5f, Eigen::Vector3f::UnitX())) * */
/*Eigen::Quaternionf(Eigen::AngleAxisf(M_PI, Eigen::Vector3f::UnitZ()));*/
std::cout << "Load resurces step 9" << std::endl;
@ -178,9 +185,9 @@ namespace ZL
auto defaultTexture = std::make_shared<Texture>(CreateTextureDataFromPng("resources/w/default_skin001.png", CONST_ZIP_FILE));
auto npc01 = std::make_unique<Character>();
npc01->loadAnimation(AnimationState::IDLE, "resources/w/default_idle002.txt", CONST_ZIP_FILE);
npc01->loadAnimation(AnimationState::STAND, "resources/w/default_idle002.txt", CONST_ZIP_FILE);
npc01->loadAnimation(AnimationState::WALK, "resources/w/default_walk001.txt", CONST_ZIP_FILE);
//npc01->loadAnimation(AnimationState::IDLE, "resources/idleviola_uv010.txt", CONST_ZIP_FILE);
//npc01->loadAnimation(AnimationState::STAND, "resources/idleviola_uv010.txt", CONST_ZIP_FILE);
//npc01->loadAnimation(AnimationState::WALK, "resources/walkviola_uv010.txt", CONST_ZIP_FILE);
npc01->setTexture(defaultTexture);
npc01->walkSpeed = 1.5f;
@ -198,9 +205,9 @@ namespace ZL
std::cout << "Load resurces step 11" << std::endl;
auto npc02 = std::make_unique<Character>();
npc02->loadAnimation(AnimationState::IDLE, "resources/w/default_float001.txt", CONST_ZIP_FILE);
//npc02->loadAnimation(AnimationState::IDLE, "resources/w/float_attack003.txt", CONST_ZIP_FILE);
//npc02->loadAnimation(AnimationState::IDLE, "resources/idleviola_uv010.txt", CONST_ZIP_FILE);
npc02->loadAnimation(AnimationState::STAND, "resources/w/default_float001.txt", CONST_ZIP_FILE);
//npc02->loadAnimation(AnimationState::STAND, "resources/w/float_attack003.txt", CONST_ZIP_FILE);
//npc02->loadAnimation(AnimationState::STAND, "resources/idleviola_uv010.txt", CONST_ZIP_FILE);
npc02->setTexture(ghostTexture);
npc02->walkSpeed = 1.5f;
npc02->rotationSpeed = 8.0f;
@ -669,8 +676,12 @@ namespace ZL
float t = -camPos.y() / rayDir.y();
Eigen::Vector3f hit = camPos + rayDir * t;
std::cout << "[CLICK] Clicked on ground at: (" << hit.x() << ", " << hit.z() << ")" << std::endl;
if (player->currentState == AnimationState::STAND || player->currentState == AnimationState::WALK)
{
player->setTarget(Eigen::Vector3f(hit.x(), 0.f, hit.z()));
}
}
else {
std::cout << "[CLICK] No valid target found" << std::endl;
}
@ -739,6 +750,23 @@ namespace ZL
dialogueSystem.startDialogue("test_cutscene_dialogue");
break;
case SDLK_p:
if (player->battle_state == 0)
{
player->battle_state = 1;
}
else
{
player->battle_state = 0;
}
break;
case SDLK_l:
if (player->attack == 0)
{
player->attack = 1;
}
break;
case SDLK_RETURN:
default:

View File

@ -331,7 +331,7 @@ namespace ZL {
// Load animations
try {
npc->loadAnimation(AnimationState::IDLE, npcData.animationIdlePath, zipPath);
npc->loadAnimation(AnimationState::STAND, npcData.animationIdlePath, zipPath);
std::cout << " Loaded IDLE animation: " << npcData.animationIdlePath << std::endl;
}
catch (const std::exception& e) {