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.

mac-build
sigonasr2 4 months ago
parent 477c3ab086
commit 10f5521ec2
  1. 20
      Adventures in Lestoria/Animation.cpp
  2. 4
      Adventures in Lestoria/Effect.h
  3. 17
      Adventures in Lestoria/Player.cpp
  4. 6
      Adventures in Lestoria/SwordSlash.cpp
  5. 11
      Adventures in Lestoria/TODO.txt
  6. 50
      Adventures in Lestoria/Thief.cpp
  7. 2
      Adventures in Lestoria/Version.h
  8. 2
      Adventures in Lestoria/Warrior.cpp
  9. 3
      Adventures in Lestoria/assets/config/Player.txt
  10. 2
      Adventures in Lestoria/assets/config/classes/Warrior.txt
  11. 2
      Adventures in Lestoria/assets/config/gfx/gfx.txt
  12. BIN
      Adventures in Lestoria/assets/gamepack.pak
  13. BIN
      Adventures in Lestoria/assets/nico-thief.png
  14. BIN
      Adventures in Lestoria/assets/nico-thief.xcf
  15. 32
      Adventures in Lestoria/olcPixelGameEngine.h
  16. BIN
      x64/Release/Adventures in Lestoria.exe

@ -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});

@ -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.

@ -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;
} }
} }

@ -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();

@ -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.

@ -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 (???)

@ -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

@ -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);

@ -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
} }

@ -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.

@ -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

@ -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)
{ {

Loading…
Cancel
Save