This commit is contained in:
Vladislav Khorev 2026-04-24 18:40:51 +03:00
parent b4b41e8620
commit 2bb7da2e37
8 changed files with 227397 additions and 37 deletions

BIN
resources/w/gg/new/gg_die001.anim (Stored with Git LFS) Normal file

Binary file not shown.

File diff suppressed because it is too large Load Diff

BIN
resources/w/gg/new/gg_die_idle001.anim (Stored with Git LFS) Normal file

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -6,9 +6,10 @@
namespace ZL { namespace ZL {
const float ATTACK_COOLDOWN_TIME = 3.0f; const float ATTACK_COOLDOWN_TIME = 2.3f;
extern float x; extern float x;
extern float y; extern float y;
const float ATTACK_RANGE = 1.25f;
void Character::loadAnimation(AnimationState state, const std::string& filename, const std::string& zipFile) { void Character::loadAnimation(AnimationState state, const std::string& filename, const std::string& zipFile) {
auto& data = animations[state]; auto& data = animations[state];
@ -131,7 +132,7 @@ void Character::update(int64_t deltaMs) {
battle_state = 0; battle_state = 0;
} }
else if (distToGhost < 10.0f && distToGhost >= 1.f) { else if (distToGhost < 10.0f && distToGhost >= ATTACK_RANGE) {
setTarget(attackTarget->position); setTarget(attackTarget->position);
battle_state = 0; battle_state = 0;
} }
@ -203,6 +204,17 @@ void Character::update(int64_t deltaMs) {
} }
} }
if (hp <= 0)
{
if (currentState != AnimationState::ACTION_TO_DEATH && currentState != AnimationState::DEATH_IDLE)
{
currentState = AnimationState::ACTION_TO_DEATH;
resetAnim = true;
}
}
else
{
if (battle_state == 1) if (battle_state == 1)
{ {
targetFacingAngle = atan2(lookTarget.x() - position.x(), -(lookTarget.z() - position.z())); targetFacingAngle = atan2(lookTarget.x() - position.x(), -(lookTarget.z() - position.z()));
@ -223,11 +235,14 @@ void Character::update(int64_t deltaMs) {
} }
if (attack == 1 && currentState == AnimationState::ACTION_IDLE) if (attack == 1 && currentState == AnimationState::ACTION_IDLE)
{
if (attackTarget != nullptr && attackTarget->hp > 0)
{ {
currentState = AnimationState::ACTION_ATTACK; currentState = AnimationState::ACTION_ATTACK;
resetAnim = true; resetAnim = true;
} }
} }
}
else else
{ {
if (currentState == AnimationState::STAND_TO_ACTION if (currentState == AnimationState::STAND_TO_ACTION
@ -238,6 +253,7 @@ void Character::update(int64_t deltaMs) {
resetAnim = true; resetAnim = true;
} }
} }
}
// Rotate toward target facing angle at constant angular speed // Rotate toward target facing angle at constant angular speed
float angleDiff = targetFacingAngle - facingAngle; float angleDiff = targetFacingAngle - facingAngle;
@ -262,9 +278,14 @@ void Character::update(int64_t deltaMs) {
resetAnim = false; resetAnim = false;
anim.currentFrame = 0; anim.currentFrame = 0;
} }
//19
int prevFrame = anim.currentFrame;
anim.currentFrame += static_cast<float>(deltaMs) / 24.f; anim.currentFrame += static_cast<float>(deltaMs) / 24.f;
/*
//std::cout << "Current animation frame: " << anim.currentFrame << " / " << anim.totalFrames << " -- " << anim.lastFrame << std::endl; if (npcId == "ghost_01x")
{
std::cout << "Current animation frame: " << anim.currentFrame << " / " << anim.totalFrames << " -- " << anim.lastFrame << std::endl;
}*/
if (static_cast<int>(anim.currentFrame) >= 20 && currentState == AnimationState::STAND_TO_ACTION) if (static_cast<int>(anim.currentFrame) >= 20 && currentState == AnimationState::STAND_TO_ACTION)
{ {
@ -283,6 +304,27 @@ void Character::update(int64_t deltaMs) {
showWeapon = false; showWeapon = false;
} }
if (isPlayer)
{
if (prevFrame == 18 && static_cast<int>(anim.currentFrame) != 18 && (currentState == AnimationState::ACTION_ATTACK || currentState == AnimationState::ACTION_ATTACK_2))
{
if (attackTarget != nullptr)
{
attackTarget->applyDamage(10.f);
}
}
}
else
{
if (prevFrame == 49 && static_cast<int>(anim.currentFrame) != 49 && (currentState == AnimationState::ACTION_ATTACK || currentState == AnimationState::ACTION_ATTACK_2))
{
if (attackTarget != nullptr)
{
attackTarget->applyDamage(10.f);
}
}
}
int frms = anim.model.animations[0].keyFrames[anim.model.animations[0].keyFrames.size() - 1].frame; int frms = anim.model.animations[0].keyFrames[anim.model.animations[0].keyFrames.size() - 1].frame;
if (static_cast<int>(anim.currentFrame) >= frms) { if (static_cast<int>(anim.currentFrame) >= frms) {
anim.currentFrame = anim.model.startingFrame; anim.currentFrame = anim.model.startingFrame;
@ -290,20 +332,26 @@ void Character::update(int64_t deltaMs) {
if (currentState == AnimationState::STAND_TO_ACTION) if (currentState == AnimationState::STAND_TO_ACTION)
{ {
currentState = AnimationState::ACTION_IDLE; currentState = AnimationState::ACTION_IDLE;
resetAnim = true; //resetAnim = true;
} }
if (currentState == AnimationState::ACTION_TO_STAND) if (currentState == AnimationState::ACTION_TO_STAND)
{ {
currentState = AnimationState::STAND; currentState = AnimationState::STAND;
resetAnim = true; //resetAnim = true;
} }
if (currentState == AnimationState::ACTION_ATTACK) if (currentState == AnimationState::ACTION_ATTACK)
{ {
currentState = AnimationState::ACTION_IDLE; currentState = AnimationState::ACTION_IDLE;
resetAnim = true; //resetAnim = true;
attack = 0; attack = 0;
} }
if (currentState == AnimationState::ACTION_TO_DEATH)
{
currentState = AnimationState::DEATH_IDLE;
//resetAnim = true;
}
} }
@ -317,6 +365,10 @@ void Character::update(int64_t deltaMs) {
} }
void Character::draw(Renderer& renderer) { void Character::draw(Renderer& renderer) {
if (!isPlayer && hp <= 0)
{
return;
}
if (useGpuSkinning) { if (useGpuSkinning) {
drawGpuSkinning(renderer); drawGpuSkinning(renderer);
return; return;
@ -482,6 +534,10 @@ void Character::drawAttachedWeapon(Renderer& renderer)
// ==================== Shadow depth pass ==================== // ==================== Shadow depth pass ====================
void Character::drawShadowDepth(Renderer& renderer) { void Character::drawShadowDepth(Renderer& renderer) {
if (!isPlayer && hp <= 0)
{
return;
}
if (useGpuSkinning) { if (useGpuSkinning) {
drawShadowDepthGpuSkinning(renderer); drawShadowDepthGpuSkinning(renderer);
} else { } else {
@ -568,6 +624,10 @@ void Character::drawShadowDepthGpuSkinning(Renderer& renderer) {
// ==================== Main pass with shadows ==================== // ==================== Main pass with shadows ====================
void Character::drawWithShadow(Renderer& renderer, const Eigen::Matrix4f& lightFromCamera, GLuint shadowMapTex, const Eigen::Vector3f& lightDirCamera) { void Character::drawWithShadow(Renderer& renderer, const Eigen::Matrix4f& lightFromCamera, GLuint shadowMapTex, const Eigen::Vector3f& lightDirCamera) {
if (!isPlayer && hp <= 0)
{
return;
}
if (useGpuSkinning) { if (useGpuSkinning) {
drawGpuSkinningWithShadow(renderer, lightFromCamera, shadowMapTex, lightDirCamera); drawGpuSkinningWithShadow(renderer, lightFromCamera, shadowMapTex, lightDirCamera);
} else { } else {
@ -695,4 +755,10 @@ void Character::drawGpuSkinningWithShadow(Renderer& renderer, const Eigen::Matri
CheckGlError(__FILE__, __LINE__); CheckGlError(__FILE__, __LINE__);
} }
void Character::applyDamage(float damageAmount)
{
hp = hp - damageAmount;
if (hp < 0) hp = 0;
}
} // namespace ZL } // namespace ZL

View File

@ -20,7 +20,9 @@ enum class AnimationState {
ACTION_ATTACK = 3, ACTION_ATTACK = 3,
ACTION_ATTACK_2 = 4, ACTION_ATTACK_2 = 4,
ACTION_IDLE = 5, ACTION_IDLE = 5,
ACTION_TO_STAND = 6 ACTION_TO_STAND = 6,
ACTION_TO_DEATH = 7,
DEATH_IDLE = 8,
}; };
class Character { class Character {
@ -48,6 +50,9 @@ public:
void drawShadowDepth(Renderer& renderer); void drawShadowDepth(Renderer& renderer);
void drawWithShadow(Renderer& renderer, const Eigen::Matrix4f& lightFromCamera, GLuint shadowMapTex, const Eigen::Vector3f& lightDirCamera); void drawWithShadow(Renderer& renderer, const Eigen::Matrix4f& lightFromCamera, GLuint shadowMapTex, const Eigen::Vector3f& lightDirCamera);
void applyDamage(float damageAmount);
// Public: read by Game for camera tracking and ray-cast origin // Public: read by Game for camera tracking and ray-cast origin
Eigen::Vector3f position = Eigen::Vector3f(0.f, 0.f, 0.f); Eigen::Vector3f position = Eigen::Vector3f(0.f, 0.f, 0.f);
float facingAngle = 0.0f; float facingAngle = 0.0f;
@ -64,6 +69,7 @@ public:
std::string npcId; std::string npcId;
std::string npcName; std::string npcName;
bool giftReceived = false; bool giftReceived = false;
float hp = 100.f;
int battle_state = 0; int battle_state = 0;

View File

@ -516,6 +516,7 @@ namespace ZL
case SDLK_o: case SDLK_o:
y = y + 0.002; y = y + 0.002;
currentLocation->player->hp = 5;
break; break;
case SDLK_k: case SDLK_k:

View File

@ -63,6 +63,9 @@ namespace ZL
player->loadBinaryAnimation(AnimationState::ACTION_ATTACK_2, "resources/w/gg/gg_action_stab001.anim", CONST_ZIP_FILE); player->loadBinaryAnimation(AnimationState::ACTION_ATTACK_2, "resources/w/gg/gg_action_stab001.anim", CONST_ZIP_FILE);
player->loadBinaryAnimation(AnimationState::ACTION_IDLE, "resources/w/gg/gg_action_idle002.anim", CONST_ZIP_FILE); player->loadBinaryAnimation(AnimationState::ACTION_IDLE, "resources/w/gg/gg_action_idle002.anim", CONST_ZIP_FILE);
player->loadBinaryAnimation(AnimationState::ACTION_TO_STAND, "resources/w/gg/new/gg_action_to_stand001.anim", CONST_ZIP_FILE); player->loadBinaryAnimation(AnimationState::ACTION_TO_STAND, "resources/w/gg/new/gg_action_to_stand001.anim", CONST_ZIP_FILE);
player->loadBinaryAnimation(AnimationState::ACTION_TO_DEATH, "resources/w/gg/new/gg_die001.anim", CONST_ZIP_FILE);
player->loadBinaryAnimation(AnimationState::DEATH_IDLE, "resources/w/gg/new/gg_die_idle001.anim", CONST_ZIP_FILE);
player->weaponTexture = std::make_shared<Texture>(CreateTextureDataFromPng("resources/w/white.png", CONST_ZIP_FILE)); player->weaponTexture = std::make_shared<Texture>(CreateTextureDataFromPng("resources/w/white.png", CONST_ZIP_FILE));
@ -106,10 +109,15 @@ namespace ZL
npc02->loadBinaryAnimation(AnimationState::ACTION_ATTACK, "resources/w/float_attack003.anim", CONST_ZIP_FILE); npc02->loadBinaryAnimation(AnimationState::ACTION_ATTACK, "resources/w/float_attack003.anim", CONST_ZIP_FILE);
npc02->loadBinaryAnimation(AnimationState::STAND_TO_ACTION, "resources/w/default_float001_cut.anim", CONST_ZIP_FILE); npc02->loadBinaryAnimation(AnimationState::STAND_TO_ACTION, "resources/w/default_float001_cut.anim", CONST_ZIP_FILE);
npc02->loadBinaryAnimation(AnimationState::ACTION_TO_STAND, "resources/w/default_float001_cut.anim", CONST_ZIP_FILE); npc02->loadBinaryAnimation(AnimationState::ACTION_TO_STAND, "resources/w/default_float001_cut.anim", CONST_ZIP_FILE);
npc02->loadBinaryAnimation(AnimationState::ACTION_TO_DEATH, "resources/w/default_float001_cut.anim", CONST_ZIP_FILE);
npc02->loadBinaryAnimation(AnimationState::DEATH_IDLE, "resources/w/default_float001_cut.anim", CONST_ZIP_FILE);
npc02->npcId = "ghost_01x";
npc02->setTexture(ghostTexture); npc02->setTexture(ghostTexture);
npc02->walkSpeed = 1.5f; npc02->walkSpeed = 1.5f;
npc02->rotationSpeed = 8.0f; npc02->rotationSpeed = 8.0f;
npc02->modelScale = 0.01f; npc02->modelScale = 0.01f;
npc02->hp = 30;
//npc02->modelScale = 0.1f; //npc02->modelScale = 0.1f;
npc02->modelCorrectionRotation = Eigen::Quaternionf(Eigen::AngleAxisf(M_PI, Eigen::Vector3f::UnitY())); npc02->modelCorrectionRotation = Eigen::Quaternionf(Eigen::AngleAxisf(M_PI, Eigen::Vector3f::UnitY()));