Monsters that ignore terrain collision should not be moved by other solid objects. Hide fade timers and the internal UpdateFadeTime function from inherited bullet types. Add large stone graphic. Apply fixed time step to large stone throw. Add in physics for large stone throw attack. Release Build 9630.

mac-build
sigonasr2 5 months ago
parent c02d6cdb47
commit daad7d82fb
  1. 1
      Adventures in Lestoria/Adventures in Lestoria.vcxproj
  2. 15
      Adventures in Lestoria/Adventures in Lestoria.vcxproj.filters
  3. 11
      Adventures in Lestoria/Bullet.cpp
  4. 10
      Adventures in Lestoria/Bullet.h
  5. 19
      Adventures in Lestoria/BulletTypes.h
  6. 4
      Adventures in Lestoria/ItemDrop.cpp
  7. 78
      Adventures in Lestoria/LargeStone.cpp
  8. 3
      Adventures in Lestoria/Monster.cpp
  9. 10
      Adventures in Lestoria/StoneGolem.cpp
  10. 6
      Adventures in Lestoria/TODO.txt
  11. 2
      Adventures in Lestoria/Version.h
  12. 5
      Adventures in Lestoria/assets/config/MonsterStrategies.txt
  13. BIN
      x64/Release/Adventures in Lestoria.exe

@ -798,6 +798,7 @@
<ClCompile Include="ItemDrop.cpp" /> <ClCompile Include="ItemDrop.cpp" />
<ClCompile Include="ItemLoadoutWindow.cpp" /> <ClCompile Include="ItemLoadoutWindow.cpp" />
<ClCompile Include="Key.cpp" /> <ClCompile Include="Key.cpp" />
<ClCompile Include="LargeStone.cpp" />
<ClCompile Include="LargeTornado.cpp"> <ClCompile Include="LargeTornado.cpp">
<SubType> <SubType>
</SubType> </SubType>

@ -1037,9 +1037,6 @@
<ClCompile Include="Boar.cpp"> <ClCompile Include="Boar.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="Bomb.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="DaggerSlash.cpp"> <ClCompile Include="DaggerSlash.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
@ -1103,6 +1100,18 @@
<ClCompile Include="Pixel.cpp"> <ClCompile Include="Pixel.cpp">
<Filter>Source Files\Engine</Filter> <Filter>Source Files\Engine</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="Feather.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="SpellCircle.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="LargeStone.cpp">
<Filter>Source Files\Bullet Types</Filter>
</ClCompile>
<ClCompile Include="Bomb.cpp">
<Filter>Source Files\Bullet Types</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="cpp.hint" /> <None Include="cpp.hint" />

@ -61,6 +61,7 @@ Animate2D::Frame Bullet::GetFrame()const{
} }
void Bullet::UpdateFadeTime(float fElapsedTime) void Bullet::UpdateFadeTime(float fElapsedTime)
{ {
aliveTime+=fElapsedTime;
if(fadeInTime>0){ if(fadeInTime>0){
if(fadeInTimer<fadeInTime){ if(fadeInTimer<fadeInTime){
fadeInTimer=std::min(fadeInTime,fadeInTimer+fElapsedTime); fadeInTimer=std::min(fadeInTime,fadeInTimer+fElapsedTime);
@ -250,5 +251,13 @@ const bool Bullet::IsActivated()const{
return !IsDeactivated(); return !IsDeactivated();
} }
const bool Bullet::IsDeactivated()const{ const bool Bullet::IsDeactivated()const{
return fadeOutTime>0.f; return deactivated||fadeOutTime>0.f;
}
void Bullet::Deactivate(){
deactivated=true;
}
const double Bullet::GetTimeAlive()const{
return aliveTime;
} }

@ -72,24 +72,28 @@ struct Bullet{
protected: protected:
float distanceTraveled=0.f; float distanceTraveled=0.f;
vf2d scale={1,1}; vf2d scale={1,1};
float fadeOutTimer=0;
float fadeInTime=0; //Setting the fade in time causes the bullet to be disabled and the bullet's alpha will fade in from zero to the actual alpha of the bullet. When the fade in timer reaches the fade in time automatically, the bullet will be enabled. float fadeInTime=0; //Setting the fade in time causes the bullet to be disabled and the bullet's alpha will fade in from zero to the actual alpha of the bullet. When the fade in timer reaches the fade in time automatically, the bullet will be enabled.
float fadeInTimer=0;
void UpdateFadeTime(float fElapsedTime);
virtual void Update(float fElapsedTime); virtual void Update(float fElapsedTime);
void Deactivate();
private: private:
float fadeOutTimer=0;
float fadeInTimer=0;
void UpdateFadeTime(float fElapsedTime);
bool dead=false; //When marked as dead it wil be removed by the next frame. bool dead=false; //When marked as dead it wil be removed by the next frame.
bool simulated=false; //A simulated bullet cannot interact / damage things in the world. It's simply used for simulating the trajectory and potential path of the bullet bool simulated=false; //A simulated bullet cannot interact / damage things in the world. It's simply used for simulating the trajectory and potential path of the bullet
float iframeTimerOnHit{0.f}; float iframeTimerOnHit{0.f};
bool playerAutoAttackProjectile=false; //Set to true for bullets that are auto attack projectiles to identify them. bool playerAutoAttackProjectile=false; //Set to true for bullets that are auto attack projectiles to identify them.
void _Draw()const; void _Draw()const;
BulletType type{BulletType::UNDEFINED}; BulletType type{BulletType::UNDEFINED};
bool deactivated{false};
double aliveTime{};
protected: protected:
float drawOffsetY{}; float drawOffsetY{};
BulletDestroyState _PlayerHit(Player*player); //Return true to destroy the bullet on hit, return false otherwise. THE BULLET HIT HAS ALREADY OCCURRED. BulletDestroyState _PlayerHit(Player*player); //Return true to destroy the bullet on hit, return false otherwise. THE BULLET HIT HAS ALREADY OCCURRED.
BulletDestroyState _MonsterHit(Monster&monster); //Return true to destroy the bullet on hit, return false otherwise. THE BULLET HIT HAS ALREADY OCCURRED. BulletDestroyState _MonsterHit(Monster&monster); //Return true to destroy the bullet on hit, return false otherwise. THE BULLET HIT HAS ALREADY OCCURRED.
const float&GetFadeoutTimer()const; const float&GetFadeoutTimer()const;
void SetBulletType(const BulletType type); void SetBulletType(const BulletType type);
const double GetTimeAlive()const;
public: public:
Animate2D::Animation<std::string>animation; Animate2D::Animation<std::string>animation;
Animate2D::AnimationState internal_animState; Animate2D::AnimationState internal_animState;

@ -225,4 +225,23 @@ struct LargeTornado:public Bullet{
struct Feather:public Bullet{ struct Feather:public Bullet{
Feather(vf2d pos,vf2d vel,float radius,int damage,bool upperLevel,bool hitsMultiple=false,float lifetime=INFINITE,bool friendly=false,Pixel col=WHITE,vf2d scale={1,1},float image_angle=0.f); Feather(vf2d pos,vf2d vel,float radius,int damage,bool upperLevel,bool hitsMultiple=false,float lifetime=INFINITE,bool friendly=false,Pixel col=WHITE,vf2d scale={1,1},float image_angle=0.f);
};
struct LargeStone:public Bullet{
public:
LargeStone(vf2d pos,const float stoneThrowTime,const vf2d landingPos,float moveVelWaitTimer,float radius,float z,float gravity,int damage,bool upperLevel,bool hitsMultiple=false,float lifetime=INFINITE,bool friendly=false,Pixel col=WHITE,vf2d scale={1,1},float image_angle=0.f);
protected:
void Update(float fElapsedTime)override;
BulletDestroyState PlayerHit(Player*player)override;//DO NOT CALL THIS DIRECTLY! INSTEAD USE _PlayerHit()!!
BulletDestroyState MonsterHit(Monster&monster)override;//DO NOT CALL THIS DIRECTLY! INSTEAD USE _MonsterHit()!!
private:
const float gravity;
const float fixedTimeStep{1/30.f};
const float stoneThrowTime;
const vf2d landingPos;
const vf2d startingPos;
float fixedTimeStepAcc{};
float zVel{};
float moveTimer; //Counts down to 0, when it hits zero sets the velocity to futurevel.
const float initialMoveWaitTime;
}; };

@ -58,8 +58,8 @@ ItemDrop::ItemDrop(const ItemInfo*item,const vf2d pos,const bool isUpper)
this->pos.x=std::clamp(this->pos.x,float(arenaBounds.pos.x),float(arenaBounds.pos.x+arenaBounds.size.x)); this->pos.x=std::clamp(this->pos.x,float(arenaBounds.pos.x),float(arenaBounds.pos.x+arenaBounds.size.x));
this->pos.y=std::clamp(this->pos.y,float(arenaBounds.pos.y),float(arenaBounds.pos.y+arenaBounds.size.y)); this->pos.y=std::clamp(this->pos.y,float(arenaBounds.pos.y),float(arenaBounds.pos.y+arenaBounds.size.y));
} }
speed.x=util::random("ItemDrop.Item Drop Horizontal Speed"_f[1]-"ItemDrop.Item Drop Horizontal Speed"_f[0])+"ItemDrop.Item Drop Horizontal Speed"_f[0]; speed.x=util::random_range("ItemDrop.Item Drop Horizontal Speed"_f[0],"ItemDrop.Item Drop Horizontal Speed"_f[1]);
speed.y=util::random("ItemDrop.Item Drop Vertical Speed"_f[1]-"ItemDrop.Item Drop Vertical Speed"_f[0])+"ItemDrop.Item Drop Vertical Speed"_f[0]; speed.y=util::random_range("ItemDrop.Item Drop Vertical Speed"_f[0],"ItemDrop.Item Drop Vertical Speed"_f[1]);
zSpeed="ItemDrop.Item Drop Initial Rise Speed"_F; zSpeed="ItemDrop.Item Drop Initial Rise Speed"_F;
randomSpinOffset=util::random(PI/2); randomSpinOffset=util::random(PI/2);
} }

@ -0,0 +1,78 @@
#pragma region License
/*
License (OLC-3)
~~~~~~~~~~~~~~~
Copyright 2024 Joshua Sigona <sigonasr2@gmail.com>
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions or derivations of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions or derivative works in binary form must reproduce the above
copyright notice. This list of conditions and the following disclaimer must be
reproduced in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may
be used to endorse or promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
Portions of this software are copyright © 2024 The FreeType
Project (www.freetype.org). Please see LICENSE_FT.txt for more information.
All rights reserved.
*/
#pragma endregion
#include "BulletTypes.h"
#include "AdventuresInLestoria.h"
INCLUDE_game
LargeStone::LargeStone(vf2d pos,const float stoneThrowTime,const vf2d landingPos,float moveVelWaitTimer,float radius,float z,float gravity,int damage,bool upperLevel,bool hitsMultiple,float lifetime,bool friendly,Pixel col,vf2d scale,float image_angle)
:stoneThrowTime(stoneThrowTime),startingPos(pos),landingPos(landingPos),gravity(gravity),initialMoveWaitTime(moveVelWaitTimer),moveTimer(moveVelWaitTimer),Bullet(pos,{},radius,damage,"large_rock.png",upperLevel,false,INFINITE,false,friendly,col,scale,image_angle){
this->z=z;
Deactivate();
}
void LargeStone::Update(float fElapsedTime){
fixedTimeStepAcc+=fElapsedTime;
while(fixedTimeStepAcc>fixedTimeStep){
Bullet::Update(fixedTimeStep);
if(moveTimer>0.f)moveTimer-=fixedTimeStep;
if(moveTimer<=0.f){
if(z<=0.f&&fadeOutTime==0.f){
game->Hurt(pos,radius,damage,OnUpperLevel(),0.f,friendly?HurtType::MONSTER:HurtType::PLAYER);
fadeOutTime=0.5f;
}else
if(z>0.f&&fadeOutTime>=0.f){
pos=startingPos.lerp(landingPos,(GetTimeAlive()-initialMoveWaitTime)/stoneThrowTime);
zVel+=gravity*fixedTimeStep;
z+=zVel*fixedTimeStep;
}
}
fixedTimeStepAcc-=fixedTimeStep;
}
}
BulletDestroyState LargeStone::PlayerHit(Player*player){
return BulletDestroyState::KEEP_ALIVE;
}
BulletDestroyState LargeStone::MonsterHit(Monster&monster){
return BulletDestroyState::KEEP_ALIVE;
}

@ -356,7 +356,8 @@ bool Monster::Update(float fElapsedTime){
knockbackStrength+=b.intensity; knockbackStrength+=b.intensity;
} }
Knockback(line.vector().norm()*-128*knockbackStrength); Knockback(line.vector().norm()*-128*knockbackStrength);
}else{ }else
if(!IgnoresTerrainCollision()){
SetPos(line.rpoint(-displacementDist)); SetPos(line.rpoint(-displacementDist));
} }
} }

@ -41,6 +41,7 @@ All rights reserved.
#include "AdventuresInLestoria.h" #include "AdventuresInLestoria.h"
#include "DEFINES.h" #include "DEFINES.h"
#include "util.h" #include "util.h"
#include "BulletTypes.h"
INCLUDE_game INCLUDE_game
@ -97,10 +98,17 @@ void Monster::STRATEGY::STONE_GOLEM(Monster&m,float fElapsedTime,std::string str
m.PerformAnimation("TOSS ROCK CAST"); m.PerformAnimation("TOSS ROCK CAST");
m.F(A::CASTING_TIMER)=ConfigFloat("Standard Attack.Stone Throw Cast Time"); m.F(A::CASTING_TIMER)=ConfigFloat("Standard Attack.Stone Throw Cast Time");
game->AddEffect(std::make_unique<SpellCircle>(m.V(A::LOCKON_POS),ConfigFloat("Standard Attack.Stone Throw Cast Time")+4.f,"range_indicator.png","spell_insignia.png",m.OnUpperLevel(),vf2d{1.f,1.f}*(ConfigPixels("Standard Attack.Stone Radius")/12.f)*1.25f,0.3f,vf2d{},ConfigPixel("Standard Attack.Stone Throw Spell Circle Color"),util::random(2*PI),util::degToRad(ConfigFloat("Standard Attack.Stone Throw Spell Circle Rotation Spd")),false,vf2d{1.f,1.f}*(ConfigPixels("Standard Attack.Stone Radius")/12.f)*0.9f,0.3f,vf2d{},ConfigPixel("Standard Attack.Stone Throw Spell Insignia Color"),util::random(2*PI),util::degToRad(ConfigFloat("Standard Attack.Stone Throw Spell Insignia Rotation Spd"))),true); game->AddEffect(std::make_unique<SpellCircle>(m.V(A::LOCKON_POS),ConfigFloat("Standard Attack.Stone Throw Cast Time")+4.f,"range_indicator.png","spell_insignia.png",m.OnUpperLevel(),vf2d{1.f,1.f}*(ConfigPixels("Standard Attack.Stone Radius")/12.f)*1.25f,0.3f,vf2d{},ConfigPixel("Standard Attack.Stone Throw Spell Circle Color"),util::random(2*PI),util::degToRad(ConfigFloat("Standard Attack.Stone Throw Spell Circle Rotation Spd")),false,vf2d{1.f,1.f}*(ConfigPixels("Standard Attack.Stone Radius")/12.f)*0.9f,0.3f,vf2d{},ConfigPixel("Standard Attack.Stone Throw Spell Insignia Color"),util::random(2*PI),util::degToRad(ConfigFloat("Standard Attack.Stone Throw Spell Insignia Rotation Spd"))),true);
//Use acceleration equation to determine how much time it takes for the stone to land based on gravity.
const float stoneTossTime{ConfigFloat("Standard Attack.Stone Throw Time")};
//Physics!! Kinematic equation from https://openstax.org/books/physics/pages/3-2-representing-acceleration-with-equations-and-graphs a=(2d)/(t^2)
const float acc{(2*-ConfigFloat("Standard Attack.Stone Throw Height Offset"))/std::pow(stoneTossTime,2.f)};
CreateBullet(LargeStone)(m.GetPos()+ConfigFloat("Standard Attack.Stone Throw Height Offset")/2.f,ConfigFloat("Standard Attack.Stone Throw Time"),m.V(A::LOCKON_POS),m.F(A::CASTING_TIMER),ConfigPixels("Standard Attack.Stone Radius"),ConfigFloat("Standard Attack.Stone Throw Height Offset"),acc,ConfigInt("Standard Attack.Stone Damage"),m.OnUpperLevel(),false,INFINITY,false,WHITE,vf2d{1,1}*m.GetSizeMult(),util::random(2*PI))EndBullet;
} }
}break; }break;
case STONE_THROW_CAST:{ case STONE_THROW_CAST:{
}break; }break;
} }
} }

@ -10,15 +10,9 @@ Upon the second time entering a stage, the game will spawn a timer that the play
Upon completion of a stage in time trial mode if the player beat their previous time (which they likely will) the record will update. Upon completion of a stage in time trial mode if the player beat their previous time (which they likely will) the record will update.
For each class and stage combination there will be a "dev time" For each class and stage combination there will be a "dev time"
Settings menu doesn't scroll back up properly while the scrollbar does?
Traveling merchants of different colors/looks. Traveling merchants of different colors/looks.
Steel Weapons appear in the demo for Chapter 2.
Look into removing OVERRIDE from rumble settings. It looks like it was used to purposefully disable rumble, but looks very unnecessary. Look into removing OVERRIDE from rumble settings. It looks like it was used to purposefully disable rumble, but looks very unnecessary.
Move old maps from master branch into demo branch (has boundary changes)
When a monster spawns, if it spawns inside a collision tile, attempt to set it outside somewhere and make a warning popup.
New Monster Sound Effects New Monster Sound Effects
DEMO DEMO

@ -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 9622 #define VERSION_BUILD 9630
#define stringify(a) stringify_(a) #define stringify(a) stringify_(a)
#define stringify_(a) #a #define stringify_(a) #a

@ -917,9 +917,12 @@ MonsterStrategy
Stone Throw Chance = 25% Stone Throw Chance = 25%
Stone Radius = 250 Stone Radius = 250
Stone Damage = 55 Stone Damage = 55
Stone Pillar Damage = 3
Stone Throw Cast Time = 2.5s Stone Throw Cast Time = 2.5s
# How high in the air the rock starts at from the GROUND.
Stone Throw Height Offset = 160pixels
Stone Throw Time = 0.75s
Stone Throw Spell Circle Color = 40, 40, 40, 80 Stone Throw Spell Circle Color = 40, 40, 40, 80
Stone Throw Spell Insignia Color = 144, 137, 160, 255 Stone Throw Spell Insignia Color = 144, 137, 160, 255
# Degrees/sec. Positive is CW, Negative is CCW. # Degrees/sec. Positive is CW, Negative is CCW.

Loading…
Cancel
Save