Adjust sword slash effect to accept config values. Add DrawPartialSquishedRotatedDecal to PGE. Performs rotation transform before scale transformation. Add thief animations to animation databases. Setup thief's auto attack ability. Release Build 10053.

This commit is contained in:
sigonasr2 2024-07-16 03:58:33 -05:00
parent 34510e732a
commit 5f40ee8306
16 changed files with 132 additions and 19 deletions

View File

@ -211,6 +211,26 @@ void sig::Animation::InitializeAnimations(){
} }
ANIMATION_DATA["WIZARD_CAST_W"]=pl_wizard_cast_w; ANIMATION_DATA["WIZARD_CAST_W"]=pl_wizard_cast_w;
//Thief animations.
SetupClassWalkIdleAnimations(GFX["nico-thief.png"],"THIEF");
Animate2D::FrameSequence pl_thief_swing_s(0.05f),pl_thief_swing_n(0.05f),pl_thief_swing_e(0.05f),pl_thief_swing_w(0.05f);
for (int i=0;i<4;i++){
pl_thief_swing_s.AddFrame({&GFX["nico-thief.png"],{vi2d{4+i,0}*24,{24,24}}});
}
for (int i=0;i<4;i++){
pl_thief_swing_n.AddFrame({&GFX["nico-thief.png"],{vi2d{4+i,1}*24,{24,24}}});
}
for (int i=0;i<4;i++){
pl_thief_swing_w.AddFrame({&GFX["nico-thief.png"],{vi2d{4+i,2}*24,{24,24}}});
}
for (int i=0;i<4;i++){
pl_thief_swing_e.AddFrame({&GFX["nico-thief.png"],{vi2d{4+i,3}*24,{24,24}}});
}
ANIMATION_DATA["THIEF_SWINGSWORD_N"]=pl_thief_swing_n;
ANIMATION_DATA["THIEF_SWINGSWORD_E"]=pl_thief_swing_e;
ANIMATION_DATA["THIEF_SWINGSWORD_S"]=pl_thief_swing_s;
ANIMATION_DATA["THIEF_SWINGSWORD_W"]=pl_thief_swing_w;
CreateHorizontalAnimationSequence("ground-slam-attack-back.png",5,{64,64},{0.02f,Animate2D::Style::OneShot}); CreateHorizontalAnimationSequence("ground-slam-attack-back.png",5,{64,64},{0.02f,Animate2D::Style::OneShot});
CreateHorizontalAnimationSequence("ground-slam-attack-front.png",5,{64,64},{0.02f,Animate2D::Style::OneShot}); CreateHorizontalAnimationSequence("ground-slam-attack-front.png",5,{64,64},{0.02f,Animate2D::Style::OneShot});
CreateHorizontalAnimationSequence("battlecry_effect.png",5,{84,84},{0.02f,Animate2D::Style::OneShot}); CreateHorizontalAnimationSequence("battlecry_effect.png",5,{84,84},{0.02f,Animate2D::Style::OneShot});

View File

@ -97,10 +97,12 @@ struct PulsatingFire:Effect{
}; };
struct SwordSlash:Effect{ struct SwordSlash:Effect{
SwordSlash(float lifetime,std::string imgFile,vf2d size={1,1},float fadeout=0.0f,vf2d spd={},Pixel col=WHITE,float rotation=0,float rotationSpd=0,bool additiveBlending=false); SwordSlash(float lifetime,std::string imgFile,float damageMult, float swordSweepAngle,vf2d size={1,1},float fadeout=0.0f,vf2d spd={},Pixel col=WHITE,float rotation=0,float rotationSpd=0,bool additiveBlending=false);
bool Update(float fElapsedTime)override; bool Update(float fElapsedTime)override;
private: private:
HitList hitList; HitList hitList;
const float damageMult;
const float swordSweepAngle;
}; };
//This draws effects using screen coordinates instead of world coordinates, useful for applying effects directly on the screen. //This draws effects using screen coordinates instead of world coordinates, useful for applying effects directly on the screen.

View File

@ -1019,8 +1019,7 @@ void Player::SetAnimationBasedOnTargetingDirection(float targetDirection){
auto FacingNorth=[&](){return targetDirection>=-3*PI/4&&targetDirection<-PI/4;}; auto FacingNorth=[&](){return targetDirection>=-3*PI/4&&targetDirection<-PI/4;};
switch(GetClass()){ switch(GetClass()){
case Class::WARRIOR: case Class::WARRIOR:{
case Class::THIEF:{
if(FacingNorth()){ if(FacingNorth()){
UpdateAnimation("WARRIOR_SWINGSWORD_N"); UpdateAnimation("WARRIOR_SWINGSWORD_N");
}else }else
@ -1049,6 +1048,20 @@ void Player::SetAnimationBasedOnTargetingDirection(float targetDirection){
UpdateAnimation("RANGER_SHOOT_E"); UpdateAnimation("RANGER_SHOOT_E");
} }
}break; }break;
case Class::THIEF:{
if(FacingNorth()){
UpdateAnimation("THIEF_SWINGSWORD_N");
}else
if(FacingSouth()){
UpdateAnimation("THIEF_SWINGSWORD_S");
}else
if(FacingWest()){
UpdateAnimation("THIEF_SWINGSWORD_W");
}else
if(FacingEast()){
UpdateAnimation("THIEF_SWINGSWORD_E");
}
}break;
} }
} }

View File

@ -41,12 +41,12 @@ All rights reserved.
INCLUDE_game INCLUDE_game
SwordSlash::SwordSlash(float lifetime, std::string imgFile, vf2d size, float fadeout, vf2d spd, Pixel col, float rotation, float rotationSpd, bool additiveBlending) SwordSlash::SwordSlash(float lifetime, std::string imgFile,float damageMult, float swordSweepAngle,vf2d size, float fadeout, vf2d spd, Pixel col, float rotation, float rotationSpd, bool additiveBlending)
:Effect(game->GetPlayer()->GetPos(),lifetime,imgFile,game->GetPlayer()->OnUpperLevel(),size,fadeout,spd,col,rotation,rotationSpd,additiveBlending){} :damageMult(damageMult),swordSweepAngle(swordSweepAngle),Effect(game->GetPlayer()->GetPos(),lifetime,imgFile,game->GetPlayer()->OnUpperLevel(),size,fadeout,spd,col,rotation,rotationSpd,additiveBlending){}
bool SwordSlash::Update(float fElapsedTime){ bool SwordSlash::Update(float fElapsedTime){
if(lifetime>0){ if(lifetime>0){
game->HurtConeNotHit(game->GetPlayer()->GetPos(),game->GetPlayer()->GetAttackRangeMult()*12.f,rotation,util::degToRad("Warrior.Auto Attack.SwordSlashSweepAngle"_F),game->GetPlayer()->GetAttack(),hitList,game->GetPlayer()->OnUpperLevel(),game->GetPlayer()->GetZ(),HurtType::MONSTER); game->HurtConeNotHit(game->GetPlayer()->GetPos(),game->GetPlayer()->GetAttackRangeMult()*12.f,rotation,util::degToRad(swordSweepAngle),game->GetPlayer()->GetAttack()*damageMult,hitList,game->GetPlayer()->OnUpperLevel(),game->GetPlayer()->GetZ(),HurtType::MONSTER);
} }
pos=game->GetPlayer()->GetPos(); pos=game->GetPlayer()->GetPos();

View File

@ -26,4 +26,13 @@ Add Spell Names on info screen.
PGETinker notes PGETinker notes
=============== ===============
Changing zoom size does not affect the indentation breadcumb immediately (requires scrolling to change the view) Changing zoom size does not affect the indentation breadcumb immediately (requires scrolling to change the view)
Enabling javid mode does not immediately re-evaluate code. Enabling javid mode does not immediately re-evaluate code.
Adding new class animations
===========================
Player.txt contains animation names the player has to have loaded.
<className>.cpp contains walk and idle animation references that must be loaded in the Initialize() function.
Animation.cpp contains the SetupClassWalkIdleAnimations() function which all classes need to implement with their spritesheet and class name (all caps) to create the WALK and IDLE animations in the animation database.
All other custom player class animations must be added here too.

View File

@ -41,6 +41,7 @@ All rights reserved.
#include "Effect.h" #include "Effect.h"
#include "AdventuresInLestoria.h" #include "AdventuresInLestoria.h"
#include "config.h" #include "config.h"
#include "SoundEffect.h"
INCLUDE_MONSTER_LIST INCLUDE_MONSTER_LIST
INCLUDE_BULLET_LIST INCLUDE_BULLET_LIST
@ -48,14 +49,14 @@ INCLUDE_game
void Thief::Initialize(){ void Thief::Initialize(){
READFROMCONFIG(Thief,THIEF); READFROMCONFIG(Thief,THIEF);
Thief::idle_n="WARRIOR_IDLE_N"; Thief::idle_n="THIEF_IDLE_N";
Thief::idle_e="WARRIOR_IDLE_E"; Thief::idle_e="THIEF_IDLE_E";
Thief::idle_s="WARRIOR_IDLE_S"; Thief::idle_s="THIEF_IDLE_S";
Thief::idle_w="WARRIOR_IDLE_W"; Thief::idle_w="THIEF_IDLE_W";
Thief::walk_n="WARRIOR_WALK_N"; Thief::walk_n="THIEF_WALK_N";
Thief::walk_e="WARRIOR_WALK_E"; Thief::walk_e="THIEF_WALK_E";
Thief::walk_s="WARRIOR_WALK_S"; Thief::walk_s="THIEF_WALK_S";
Thief::walk_w="WARRIOR_WALK_W"; Thief::walk_w="THIEF_WALK_W";
} }
SETUP_CLASS(Thief) SETUP_CLASS(Thief)
@ -65,7 +66,38 @@ void Thief::OnUpdate(float fElapsedTime){
} }
bool Thief::AutoAttack(){ bool Thief::AutoAttack(){
return false; bool attack=false;
Monster*closest=nullptr;
float closest_dist=999999;
for(std::unique_ptr<Monster>&m:MONSTER_LIST){
if(m->IsAlive()&&
geom2d::overlaps(geom2d::circle<float>(GetPos(),attack_range*GetSizeMult()*12),geom2d::circle<float>(m->GetPos(),m->GetSizeMult()*12))&&
geom2d::line<float>(GetWorldAimingLocation(),m->GetPos()).length()<closest_dist){
closest_dist=geom2d::line<float>(GetWorldAimingLocation(),m->GetPos()).length();
closest=&*m;
}
}
float targetDirection;
if(closest!=nullptr){
float dirToEnemy=geom2d::line<float>(GetPos(),closest->GetPos()).vector().polar().y;
targetDirection=dirToEnemy;
SetAnimationBasedOnTargetingDirection(dirToEnemy);
}else{
float dirToMouse=geom2d::line<float>(GetPos(),GetWorldAimingLocation()).vector().polar().y;
targetDirection=dirToMouse;
SetAnimationBasedOnTargetingDirection(dirToMouse);
}
attack_cooldown_timer=ATTACK_COOLDOWN-GetAttackRecoveryRateReduction();
swordSwingTimer="Thief.Auto Attack.SwordAnimationSwingTime"_F;
game->AddEffect(std::make_unique<SwordSlash>(0.125f,"swordslash.png"s,"Thief.Auto Attack.DamageMult"_F,"Thief.Auto Attack.SwordSlashSweepAngle"_F,vf2d{0.9f,0.9f}*"Thief.Auto Attack.Range"_F/100.f,0.1f,vf2d{0.f,0.f},WHITE,targetDirection));
SetState(State::SWING_SWORD);
SoundEffect::PlaySFX("Warrior Auto Attack",SoundEffect::CENTERED);
return true;
} }
void Thief::InitializeClassAbilities(){ void Thief::InitializeClassAbilities(){
#pragma region Thief Right-click Ability (???) #pragma region Thief Right-click Ability (???)

View File

@ -39,7 +39,7 @@ All rights reserved.
#define VERSION_MAJOR 1 #define VERSION_MAJOR 1
#define VERSION_MINOR 2 #define VERSION_MINOR 2
#define VERSION_PATCH 3 #define VERSION_PATCH 3
#define VERSION_BUILD 10050 #define VERSION_BUILD 10053
#define stringify(a) stringify_(a) #define stringify(a) stringify_(a)
#define stringify_(a) #a #define stringify_(a) #a

View File

@ -94,7 +94,7 @@ bool Warrior::AutoAttack(){
attack_cooldown_timer=ATTACK_COOLDOWN-GetAttackRecoveryRateReduction(); attack_cooldown_timer=ATTACK_COOLDOWN-GetAttackRecoveryRateReduction();
swordSwingTimer="Warrior.Auto Attack.SwordAnimationSwingTime"_F; swordSwingTimer="Warrior.Auto Attack.SwordAnimationSwingTime"_F;
game->AddEffect(std::make_unique<SwordSlash>(0.125f,"swordslash.png"s,vf2d{0.9f,0.9f}*"Warrior.Auto Attack.Range"_F/100.f,0.1f,vf2d{0.f,0.f},WHITE,targetDirection)); game->AddEffect(std::make_unique<SwordSlash>(0.125f,"swordslash.png"s,"Warrior.Auto Attack.DamageMult"_F,"Warrior.Auto Attack.SwordSlashSweepAngle"_F,vf2d{0.9f,0.9f}*"Warrior.Auto Attack.Range"_F/100.f,0.1f,vf2d{0.f,0.f},WHITE,targetDirection));
SetState(State::SWING_SWORD); SetState(State::SWING_SWORD);
SoundEffect::PlaySFX("Warrior Auto Attack",SoundEffect::CENTERED); SoundEffect::PlaySFX("Warrior Auto Attack",SoundEffect::CENTERED);

View File

@ -83,6 +83,9 @@ Player
PLAYER_ANIMATION[9] = WIZARD_ATTACK PLAYER_ANIMATION[9] = WIZARD_ATTACK
PLAYER_ANIMATION[10] = WIZARD_CAST PLAYER_ANIMATION[10] = WIZARD_CAST
PLAYER_ANIMATION[11] = WIZARD_IDLE PLAYER_ANIMATION[11] = WIZARD_IDLE
PLAYER_ANIMATION[12] = THIEF_IDLE
PLAYER_ANIMATION[13] = THIEF_WALK
PLAYER_ANIMATION[14] = THIEF_SWINGSWORD
} }

View File

@ -14,7 +14,7 @@ Warrior
Auto Attack Auto Attack
{ {
DamageMult = 1 DamageMult = 1x
Range = 150 Range = 150
Cooldown = 0.35 Cooldown = 0.35
# Whether or not this ability cancels casts. # Whether or not this ability cancels casts.

View File

@ -108,6 +108,8 @@ Images
GFX_Feather = feather.png GFX_Feather = feather.png
GFX_LargeRock = large_rock.png GFX_LargeRock = large_rock.png
GFX_Thief_Sheet = nico-thief.png
# Ability Icons # Ability Icons
GFX_Warrior_BattleCry_Icon = Ability Icons/battlecry.png GFX_Warrior_BattleCry_Icon = Ability Icons/battlecry.png
GFX_Warrior_Block_Icon = Ability Icons/block.png GFX_Warrior_Block_Icon = Ability Icons/block.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

View File

@ -1144,6 +1144,7 @@ namespace olc
// Draws a decal rotated to specified angle, wit point of rotation offset // Draws a decal rotated to specified angle, wit point of rotation offset
void DrawRotatedDecal(const olc::vf2d& pos, olc::Decal* decal, const float fAngle, const olc::vf2d& center = { 0.0f, 0.0f }, const olc::vf2d& scale = { 1.0f,1.0f }, const olc::Pixel& tint = olc::WHITE); void DrawRotatedDecal(const olc::vf2d& pos, olc::Decal* decal, const float fAngle, const olc::vf2d& center = { 0.0f, 0.0f }, const olc::vf2d& scale = { 1.0f,1.0f }, const olc::Pixel& tint = olc::WHITE);
void DrawPartialRotatedDecal(const olc::vf2d& pos, olc::Decal* decal, const float fAngle, const olc::vf2d& center, const olc::vf2d& source_pos, const olc::vf2d& source_size, const olc::vf2d& scale = { 1.0f, 1.0f }, const olc::Pixel& tint = olc::WHITE); void DrawPartialRotatedDecal(const olc::vf2d& pos, olc::Decal* decal, const float fAngle, const olc::vf2d& center, const olc::vf2d& source_pos, const olc::vf2d& source_size, const olc::vf2d& scale = { 1.0f, 1.0f }, const olc::Pixel& tint = olc::WHITE);
void DrawPartialSquishedRotatedDecal(const olc::vf2d& pos, olc::Decal* decal, const float fAngle, const olc::vf2d& center, const olc::vf2d& source_pos, const olc::vf2d& source_size, const olc::vf2d& scale = { 1.0f, 1.0f }, const olc::Pixel& tint = olc::WHITE);
// Draws a multiline string as a decal, with tiniting and scaling // Draws a multiline string as a decal, with tiniting and scaling
void DrawStringDecal(const olc::vf2d& pos, std::string_view sText, const Pixel col = olc::WHITE, const olc::vf2d& scale = { 1.0f, 1.0f },const float width=std::numeric_limits<float>::max(),const bool disableDynamicScaling=false); void DrawStringDecal(const olc::vf2d& pos, std::string_view sText, const Pixel col = olc::WHITE, const olc::vf2d& scale = { 1.0f, 1.0f },const float width=std::numeric_limits<float>::max(),const bool disableDynamicScaling=false);
void DrawOGStringDecal(const olc::vf2d& pos, const std::string& sText, const Pixel col = olc::WHITE, const olc::vf2d& scale = { 1.0f, 1.0f }); void DrawOGStringDecal(const olc::vf2d& pos, const std::string& sText, const Pixel col = olc::WHITE, const olc::vf2d& scale = { 1.0f, 1.0f });
@ -3321,6 +3322,37 @@ namespace olc
di.structure = nDecalStructure; di.structure = nDecalStructure;
vLayers[nTargetLayer].vecDecalInstance.push_back(di); vLayers[nTargetLayer].vecDecalInstance.push_back(di);
} }
void PixelGameEngine::DrawPartialSquishedRotatedDecal(const olc::vf2d& pos, olc::Decal* decal, const float fAngle, const olc::vf2d& center, const olc::vf2d& source_pos, const olc::vf2d& source_size, const olc::vf2d& scale, const olc::Pixel& tint)
{
DecalInstance di;
di.decal = decal;
di.points = 4;
di.tint = { tint, tint, tint, tint };
di.w = { 1, 1, 1, 1 };
di.pos.resize(4);
di.pos[0] = (olc::vf2d(0.0f, 0.0f) - center);
di.pos[1] = (olc::vf2d(0.0f, source_size.y) - center);
di.pos[2] = (olc::vf2d(source_size.x, source_size.y) - center);
di.pos[3] = (olc::vf2d(source_size.x, 0.0f) - center);
float c = cos(fAngle), s = sin(fAngle);
for (int i = 0; i < 4; i++)
{
di.pos[i] = pos + olc::vf2d(di.pos[i].x * c - di.pos[i].y * s, di.pos[i].x * s + di.pos[i].y * c);
di.pos[i] = di.pos[i] * vInvScreenSize * 2.0f - olc::vf2d(1.0f, 1.0f);
di.pos[i].y *= -1.0f;
}
di.pos[0] *= scale;
di.pos[1] *= scale;
di.pos[2] *= scale;
di.pos[3] *= scale;
olc::vf2d uvtl = source_pos * decal->vUVScale;
olc::vf2d uvbr = uvtl + (source_size * decal->vUVScale);
di.uv = { { uvtl.x, uvtl.y }, { uvtl.x, uvbr.y }, { uvbr.x, uvbr.y }, { uvbr.x, uvtl.y } };
di.mode = nDecalMode;
di.structure = nDecalStructure;
vLayers[nTargetLayer].vecDecalInstance.push_back(di);
}
void PixelGameEngine::DrawPartialWarpedDecal(olc::Decal* decal, const olc::vf2d* pos, const olc::vf2d& source_pos, const olc::vf2d& source_size, const olc::Pixel& tint) void PixelGameEngine::DrawPartialWarpedDecal(olc::Decal* decal, const olc::vf2d* pos, const olc::vf2d& source_pos, const olc::vf2d& source_size, const olc::Pixel& tint)
{ {