Remove the random message

pull/28/head
commit 5bc449fb7a
  1. 4
      Crawler/Ability.cpp
  2. 3
      Crawler/Ability.h
  3. 131
      Crawler/Animation.cpp
  4. 6
      Crawler/Arrow.cpp
  5. 5
      Crawler/Bullet.cpp
  6. 2
      Crawler/C++/scripts/md5
  7. 6
      Crawler/C++/scripts/web.sh
  8. 4
      Crawler/ChargedArrow.cpp
  9. 665
      Crawler/ClassDiagram2.cd
  10. BIN
      Crawler/ClassDiagram2.png
  11. BIN
      Crawler/Crawler
  12. 618
      Crawler/Crawler.cpp
  13. 32
      Crawler/Crawler.h
  14. 59
      Crawler/Crawler.tiled-project
  15. 2
      Crawler/Crawler.vcxproj
  16. 4
      Crawler/Crawler.vcxproj.filters
  17. 4
      Crawler/DEFINES.h
  18. 10
      Crawler/Effect.cpp
  19. 8
      Crawler/Effect.h
  20. 8
      Crawler/EnergyBolt.cpp
  21. 19
      Crawler/FallingDebris.h
  22. 10
      Crawler/FireBolt.cpp
  23. 16
      Crawler/LightningBolt.cpp
  24. 4
      Crawler/LightningBoltEmitter.cpp
  25. 2
      Crawler/Map.cpp
  26. 13
      Crawler/Map.h
  27. 14
      Crawler/Meteor.cpp
  28. 23
      Crawler/Monster.cpp
  29. 3
      Crawler/Monster.h
  30. 2
      Crawler/MonsterAttribute.h
  31. 2
      Crawler/MonsterData.cpp
  32. 1
      Crawler/Pathfinding.cpp
  33. 28
      Crawler/Player.cpp
  34. 18
      Crawler/Player.h
  35. 14
      Crawler/PulsatingFire.cpp
  36. 102
      Crawler/SlimeKing.cpp
  37. 26
      Crawler/TMXParser.h
  38. 25
      Crawler/TSXParser.h
  39. 9
      Crawler/Turret.cpp
  40. 2
      Crawler/Version.h
  41. 4
      Crawler/Warrior.cpp
  42. 7
      Crawler/Wizard.cpp
  43. BIN
      Crawler/assets/Campaigns/1_1_v2.png
  44. 1253
      Crawler/assets/Campaigns/1_1_v2.tmx
  45. 10
      Crawler/assets/config/MonsterStrategies.txt
  46. 4
      Crawler/assets/config/Monsters.txt
  47. 11
      Crawler/assets/config/classes/Ranger.txt
  48. 8
      Crawler/assets/config/classes/Thief.txt
  49. 8
      Crawler/assets/config/classes/Trapper.txt
  50. 10
      Crawler/assets/config/classes/Warrior.txt
  51. 8
      Crawler/assets/config/classes/Witch.txt
  52. 10
      Crawler/assets/config/classes/Wizard.txt
  53. 17
      Crawler/assets/config/configuration.txt
  54. 36
      Crawler/assets/config/gfx/gfx.txt
  55. BIN
      Crawler/assets/fire_ring0.png
  56. BIN
      Crawler/assets/fire_ring1.png
  57. BIN
      Crawler/assets/fire_ring2.png
  58. BIN
      Crawler/assets/fire_ring3.png
  59. BIN
      Crawler/assets/fire_ring4.png
  60. 124
      Crawler/assets/maps/24x24_Waterfall.tsx
  61. 1437
      Crawler/assets/maps/Decorations_c1_No_Shadow24x24.tsx
  62. 3124
      Crawler/assets/maps/Tile_Presets.tmx
  63. 4645
      Crawler/assets/maps/Tilesheet_No_Shadow24x24.tsx
  64. BIN
      Crawler/assets/monsters/Slime King - Cast.png
  65. BIN
      Crawler/assets/nico-warrior.png
  66. BIN
      Crawler/assets/nico-warrior.xcf
  67. 2
      Crawler/buildtemplate.html
  68. 2
      Crawler/olcPGEX_TransformedView.h
  69. 4
      Crawler/olcPixelGameEngine.h
  70. 19
      Crawler/olcUTIL_DataFile.h
  71. 16364
      Crawler/pge.data
  72. 2
      Crawler/pge.js
  73. BIN
      Crawler/pge.wasm
  74. 1
      Crawler/pixelGameEngine.cpp
  75. 75
      Crawler/play.html
  76. 17
      Crawler/safemap.h
  77. 5
      Crawler/sig
  78. 4
      Crawler/utils.cpp
  79. 2
      Crawler/utils.h
  80. BIN
      x64/Release/Crawler.exe

@ -10,5 +10,5 @@ PrecastData::PrecastData(float castTime,float range,float size)
};
Ability::Ability(){};
Ability::Ability(std::string name,float cooldownTime,int manaCost,Pixel barColor1,Pixel barColor2,PrecastData precastInfo)
:name(name),cooldown(0),COOLDOWN_TIME(cooldownTime),manaCost(manaCost),barColor1(barColor1),barColor2(barColor2),precastInfo(precastInfo){}
Ability::Ability(std::string name,float cooldownTime,int manaCost,Pixel barColor1,Pixel barColor2,PrecastData precastInfo,bool canCancelCast)
:name(name),cooldown(0),COOLDOWN_TIME(cooldownTime),manaCost(manaCost),barColor1(barColor1),barColor2(barColor2),precastInfo(precastInfo),canCancelCast(canCancelCast){}

@ -23,7 +23,8 @@ struct Ability{
int manaCost=0;
Pixel barColor1,barColor2;
PrecastData precastInfo;
bool canCancelCast=false;
std::function<bool(Player*,vf2d)>action=[](Player*,vf2d){return false;};
Ability();
Ability(std::string name,float cooldownTime,int manaCost,Pixel barColor1=VERY_DARK_RED,Pixel barColor2=DARK_RED,PrecastData precastInfo={});
Ability(std::string name,float cooldownTime,int manaCost,Pixel barColor1=VERY_DARK_RED,Pixel barColor2=DARK_RED,PrecastData precastInfo={},bool canCancelCast=false);
};

@ -6,21 +6,22 @@
INCLUDE_game
INCLUDE_ANIMATION_DATA
INCLUDE_DATA
INCLUDE_GFX
void sig::Animation::InitializeAnimations(){
auto CreateStillAnimation=[&](Renderable&img,vf2d size,std::string state,AnimationData data={}){
auto CreateStillAnimation=[&](std::string imgName,vf2d size,AnimationData data={}){
Animate2D::FrameSequence anim(data.frameDuration,data.style);
anim.AddFrame({&img,{{0,0},size}});
ANIMATION_DATA[state]=anim;
anim.AddFrame({&GFX[imgName],{{0,0},size}});
ANIMATION_DATA[imgName]=anim;
};
auto CreateHorizontalAnimationSequence=[&](Renderable&img,int frameCount,vf2d size,std::string state,AnimationData data={}){
auto CreateHorizontalAnimationSequence=[&](std::string imgName,int frameCount,vf2d size,AnimationData data={}){
Animate2D::FrameSequence anim(data.frameDuration,data.style);
for(int i=0;i<frameCount;i++){
anim.AddFrame({&img,{{int(i*size.x),0},size}});
anim.AddFrame({&GFX[imgName],{{int(i*size.x),0},size}});
}
ANIMATION_DATA[state]=anim;
ANIMATION_DATA[imgName]=anim;
};
auto SetupClassWalkIdleAnimations=[&](Renderable&sheet,std::string className){
@ -63,24 +64,24 @@ void sig::Animation::InitializeAnimations(){
};
//Warrior animations.
SetupClassWalkIdleAnimations(game->GFX_Warrior_Sheet,"WARRIOR");
SetupClassWalkIdleAnimations(GFX["nico-warrior.png"],"WARRIOR");
Animate2D::FrameSequence pl_warrior_swing_s(0.05),pl_warrior_swing_n(0.05),pl_warrior_swing_e(0.05),pl_warrior_swing_w(0.05);
Animate2D::FrameSequence pl_warrior_sonic_swing_s(0.1,Animate2D::Style::OneShot),pl_warrior_sonic_swing_n(0.1,Animate2D::Style::OneShot),pl_warrior_sonic_swing_e(0.1,Animate2D::Style::OneShot),pl_warrior_sonic_swing_w(0.1,Animate2D::Style::OneShot);
for (int i=0;i<4;i++){
pl_warrior_swing_s.AddFrame({&game->GFX_Warrior_Sheet,{vi2d{4+i,0}*24,{24,24}}});
pl_warrior_sonic_swing_s.AddFrame({&game->GFX_Warrior_Sheet,{vi2d{4+i,4}*24,{24,24}}});
pl_warrior_swing_s.AddFrame({&GFX["nico-warrior.png"],{vi2d{4+i,0}*24,{24,24}}});
pl_warrior_sonic_swing_s.AddFrame({&GFX["nico-warrior.png"],{vi2d{4+i,4}*24,{24,24}}});
}
for (int i=0;i<4;i++){
pl_warrior_swing_n.AddFrame({&game->GFX_Warrior_Sheet,{vi2d{4+i,1}*24,{24,24}}});
pl_warrior_sonic_swing_n.AddFrame({&game->GFX_Warrior_Sheet,{vi2d{4+i,5}*24,{24,24}}});
pl_warrior_swing_n.AddFrame({&GFX["nico-warrior.png"],{vi2d{4+i,1}*24,{24,24}}});
pl_warrior_sonic_swing_n.AddFrame({&GFX["nico-warrior.png"],{vi2d{4+i,5}*24,{24,24}}});
}
for (int i=0;i<4;i++){
pl_warrior_swing_w.AddFrame({&game->GFX_Warrior_Sheet,{vi2d{4+i,2}*24,{24,24}}});
pl_warrior_sonic_swing_w.AddFrame({&game->GFX_Warrior_Sheet,{vi2d{4+i,6}*24,{24,24}}});
pl_warrior_swing_w.AddFrame({&GFX["nico-warrior.png"],{vi2d{4+i,2}*24,{24,24}}});
pl_warrior_sonic_swing_w.AddFrame({&GFX["nico-warrior.png"],{vi2d{4+i,6}*24,{24,24}}});
}
for (int i=0;i<4;i++){
pl_warrior_swing_e.AddFrame({&game->GFX_Warrior_Sheet,{vi2d{4+i,3}*24,{24,24}}});
pl_warrior_sonic_swing_e.AddFrame({&game->GFX_Warrior_Sheet,{vi2d{4+i,7}*24,{24,24}}});
pl_warrior_swing_e.AddFrame({&GFX["nico-warrior.png"],{vi2d{4+i,3}*24,{24,24}}});
pl_warrior_sonic_swing_e.AddFrame({&GFX["nico-warrior.png"],{vi2d{4+i,7}*24,{24,24}}});
}
ANIMATION_DATA["WARRIOR_SWINGSWORD_N"]=pl_warrior_swing_n;
ANIMATION_DATA["WARRIOR_SWINGSWORD_E"]=pl_warrior_swing_e;
@ -92,13 +93,13 @@ void sig::Animation::InitializeAnimations(){
ANIMATION_DATA["WARRIOR_SWINGSONICSWORD_W"]=pl_warrior_sonic_swing_w;
//Ranger animations
SetupClassWalkIdleAnimations(game->GFX_Ranger_Sheet,"RANGER");
SetupClassWalkIdleAnimations(GFX["nico-ranger.png"],"RANGER");
Animate2D::FrameSequence pl_ranger_shoot_s,pl_ranger_shoot_n,pl_ranger_shoot_e,pl_ranger_shoot_w;
for(int i=0;i<3;i++){
pl_ranger_shoot_s.AddFrame({&game->GFX_Ranger_Sheet,{vi2d{3+i,0}*24,{24,24}}});
pl_ranger_shoot_n.AddFrame({&game->GFX_Ranger_Sheet,{vi2d{3+i,1}*24,{24,24}}});
pl_ranger_shoot_e.AddFrame({&game->GFX_Ranger_Sheet,{vi2d{3+i,3}*24,{24,24}}});
pl_ranger_shoot_w.AddFrame({&game->GFX_Ranger_Sheet,{vi2d{3+i,2}*24,{24,24}}});
pl_ranger_shoot_s.AddFrame({&GFX["nico-ranger.png"],{vi2d{3+i,0}*24,{24,24}}});
pl_ranger_shoot_n.AddFrame({&GFX["nico-ranger.png"],{vi2d{3+i,1}*24,{24,24}}});
pl_ranger_shoot_e.AddFrame({&GFX["nico-ranger.png"],{vi2d{3+i,3}*24,{24,24}}});
pl_ranger_shoot_w.AddFrame({&GFX["nico-ranger.png"],{vi2d{3+i,2}*24,{24,24}}});
}
ANIMATION_DATA["RANGER_SHOOT_S"]=pl_ranger_shoot_s;
ANIMATION_DATA["RANGER_SHOOT_N"]=pl_ranger_shoot_n;
@ -106,107 +107,119 @@ void sig::Animation::InitializeAnimations(){
ANIMATION_DATA["RANGER_SHOOT_W"]=pl_ranger_shoot_w;
//Wizard animations
SetupClassWalkIdleAnimations(game->GFX_Wizard_Sheet,"WIZARD");
SetupClassWalkIdleAnimations(GFX["nico-wizard.png"],"WIZARD");
Animate2D::FrameSequence pl_wizard_idle_attack_s;
pl_wizard_idle_attack_s.AddFrame({&game->GFX_Wizard_Sheet,{vi2d{4,0}*24,{24,24}}});
pl_wizard_idle_attack_s.AddFrame({&GFX["nico-wizard.png"],{vi2d{4,0}*24,{24,24}}});
ANIMATION_DATA["WIZARD_IDLE_ATTACK_S"]=pl_wizard_idle_attack_s;
Animate2D::FrameSequence pl_wizard_idle_attack_e;
pl_wizard_idle_attack_e.AddFrame({&game->GFX_Wizard_Sheet,{vi2d{4,3}*24,{24,24}}});
pl_wizard_idle_attack_e.AddFrame({&GFX["nico-wizard.png"],{vi2d{4,3}*24,{24,24}}});
ANIMATION_DATA["WIZARD_IDLE_ATTACK_E"]=pl_wizard_idle_attack_e;
Animate2D::FrameSequence pl_wizard_idle_attack_w;
pl_wizard_idle_attack_w.AddFrame({&game->GFX_Wizard_Sheet,{vi2d{4,2}*24,{24,24}}});
pl_wizard_idle_attack_w.AddFrame({&GFX["nico-wizard.png"],{vi2d{4,2}*24,{24,24}}});
ANIMATION_DATA["WIZARD_IDLE_ATTACK_W"]=pl_wizard_idle_attack_w;
Animate2D::FrameSequence pl_wizard_idle_attack_n;
pl_wizard_idle_attack_n.AddFrame({&game->GFX_Wizard_Sheet,{vi2d{4,1}*24,{24,24}}});
pl_wizard_idle_attack_n.AddFrame({&GFX["nico-wizard.png"],{vi2d{4,1}*24,{24,24}}});
ANIMATION_DATA["WIZARD_IDLE_ATTACK_N"]=pl_wizard_idle_attack_n;
Animate2D::FrameSequence pl_wizard_attack_s(0.2);
for(int i=0;i<3;i++){
pl_wizard_attack_s.AddFrame({&game->GFX_Wizard_Sheet,{vi2d{4+i,0}*24,{24,24}}});
pl_wizard_attack_s.AddFrame({&GFX["nico-wizard.png"],{vi2d{4+i,0}*24,{24,24}}});
if(i==1){
pl_wizard_attack_s.AddFrame({&game->GFX_Wizard_Sheet,{vi2d{4,0}*24,{24,24}}});
pl_wizard_attack_s.AddFrame({&GFX["nico-wizard.png"],{vi2d{4,0}*24,{24,24}}});
}
}
ANIMATION_DATA["WIZARD_ATTACK_S"]=pl_wizard_attack_s;
Animate2D::FrameSequence pl_wizard_attack_e(0.2);
for(int i=0;i<3;i++){
pl_wizard_attack_e.AddFrame({&game->GFX_Wizard_Sheet,{vi2d{4+i,3}*24,{24,24}}});
pl_wizard_attack_e.AddFrame({&GFX["nico-wizard.png"],{vi2d{4+i,3}*24,{24,24}}});
if(i==1){
pl_wizard_attack_e.AddFrame({&game->GFX_Wizard_Sheet,{vi2d{4,3}*24,{24,24}}});
pl_wizard_attack_e.AddFrame({&GFX["nico-wizard.png"],{vi2d{4,3}*24,{24,24}}});
}
}
ANIMATION_DATA["WIZARD_ATTACK_E"]=pl_wizard_attack_e;
Animate2D::FrameSequence pl_wizard_attack_w(0.2);
for(int i=0;i<3;i++){
pl_wizard_attack_w.AddFrame({&game->GFX_Wizard_Sheet,{vi2d{4+i,2}*24,{24,24}}});
pl_wizard_attack_w.AddFrame({&GFX["nico-wizard.png"],{vi2d{4+i,2}*24,{24,24}}});
if(i==1){
pl_wizard_attack_w.AddFrame({&game->GFX_Wizard_Sheet,{vi2d{4,2}*24,{24,24}}});
pl_wizard_attack_w.AddFrame({&GFX["nico-wizard.png"],{vi2d{4,2}*24,{24,24}}});
}
}
ANIMATION_DATA["WIZARD_ATTACK_W"]=pl_wizard_attack_w;
Animate2D::FrameSequence pl_wizard_attack_n(0.2);
for(int i=0;i<3;i++){
pl_wizard_attack_n.AddFrame({&game->GFX_Wizard_Sheet,{vi2d{4+i,1}*24,{24,24}}});
pl_wizard_attack_n.AddFrame({&GFX["nico-wizard.png"],{vi2d{4+i,1}*24,{24,24}}});
if(i==1){
pl_wizard_attack_n.AddFrame({&game->GFX_Wizard_Sheet,{vi2d{4,1}*24,{24,24}}});
pl_wizard_attack_n.AddFrame({&GFX["nico-wizard.png"],{vi2d{4,1}*24,{24,24}}});
}
}
ANIMATION_DATA["WIZARD_ATTACK_N"]=pl_wizard_attack_n;
Animate2D::FrameSequence pl_wizard_cast_s(0.1);
for(int i=0;i<2;i++){
pl_wizard_cast_s.AddFrame({&game->GFX_Wizard_Sheet,{vi2d{7+i,0}*24,{24,24}}});
pl_wizard_cast_s.AddFrame({&GFX["nico-wizard.png"],{vi2d{7+i,0}*24,{24,24}}});
}
ANIMATION_DATA["WIZARD_CAST_S"]=pl_wizard_cast_s;
Animate2D::FrameSequence pl_wizard_cast_e(0.1);
for(int i=0;i<2;i++){
pl_wizard_cast_e.AddFrame({&game->GFX_Wizard_Sheet,{vi2d{7+i,3}*24,{24,24}}});
pl_wizard_cast_e.AddFrame({&GFX["nico-wizard.png"],{vi2d{7+i,3}*24,{24,24}}});
}
ANIMATION_DATA["WIZARD_CAST_E"]=pl_wizard_cast_e;
Animate2D::FrameSequence pl_wizard_cast_n(0.1);
for(int i=0;i<2;i++){
pl_wizard_cast_n.AddFrame({&game->GFX_Wizard_Sheet,{vi2d{7+i,1}*24,{24,24}}});
pl_wizard_cast_n.AddFrame({&GFX["nico-wizard.png"],{vi2d{7+i,1}*24,{24,24}}});
}
ANIMATION_DATA["WIZARD_CAST_N"]=pl_wizard_cast_n;
Animate2D::FrameSequence pl_wizard_cast_w(0.1);
for(int i=0;i<2;i++){
pl_wizard_cast_w.AddFrame({&game->GFX_Wizard_Sheet,{vi2d{7+i,2}*24,{24,24}}});
pl_wizard_cast_w.AddFrame({&GFX["nico-wizard.png"],{vi2d{7+i,2}*24,{24,24}}});
}
ANIMATION_DATA["WIZARD_CAST_W"]=pl_wizard_cast_w;
CreateHorizontalAnimationSequence(game->GFX_Effect_GroundSlam_Back,5,{64,64},"GROUND_SLAM_ATTACK_BACK",{0.02,Animate2D::Style::OneShot});
CreateHorizontalAnimationSequence(game->GFX_Effect_GroundSlam_Front,5,{64,64},"GROUND_SLAM_ATTACK_FRONT",{0.02,Animate2D::Style::OneShot});
CreateHorizontalAnimationSequence(game->GFX_Battlecry_Effect,5,{84,84},"BATTLECRY_EFFECT",{0.02,Animate2D::Style::OneShot});
CreateHorizontalAnimationSequence(game->GFX_SonicSlash,4,{60,60},"SONICSLASH",{0.04,Animate2D::Style::OneShot});
CreateHorizontalAnimationSequence("ground-slam-attack-back.png",5,{64,64},{0.02,Animate2D::Style::OneShot});
CreateHorizontalAnimationSequence("ground-slam-attack-front.png",5,{64,64},{0.02,Animate2D::Style::OneShot});
CreateHorizontalAnimationSequence("battlecry_effect.png",5,{84,84},{0.02,Animate2D::Style::OneShot});
CreateHorizontalAnimationSequence("sonicslash.png",4,{60,60},{0.04,Animate2D::Style::OneShot});
CreateStillAnimation(game->GFX_EnergyBolt,{24,24},"ENERGY_BOLT");
CreateStillAnimation("energy_bolt.png",{24,24});
CreateHorizontalAnimationSequence(game->GFX_EnergyParticle,3,{3,3},"ENERGY_PARTICLE");
CreateHorizontalAnimationSequence("energy_particle.png",3,{3,3});
CreateHorizontalAnimationSequence(game->GFX_Splash_Effect,5,{24,24},"SPLASH_EFFECT",{0.05});
CreateHorizontalAnimationSequence("splash_effect.png",5,{24,24},{0.05});
CreateStillAnimation(game->GFX_BulletCircle,{3,3},"DOT_PARTICLE");
CreateStillAnimation("circle.png",{3,3});
CreateHorizontalAnimationSequence(game->GFX_LightningBolt,5,{24,24},"LIGHTNING_BOLT",{0.03,Animate2D::Style::PingPong});
CreateHorizontalAnimationSequence("lightning_bolt.png",5,{24,24},{0.03,Animate2D::Style::PingPong});
CreateStillAnimation(game->GFX_LightningBoltParticle1,{5,5},"LIGHTNING_BOLT_PARTICLE1");
CreateStillAnimation(game->GFX_LightningBoltParticle2,{5,5},"LIGHTNING_BOLT_PARTICLE2");
CreateStillAnimation(game->GFX_LightningBoltParticle3,{5,5},"LIGHTNING_BOLT_PARTICLE3");
CreateStillAnimation(game->GFX_LightningBoltParticle4,{5,5},"LIGHTNING_BOLT_PARTICLE4");
CreateStillAnimation("lightning_bolt_part1.png",{5,5});
CreateStillAnimation("lightning_bolt_part2.png",{5,5});
CreateStillAnimation("lightning_bolt_part3.png",{5,5});
CreateStillAnimation("lightning_bolt_part4.png",{5,5});
CreateStillAnimation(game->GFX_ChainLightning,{1,9},"CHAIN_LIGHTNING");
CreateStillAnimation("chain_lightning.png",{1,9});
CreateHorizontalAnimationSequence(game->GFX_LightningSplash,5,{24,24},"LIGHTNING_SPLASH");
CreateHorizontalAnimationSequence("lightning_splash_effect.png",5,{24,24});
CreateStillAnimation(game->GFX_Meteor,{192,192},"METEOR");
CreateHorizontalAnimationSequence("monsters/Slime King - Cast.png",10,{24,24},{0.04});
CreateStillAnimation("meteor.png",{192,192});
for(int i=0;i<5;i++){
Animate2D::FrameSequence firering;
firering.AddFrame({&game->GFX_LightningSplash,{{i*24,0},{24,24}}});
ANIMATION_DATA["FIRE_RING"+std::to_string(i+1)]=firering;
firering.AddFrame({&GFX["fire_ring"+std::to_string(i)+".png"],{{0,0},{24,24}}});
ANIMATION_DATA["fire_ring"+std::to_string(i)+".png"]=firering;
}
CreateStillAnimation("arrow.png",{24,24});
CreateStillAnimation("charged_shot_arrow.png",{48,48});
CreateStillAnimation("laser.png",{5,1});
CreateStillAnimation("range_indicator.png",{24,24});
for(auto&dat:GFX){
std::string imgFile=dat.first;
if(!ANIMATION_DATA.count(imgFile)){
std::cout<<"WARNING! Animation data for "<<imgFile<<" not found! Auto-generating..."<<std::endl;
CreateStillAnimation(imgFile,GFX[imgFile].Sprite()->Size());
std::map<int,int>test;
test.begin();
}
}
CreateStillAnimation(game->GFX_Arrow,{24,24},"ARROW");
CreateStillAnimation(game->GFX_ChargedArrow,{48,48},"CHARGED_ARROW");
CreateStillAnimation(game->GFX_Laser,{5,1},"LASER");
CreateStillAnimation(game->GFX_RangeIndicator,{24,24},"RANGE_INDICATOR");
}
void sig::Animation::SetupPlayerAnimations(){

@ -10,7 +10,7 @@ INCLUDE_game
Arrow::Arrow(vf2d pos,vf2d targetPos,vf2d vel,float radius,int damage,bool upperLevel,bool friendly,Pixel col)
:finalDistance(geom2d::line(pos,targetPos).length()),acc(PI/2*"Ranger.Auto Attack.ArrowSpd"_F),
Bullet(pos,vel,radius,damage,
"ARROW",upperLevel,false,INFINITE,true,friendly,col){}
"arrow.png",upperLevel,false,INFINITE,true,friendly,col){}
void Arrow::Update(float fElapsedTime){
float speed=vel.mag();
@ -26,7 +26,7 @@ bool Arrow::PlayerHit(Player*player)
{
deactivated=true;
fadeOutTime=0.2f;
game->AddEffect(std::make_unique<Effect>(player->GetPos(),0,"SPLASH_EFFECT",upperLevel,player->GetSizeMult(),0.25));
game->AddEffect(std::make_unique<Effect>(player->GetPos(),0,"splash_effect.png",upperLevel,player->GetSizeMult(),0.25));
return false;
}
@ -34,6 +34,6 @@ bool Arrow::MonsterHit(Monster& monster)
{
deactivated=true;
fadeOutTime=0.2f;
game->AddEffect(std::make_unique<Effect>(monster.GetPos(),0,"SPLASH_EFFECT",upperLevel,monster.GetSizeMult(),0.25));
game->AddEffect(std::make_unique<Effect>(monster.GetPos(),0,"splash_effect.png",upperLevel,monster.GetSizeMult(),0.25));
return false;
}

@ -5,6 +5,7 @@
INCLUDE_ANIMATION_DATA
INCLUDE_game
INCLUDE_GFX
Bullet::Bullet(vf2d pos,vf2d vel,float radius,int damage,bool upperLevel,bool friendly,Pixel col,vf2d scale)
:pos(pos),vel(vel),radius(radius),damage(damage),col(col),friendly(friendly),upperLevel(upperLevel),scale(scale){};
@ -36,8 +37,8 @@ void Bullet::Draw(){
if(animated){
game->view.DrawPartialRotatedDecal(pos,GetFrame().GetSourceImage()->Decal(),rotates?atan2(vel.y,vel.x)-PI/2:0,GetFrame().GetSourceRect().size/2,GetFrame().GetSourceRect().pos,GetFrame().GetSourceRect().size,scale,fadeOutTime==0?col:Pixel{col.r,col.g,col.b,lerp(col.a,0,1-((fadeOutTime-fadeOutTimer)/fadeOutTime))});
} else {
game->view.DrawDecal(pos-game->GFX_BulletCircle.Sprite()->Size()*scale/2,game->GFX_BulletCircle.Decal(),scale,fadeOutTime==0?col:Pixel{col.r,col.g,col.b,lerp(col.a,0,1-((fadeOutTime-fadeOutTimer)/fadeOutTime))});
game->view.DrawDecal(pos-game->GFX_BulletCircle.Sprite()->Size()*scale/2,game->GFX_BulletCircleOutline.Decal(),scale,fadeOutTime==0?WHITE:Pixel{WHITE.r,WHITE.g,WHITE.b,lerp(WHITE.a,0,1-((fadeOutTime-fadeOutTimer)/fadeOutTime))});
game->view.DrawDecal(pos-GFX["circle.png"].Sprite()->Size()*scale/2,GFX["circle.png"].Decal(),scale,fadeOutTime==0?col:Pixel{col.r,col.g,col.b,lerp(col.a,0,1-((fadeOutTime-fadeOutTimer)/fadeOutTime))});
game->view.DrawDecal(pos-GFX["circle.png"].Sprite()->Size()*scale/2,GFX["circle_outline.png"].Decal(),scale,fadeOutTime==0?WHITE:Pixel{WHITE.r,WHITE.g,WHITE.b,lerp(WHITE.a,0,1-((fadeOutTime-fadeOutTimer)/fadeOutTime))});
}
}

@ -4,4 +4,4 @@ debug.sh:8125f303032b6cbc137223df63d10096 -
lines.sh:3b907786f7fc9204025993016c9080de -
release.sh:b1ce8461a303e8e7aa9ed74259db3873 -
temp:d41d8cd98f00b204e9800998ecf8427e -
web.sh:e196c0bb38ff4cd9428b4a4e56f500a9 -
web.sh:cd3b8a99e208244dee7576bc23c0dc80 -

@ -12,12 +12,12 @@ source ../emsdk/emsdk_env.sh
if [ ! -f "pixelGameEngine_wasm.o" ]
then
printf "Pixel Game Engine compile object missing. Compiling for the first time..."
em++ -std=c++20 -O2 -s ALLOW_MEMORY_GROWTH=1 -s MAXIMUM_MEMORY=4GB -s MAX_WEBGL_VERSION=2 -s MIN_WEBGL_VERSION=2 -s USE_SDL_MIXER=2 -s USE_LIBPNG=1 -c pixelGameEngine.cpp -o pixelGameEngine_wasm.o
em++ -std=c++20 -O2 ${EMSCRIPTEN_CUSTOM_PARAMS} -s ALLOW_MEMORY_GROWTH=1 -s MAXIMUM_MEMORY=4GB -s MAX_WEBGL_VERSION=2 -s MIN_WEBGL_VERSION=2 -s USE_SDL_MIXER=2 -s USE_LIBPNG=1 -c pixelGameEngine.cpp -o pixelGameEngine_wasm.o
fi
if [ -d "assets" ]; then
em++ -std=c++20 -O2 -s ALLOW_MEMORY_GROWTH=1 -s MAXIMUM_MEMORY=4GB -s MAX_WEBGL_VERSION=2 -s MIN_WEBGL_VERSION=2 -s USE_SDL_MIXER=2 -s USE_LIBPNG=1 $(find . -type f -name "*.cpp" -not -path "./test/*" -not -name "pixelGameEngine.cpp") pixelGameEngine_wasm.o -o ${PROJECT_NAME}.html --preload-file ./assets
em++ -std=c++20 -O2 ${EMSCRIPTEN_CUSTOM_PARAMS} -s ALLOW_MEMORY_GROWTH=1 -s MAXIMUM_MEMORY=4GB -s MAX_WEBGL_VERSION=2 -s MIN_WEBGL_VERSION=2 -s USE_SDL_MIXER=2 -s USE_LIBPNG=1 $(find . -type f -name "*.cpp" -not -path "./test/*" -not -name "pixelGameEngine.cpp") pixelGameEngine_wasm.o -o ${PROJECT_NAME}.html --preload-file ./assets
else
em++ -std=c++20 -O2 -s ALLOW_MEMORY_GROWTH=1 -s MAXIMUM_MEMORY=4GB -s MAX_WEBGL_VERSION=2 -s MIN_WEBGL_VERSION=2 -s USE_SDL_MIXER=2 -s USE_LIBPNG=1 $(find . -type f -name "*.cpp" -not -path "./test/*" -not -name "pixelGameEngine.cpp") pixelGameEngine_wasm.o -o ${PROJECT_NAME}.html
em++ -std=c++20 -O2 ${EMSCRIPTEN_CUSTOM_PARAMS} -s ALLOW_MEMORY_GROWTH=1 -s MAXIMUM_MEMORY=4GB -s MAX_WEBGL_VERSION=2 -s MIN_WEBGL_VERSION=2 -s USE_SDL_MIXER=2 -s USE_LIBPNG=1 $(find . -type f -name "*.cpp" -not -path "./test/*" -not -name "pixelGameEngine.cpp") pixelGameEngine_wasm.o -o ${PROJECT_NAME}.html
fi
cp buildtemplate.html ${PROJECT_NAME}.html

@ -10,14 +10,14 @@ INCLUDE_game
ChargedArrow::ChargedArrow(vf2d pos,vf2d vel,float radius,int damage,bool upperLevel,bool friendly,Pixel col)
:lastLaserPos(pos),
Bullet(pos,vel,radius,damage,
"CHARGED_ARROW",upperLevel,true,INFINITE,true,friendly,col){}
"charged_shot_arrow.png",upperLevel,true,INFINITE,true,friendly,col){}
void ChargedArrow::Update(float fElapsedTime){
geom2d::line lineToCurrentPos(geom2d::line(lastLaserPos,pos));
float dist=lineToCurrentPos.length();
if(dist>=1){
vf2d midpoint(lineToCurrentPos.rpoint(0.5));
game->AddEffect(std::make_unique<Effect>(midpoint,0.1,"LASER",upperLevel,vf2d{1,dist},0.3,vf2d{},Pixel{192,128,238},atan2(pos.y-lastLaserPos.y,pos.x-lastLaserPos.x)+PI/2,0,true));
game->AddEffect(std::make_unique<Effect>(midpoint,0.1,"laser.png",upperLevel,vf2d{1,dist},0.3,vf2d{},Pixel{192,128,238},atan2(pos.y-lastLaserPos.y,pos.x-lastLaserPos.x)+PI/2,0,true));
lastLaserPos=pos;
}
}

@ -0,0 +1,665 @@
<?xml version="1.0" encoding="utf-8"?>
<ClassDiagram MajorVersion="1" MinorVersion="1">
<Class Name="Crawler" Collapsed="true">
<Position X="3.5" Y="13.75" Width="1.5" />
<TypeIdentifier>
<HashCode>OihgwhJkUjgrCYAAVgEdFoQkBECSBhEDncMJIEmEYAg=</HashCode>
<FileName>Crawler.h</FileName>
</TypeIdentifier>
</Class>
<Class Name="Effect" Collapsed="true">
<Position X="13.75" Y="3.5" Width="1.5" />
<TypeIdentifier>
<HashCode>BAAAAAQAQAgEAAAEAIBAAAAAAAAEAAAAAAgAgAAACAA=</HashCode>
<FileName>C:\Program Files (x86)\Windows Kits\10\Include\10.0.22000.0\um\gdipluseffects.h</FileName>
</TypeIdentifier>
</Class>
<Class Name="LightningBoltEmitter" Collapsed="true">
<Position X="6.5" Y="13.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAEAAIAAABAAABAAAAAAAAAAAAAAEAI=</HashCode>
<FileName>Emitter.h</FileName>
</TypeIdentifier>
</Class>
<Class Name="olc::Decal" Collapsed="true">
<Position X="20.75" Y="1.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAQAAAAAAAAQAAAAAAAAAAAAABAAAAAAUAEAAAAAAgA=</HashCode>
<FileName>olcPixelGameEngine.h</FileName>
</TypeIdentifier>
</Class>
<Class Name="olc::GDIPlusStartup" Collapsed="true">
<Position X="26" Y="1.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAEBAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>olcPixelGameEngine.h</FileName>
</TypeIdentifier>
</Class>
<Class Name="olc::ImageLoader" Collapsed="true">
<Position X="11" Y="9.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAIAAAAAAAAAAAACAAAAAAAAAAIAAgAAAAAAAAAA=</HashCode>
<FileName>olcPixelGameEngine.h</FileName>
</TypeIdentifier>
</Class>
<Class Name="olc::ImageLoader_GDIPlus" Collapsed="true">
<Position X="13.25" Y="10.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAIAAAAAAAAAAAAAAAAIAAAAAAAAAgAAAAAAACAA=</HashCode>
<FileName>olcPixelGameEngine.h</FileName>
</TypeIdentifier>
</Class>
<Class Name="olc::ImageLoader_LibPNG" Collapsed="true">
<Position X="8.75" Y="10.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAABIAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAA=</HashCode>
<FileName>olcPixelGameEngine.h</FileName>
</TypeIdentifier>
</Class>
<Class Name="olc::ImageLoader_STB" Collapsed="true">
<Position X="11" Y="10.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAABA=</HashCode>
<FileName>olcPixelGameEngine.h</FileName>
</TypeIdentifier>
</Class>
<Class Name="olc::PGEX" Collapsed="true">
<Position X="0.5" Y="12.5" Width="1.5" />
<TypeIdentifier>
<HashCode>gAAAAAAAABAIAACAAAAgAAAAAAAAAAAAAAAAAAAAgAA=</HashCode>
<FileName>olcPixelGameEngine.h</FileName>
</TypeIdentifier>
</Class>
<Class Name="olc::PixelGameEngine" Collapsed="true">
<Position X="3.5" Y="12.5" Width="1.5" />
<TypeIdentifier>
<HashCode>S5fpQ8sYZfjd1v02mw8U0Ed9QaLH2ByFmPRdWNHpuzs=</HashCode>
<FileName>olcPixelGameEngine.h</FileName>
</TypeIdentifier>
</Class>
<Class Name="olc::Platform" Collapsed="true">
<Position X="5.25" Y="3.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAIgAAAEAAAABAAAAAAAACAIAAAAAAAAQAEiAAACAA=</HashCode>
<FileName>olcPixelGameEngine.h</FileName>
</TypeIdentifier>
</Class>
<Class Name="olc::Platform_Emscripten" Collapsed="true">
<Position X="9.75" Y="4.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAIgAAAEQACAQAAAAAAhACAIAQAAAAAAYAEiAAAAAA=</HashCode>
<FileName>olcPixelGameEngine.h</FileName>
</TypeIdentifier>
</Class>
<Class Name="olc::Platform_GLUT" Collapsed="true">
<Position X="0.75" Y="4.75" Width="1.5" />
<TypeIdentifier>
<HashCode>gAgIgAAAEAQAAAAAAAAAAACAJAAAQAAAAQAEiAAAAAA=</HashCode>
<FileName>olcPixelGameEngine.h</FileName>
</TypeIdentifier>
</Class>
<Class Name="olc::Platform_Headless" Collapsed="true">
<Position X="3" Y="4.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAIgAAAEAAAAAAAAAAAAACAIAAAAAAAAQAEiAAAAAA=</HashCode>
<FileName>olcPixelGameEngine.h</FileName>
</TypeIdentifier>
</Class>
<Class Name="olc::Platform_Linux" Collapsed="true">
<Position X="5.25" Y="4.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAIgSAAEAAAgAAAAAAAAACAICgAAAAAAUAEiAAAAAA=</HashCode>
<FileName>olcPixelGameEngine.h</FileName>
</TypeIdentifier>
</Class>
<Class Name="olc::Platform_Windows" Collapsed="true">
<Position X="7.5" Y="4.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAIgEAAEAAAABAAAAAAAAOAIAAAAAAAAUAEiAAAAQA=</HashCode>
<FileName>olcPixelGameEngine.h</FileName>
</TypeIdentifier>
</Class>
<Class Name="olc::Renderable" Collapsed="true">
<Position X="17.25" Y="2.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAQAgAAAAAQAAAAAAAAAAAgAAAAAAEAQEAAAAAAAAAA=</HashCode>
<FileName>olcPixelGameEngine.h</FileName>
</TypeIdentifier>
</Class>
<Class Name="olc::Renderer" Collapsed="true">
<Position X="3" Y="9.5" Width="1.5" />
<TypeIdentifier>
<HashCode>SAAgAAAAAIBASAAACAAAAgAAAAAEAIBAAIBAAAEACgA=</HashCode>
<FileName>olcPixelGameEngine.h</FileName>
</TypeIdentifier>
</Class>
<Class Name="olc::Renderer_Headless" Collapsed="true">
<Position X="0.75" Y="10.75" Width="1.5" />
<TypeIdentifier>
<HashCode>SAAAAAAAAIBASAAACAAAAgAAAAAEAIBAAIBAAAEAAgA=</HashCode>
<FileName>olcPixelGameEngine.h</FileName>
</TypeIdentifier>
</Class>
<Class Name="olc::Renderer_OGL10" Collapsed="true">
<Position X="3" Y="10.75" Width="1.5" />
<TypeIdentifier>
<HashCode>SAAAASAAQIBASCAACAAAAgAAAAAGAIBAAMJUAAEAAgA=</HashCode>
<FileName>olcPixelGameEngine.h</FileName>
</TypeIdentifier>
</Class>
<Class Name="olc::Renderer_OGL33" Collapsed="true">
<Position X="5.25" Y="10.75" Width="1.5" />
<TypeIdentifier>
<HashCode>SCghAyFBQIBWSCIAGAAAIgABQAAGBJhBAsJMEEEACgg=</HashCode>
<FileName>olcPixelGameEngine.h</FileName>
</TypeIdentifier>
</Class>
<Class Name="olc::ResourcePack" Collapsed="true">
<Position X="19" Y="2.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAgAAAAAEAAAIAAIBAIAgAAAAAAAAAAAACgIAIAAA=</HashCode>
<FileName>olcPixelGameEngine.h</FileName>
</TypeIdentifier>
</Class>
<Class Name="olc::Sprite" Collapsed="true">
<Position X="22.5" Y="2.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAABABBAEAAQgAQBQAAAAABAAAAAIAAQAAEAAgAAEAI=</HashCode>
<FileName>olcPixelGameEngine.h</FileName>
</TypeIdentifier>
</Class>
<Class Name="olc::TileTransformedView" Collapsed="true">
<Position X="0.5" Y="15.25" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAABAAAAAAAEAAAAAEAAAAAAAIAAAAEAIA=</HashCode>
<FileName>olcPGEX_TransformedView.h</FileName>
</TypeIdentifier>
</Class>
<Class Name="olc::TransformedView" Collapsed="true">
<Position X="0.5" Y="13.75" Width="1.5" />
<TypeIdentifier>
<HashCode>ABXBQAQAAFAGAzQACAMCyEQSUAAECDAQAsDE4AAIAog=</HashCode>
<FileName>olcPGEX_TransformedView.h</FileName>
</TypeIdentifier>
</Class>
<Class Name="olc::utils::Camera2D" Collapsed="true">
<Position X="20.75" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>JDQCAAACoCBAAhIBBAAAAAiAAAgAECAAAAIAAXAAARY=</HashCode>
<FileName>olcUTIL_Camera2D.h</FileName>
</TypeIdentifier>
</Class>
<Class Name="olc::utils::datafile" Collapsed="true">
<Position X="22.5" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>EgACAAIAMCAAAAIIAEAABAAgAQEAACAAAAACCAGAAIA=</HashCode>
<FileName>olcUTIL_DataFile.h</FileName>
</TypeIdentifier>
</Class>
<Class Name="olc::utils::datafiledoubledata" Collapsed="true">
<Position X="24.25" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAIAAAAAAAAAAAAAAEAAAAAAEAAAAAAAAQAAAAAAA=</HashCode>
<FileName>olcUTIL_DataFile.h</FileName>
</TypeIdentifier>
</Class>
<Class Name="olc::utils::datafilefloatdata" Collapsed="true">
<Position X="26" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAEAAAAAAECAAAAAAAQAAAAAAA=</HashCode>
<FileName>olcUTIL_DataFile.h</FileName>
</TypeIdentifier>
</Class>
<Class Name="olc::utils::datafileintdata" Collapsed="true">
<Position X="17.25" Y="1.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAEAAAAAAUAAAAAAAAQAAAAAAA=</HashCode>
<FileName>olcUTIL_DataFile.h</FileName>
</TypeIdentifier>
</Class>
<Class Name="olc::utils::datafilestringdata" Collapsed="true">
<Position X="19" Y="1.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAgAAAAAAAAAAAAAAAEAAAAAAEAAAAAAAAQAAAAAAA=</HashCode>
<FileName>olcUTIL_DataFile.h</FileName>
</TypeIdentifier>
</Class>
<Class Name="olc::utils::Animate2D::Animation&lt;StatesEnum&gt;" Collapsed="true">
<Position X="19" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAEAAAAAEABAAAgIAAAAAAAAAAAAAAAAAABAAACAA=</HashCode>
<FileName>olcUTIL_Animate2D.h</FileName>
</TypeIdentifier>
</Class>
<Class Name="olc::utils::Animate2D::Frame" Collapsed="true">
<Position X="22.5" Y="1.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAEAAAEAAAAAIE=</HashCode>
<FileName>olcUTIL_Animate2D.h</FileName>
</TypeIdentifier>
</Class>
<Class Name="olc::utils::Animate2D::FrameSequence" Collapsed="true">
<Position X="24.25" Y="1.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAEAAAACAAAAEAAAAABAAAEAAAAAAAAEAAgBAAAAA=</HashCode>
<FileName>olcUTIL_Animate2D.h</FileName>
</TypeIdentifier>
</Class>
<Class Name="safemap&lt;T, O&gt;" Collapsed="true">
<Position X="20.75" Y="2.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAEAAAABAAEAAAAAAAAAAAAAEAAAAAAAAAAAAAAAA=</HashCode>
<FileName>safemap.h</FileName>
</TypeIdentifier>
</Class>
<Class Name="sig::Animation" Collapsed="true">
<Position X="17.25" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>ACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAA=</HashCode>
<FileName>Animation.h</FileName>
</TypeIdentifier>
</Class>
<Class Name="TMXParser" Collapsed="true">
<Position X="24.25" Y="2.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAEAABYQAAAAAEAAAAACABIAAAKAAAAAAAAAA=</HashCode>
<FileName>TMXParser.h</FileName>
</TypeIdentifier>
</Class>
<Class Name="TSXParser" Collapsed="true">
<Position X="26" Y="2.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAIAAAAEEAAAAAAAAAAAAAAAAAAAAAAAIgAACAAQAAA=</HashCode>
<FileName>TSXParser.h</FileName>
</TypeIdentifier>
</Class>
<Struct Name="Ability" Collapsed="true">
<Position X="17.25" Y="3.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAABAAAAAAAAwACABAAAAAAACAEAAACAAAAAAAAAAA=</HashCode>
<FileName>Ability.h</FileName>
</TypeIdentifier>
</Struct>
<Struct Name="AnimationData" Collapsed="true">
<Position X="19" Y="3.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAEAAAAAAAAAEAAAAAAAAAAAAAAA=</HashCode>
<FileName>Animation.h</FileName>
</TypeIdentifier>
</Struct>
<Struct Name="Arrow" Collapsed="true">
<Position X="9.75" Y="7.75" Width="1.5" />
<TypeIdentifier>
<HashCode>CAQAQAAAAAABAAAAAIgAAAAAAAAAAAAAAAgAAAAAAAA=</HashCode>
<FileName>BulletTypes.h</FileName>
</TypeIdentifier>
</Struct>
<Struct Name="Buff" Collapsed="true">
<Position X="22.5" Y="3.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAIAAAAAAAAAAAAAAAAAAAABCAAAAAAAAAAAAAA=</HashCode>
<FileName>Buff.h</FileName>
</TypeIdentifier>
</Struct>
<Struct Name="Bullet" Collapsed="true">
<Position X="5.25" Y="6.5" Width="1.5" />
<TypeIdentifier>
<HashCode>CgREEAAACAAAggAAIKgABYACAAAAABAMAEAAgQBQAgA=</HashCode>
<FileName>Bullet.h</FileName>
</TypeIdentifier>
</Struct>
<Struct Name="CastInfo" Collapsed="true">
<Position X="24.25" Y="3.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAABAAAEAAAAAIAACAAAAAA=</HashCode>
<FileName>Player.h</FileName>
</TypeIdentifier>
</Struct>
<Struct Name="ChargedArrow" Collapsed="true">
<Position X="0.75" Y="7.75" Width="1.5" />
<TypeIdentifier>
<HashCode>CAQAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAABAAAAAAAE=</HashCode>
<FileName>BulletTypes.h</FileName>
</TypeIdentifier>
</Struct>
<Struct Name="DamageNumber" Collapsed="true">
<Position X="26" Y="3.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAgAAAAAIAAAwAAAAAAAAIACAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>DamageNumber.h</FileName>
</TypeIdentifier>
</Struct>
<Struct Name="Emitter" Collapsed="true">
<Position X="6.5" Y="12.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAQAAAgAAAAAAAAAAAAAABAABAAAAACIAAgAAAAAAAA=</HashCode>
<FileName>Emitter.h</FileName>
</TypeIdentifier>
</Struct>
<Struct Name="EnergyBolt" Collapsed="true">
<Position X="5.25" Y="7.75" Width="1.5" />
<TypeIdentifier>
<HashCode>CAQAAAAACAAAAAAAAAgAAAAAAAAEAAAAAAAAAAAAAAA=</HashCode>
<FileName>BulletTypes.h</FileName>
</TypeIdentifier>
</Struct>
<Struct Name="FireBolt" Collapsed="true">
<Position X="7.5" Y="7.75" Width="1.5" />
<TypeIdentifier>
<HashCode>CAQAAAAAAAAAAAAAAAgAAAAAAAAEAAAAAAAAAAAQAAA=</HashCode>
<FileName>BulletTypes.h</FileName>
</TypeIdentifier>
</Struct>
<Struct Name="LayerTag" Collapsed="true">
<Position X="22.5" Y="4.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAACAAAAAAAAAAAAAAAAAAAgAAACAAAAAAAAAAAAA=</HashCode>
<FileName>TMXParser.h</FileName>
</TypeIdentifier>
</Struct>
<Struct Name="LightningBolt" Collapsed="true">
<Position X="3" Y="7.75" Width="1.5" />
<TypeIdentifier>
<HashCode>CAQAAAAAAAAAAAAAAAgAAAAAAAAkAAAAAAAAAAAAAAA=</HashCode>
<FileName>BulletTypes.h</FileName>
</TypeIdentifier>
</Struct>
<Struct Name="Map" Collapsed="true">
<Position X="24.25" Y="4.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAQAAAQAAAAQAAACAAAAAAAAAAAAAAAACACAAEAAAAA=</HashCode>
<FileName>TMXParser.h</FileName>
</TypeIdentifier>
</Struct>
<Struct Name="MapTag" Collapsed="true">
<Position X="26" Y="4.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAIAAAAAAQAQAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>TMXParser.h</FileName>
</TypeIdentifier>
</Struct>
<Struct Name="Meteor" Collapsed="true">
<Position X="12.5" Y="4.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAQAAAAAAAAAQgAAAAEAAAAAAAAAAAAAAAAAAACAAAA=</HashCode>
<FileName>Effect.h</FileName>
</TypeIdentifier>
</Struct>
<Struct Name="Monster" Collapsed="true">
<Position X="17.25" Y="5.75" Width="1.5" />
<Compartments>
<Compartment Name="Nested Types" Collapsed="false" />
</Compartments>
<NestedTypes>
<Struct Name="Monster::STRATEGY" Collapsed="true">
<TypeIdentifier>
<NewMemberFileName>Monster.h</NewMemberFileName>
</TypeIdentifier>
</Struct>
</NestedTypes>
<TypeIdentifier>
<HashCode>FSSAFFAEAKB4CxYAIKAOBIgBIYYC8gAEikFMCRCwkgE=</HashCode>
<FileName>Monster.h</FileName>
</TypeIdentifier>
</Struct>
<Struct Name="MonsterData" Collapsed="true">
<Position X="19" Y="5.75" Width="1.5" />
<TypeIdentifier>
<HashCode>EAAACGAAsABAAQEQAIAAgAAQAAAEECAQgABAAiAQIkA=</HashCode>
<FileName>Monster.h</FileName>
</TypeIdentifier>
</Struct>
<Struct Name="MonsterSpawner" Collapsed="true">
<Position X="20.75" Y="5.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAIQAAAAAAAAIgIAIgAAAAAAAAAAAgBAgAAgAA=</HashCode>
<FileName>Monster.h</FileName>
</TypeIdentifier>
</Struct>
<Struct Name="olc::DecalInstance" Collapsed="true">
<Position X="17.25" Y="4.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AgAAAACAAAAAAACAAAAAAIAAAAAQBAAAAAgAAAAAAgA=</HashCode>
<FileName>olcPixelGameEngine.h</FileName>
</TypeIdentifier>
</Struct>
<Struct Name="olc::HWButton" Collapsed="true">
<Position X="19" Y="4.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAgAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAgA=</HashCode>
<FileName>olcPixelGameEngine.h</FileName>
</TypeIdentifier>
</Struct>
<Struct Name="olc::LayerDesc" Collapsed="true">
<Position X="20.75" Y="4.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AkAIAAAAAAAAABAABQAACAAAAAABQAAAAAAAAAAAAAA=</HashCode>
<FileName>olcPixelGameEngine.h</FileName>
</TypeIdentifier>
</Struct>
<Struct Name="olc::Pixel" Collapsed="true">
<Position X="24.25" Y="5.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAIAAAAAAAAAAAAAABAQAAAAAAAAAAAAAgAAAAAAA=</HashCode>
<FileName>olcPixelGameEngine.h</FileName>
</TypeIdentifier>
</Struct>
<Struct Name="olc::ResourceBuffer" Collapsed="true">
<Position X="17.25" Y="6.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAIAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAA=</HashCode>
<FileName>olcPixelGameEngine.h</FileName>
</TypeIdentifier>
</Struct>
<Struct Name="olc::utils::Animate2D::AnimationState" Collapsed="true">
<Position X="20.75" Y="3.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAA=</HashCode>
<FileName>olcUTIL_Animate2D.h</FileName>
</TypeIdentifier>
</Struct>
<Struct Name="Pathfinding" Collapsed="true">
<Position X="22.5" Y="5.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAQAEAAgAAAAAAAAAAAAAQAAAAAAAIAA=</HashCode>
<FileName>Pathfinding.h</FileName>
</TypeIdentifier>
</Struct>
<Struct Name="Player" Collapsed="true">
<Position X="6.5" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>EO9g1XQE4IJq4TbQBqAlYY0RO0YCNkh05FFEjTtkojQ=</HashCode>
<FileName>Player.h</FileName>
</TypeIdentifier>
</Struct>
<Struct Name="PrecastData" Collapsed="true">
<Position X="26" Y="5.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAIAAAAAAAEAIAAAAABAAAAAAAAAAAgAAAAAAA=</HashCode>
<FileName>Ability.h</FileName>
</TypeIdentifier>
</Struct>
<Struct Name="PulsatingFire" Collapsed="true">
<Position X="14.75" Y="4.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAQBAAAAAAAAAgAAAAAAAEAAAAAAAAAAAAAAEAAAAAE=</HashCode>
<FileName>Effect.h</FileName>
</TypeIdentifier>
</Struct>
<Struct Name="Ranger" Collapsed="true">
<Position X="3.25" Y="1.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAkAwQEAQAAIqQBQAAAEIAQACAAEMgAABAAEAAkgAgA=</HashCode>
<FileName>Player.h</FileName>
</TypeIdentifier>
</Struct>
<Struct Name="SpawnerTag" Collapsed="true">
<Position X="19" Y="6.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAQAAIAAAAAIAAAAAAAAAAACAAAAAAAAAAAAA=</HashCode>
<FileName>TMXParser.h</FileName>
</TypeIdentifier>
</Struct>
<Struct Name="Thief" Collapsed="true">
<Position X="7.75" Y="1.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAkAwQEAYAAIoQBQAAAEIAQACAAEMgAABAAEAAkgAgA=</HashCode>
<FileName>Player.h</FileName>
</TypeIdentifier>
</Struct>
<Struct Name="TileCollisionData" Collapsed="true">
<Position X="20.75" Y="6.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>Map.h</FileName>
</TypeIdentifier>
</Struct>
<Struct Name="TileGroup" Collapsed="true">
<Position X="22.5" Y="6.75" Width="1.5" />
<TypeIdentifier>
<HashCode>CDAAAAAISAgAAAAAAAAAAAAAAgAAACAAAAkAADAAQAA=</HashCode>
<FileName>Map.h</FileName>
</TypeIdentifier>
</Struct>
<Struct Name="TileRenderData" Collapsed="true">
<Position X="24.25" Y="6.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAEAAAAAAAAAAAAAIAAQAAAAAAAIAAAAAAAAAA=</HashCode>
<FileName>Map.h</FileName>
</TypeIdentifier>
</Struct>
<Struct Name="Tileset" Collapsed="true">
<Position X="26" Y="6.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAIAAAgAAAAAAgAAAAIAAAQAAAAAAAAAABAAAAAA=</HashCode>
<FileName>TSXParser.h</FileName>
</TypeIdentifier>
</Struct>
<Struct Name="TilesetData" Collapsed="true">
<Position X="17.25" Y="7.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAgAAAAAAAAAAAAAAAAIAAAAAAAAAAIAAEAQIAAAA=</HashCode>
<FileName>Map.h</FileName>
</TypeIdentifier>
</Struct>
<Struct Name="TilesheetData" Collapsed="true">
<Position X="19" Y="7.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAIAAAAAAAAAA=</HashCode>
<FileName>Crawler.h</FileName>
</TypeIdentifier>
</Struct>
<Struct Name="Trapper" Collapsed="true">
<Position X="1" Y="1.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAkAwQEAQAAIoQBQAAAEIAQECAAEMgAABAAEAAkgAgA=</HashCode>
<FileName>Player.h</FileName>
</TypeIdentifier>
</Struct>
<Struct Name="Warrior" Collapsed="true">
<Position X="12.25" Y="1.75" Width="1.5" />
<TypeIdentifier>
<HashCode>ACkAgQEAQAAIoQBQAAAEAAQACAAEIgAAAAAEAAkAAgA=</HashCode>
<FileName>Player.h</FileName>
</TypeIdentifier>
</Struct>
<Struct Name="Witch" Collapsed="true">
<Position X="10" Y="1.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAkAwQEAQAAIoQBQAAAEKAQACAAEMgAABAAEAAkgAgA=</HashCode>
<FileName>Player.h</FileName>
</TypeIdentifier>
</Struct>
<Struct Name="Wizard" Collapsed="true">
<Position X="5.5" Y="1.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAkAwQEAQAAIoQBQAAAEIAQACAAEMgAABAIEAAkgAgA=</HashCode>
<FileName>Player.h</FileName>
</TypeIdentifier>
</Struct>
<Struct Name="XMLTag" Collapsed="true">
<Position X="20.75" Y="7.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AACAACAgACAAAIAAAAAAAAAAAAAAACAAAAAQAAAAQAA=</HashCode>
<FileName>TMXParser.h</FileName>
</TypeIdentifier>
</Struct>
<Enum Name="Attribute" Collapsed="true">
<Position X="17.25" Y="9" Width="1.5" />
<TypeIdentifier>
<HashCode>AQQBgAAAAAoAAIAAAAAAAAIAJAAAAACAAAAAAAAAAAI=</HashCode>
<FileName>MonsterAttribute.h</FileName>
</TypeIdentifier>
</Enum>
<Enum Name="BuffType" Collapsed="true">
<Position X="19" Y="9" Width="1.5" />
<TypeIdentifier>
<HashCode>AAgAIAAAAAAAAAAAAAAAAAAAAEAgAAAAAAAAAAAAAAA=</HashCode>
<FileName>Buff.h</FileName>
</TypeIdentifier>
</Enum>
<Enum Name="Class" Collapsed="true">
<Position X="20.75" Y="9" Width="1.5" />
<TypeIdentifier>
<HashCode>AACAAAAAAAAAAAAAAAgAAAAEAAggAAAAAAAAAAAACAA=</HashCode>
<FileName>Class.h</FileName>
</TypeIdentifier>
</Enum>
<Enum Name="MapName" Collapsed="true">
<Position X="17.25" Y="9.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAABAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>Map.h</FileName>
</TypeIdentifier>
</Enum>
<Enum Name="MonsterAnimation" Collapsed="true">
<Position X="19" Y="9.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAEAAAAAAAAgAAACAAAAAAAQAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>Monster.h</FileName>
</TypeIdentifier>
</Enum>
<Enum Name="olc::DecalMode" Collapsed="true">
<Position X="22.5" Y="9" Width="1.5" />
<TypeIdentifier>
<HashCode>AAgAAAAAACCAAAAAABAAAIAAAAAAAAAAAAAgAAAABAA=</HashCode>
<FileName>olcPixelGameEngine.h</FileName>
</TypeIdentifier>
</Enum>
<Enum Name="olc::DecalStructure" Collapsed="true">
<Position X="24.25" Y="9" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAACAAAAAAAAAAAAAIAAAAEQAAAAAAAAAAAAAAA=</HashCode>
<FileName>olcPixelGameEngine.h</FileName>
</TypeIdentifier>
</Enum>
<Enum Name="olc::Key" Collapsed="true">
<Position X="26" Y="9" Width="1.5" />
<TypeIdentifier>
<HashCode>IgBKPCYRIAQCigCAAQAAwU8kkgMKYJhzAAAAvv//YQE=</HashCode>
<FileName>olcPixelGameEngine.h</FileName>
</TypeIdentifier>
</Enum>
<Enum Name="olc::rcode" Collapsed="true">
<Position X="20.75" Y="9.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAgCA=</HashCode>
<FileName>olcPixelGameEngine.h</FileName>
</TypeIdentifier>
</Enum>
<Enum Name="olc::utils::Animate2D::Style" Collapsed="true">
<Position X="24.25" Y="9.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAQAAAAAAAAACAAAAAAAAICAAAAAAA=</HashCode>
<FileName>olcUTIL_Animate2D.h</FileName>
</TypeIdentifier>
</Enum>
<Enum Name="State::State" Collapsed="true">
<Position X="22.5" Y="9.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAABAQCAAgCAACABABEBKAgACAAAABAgAAAAAAAA=</HashCode>
<FileName>State.h</FileName>
</TypeIdentifier>
</Enum>
<Font Name="Segoe UI" Size="9" />
</ClassDiagram>

Binary file not shown.

After

Width:  |  Height:  |  Size: 164 KiB

Binary file not shown.

@ -26,6 +26,7 @@ std::vector<Monster>MONSTER_LIST;
std::vector<MonsterSpawner>SPAWNER_LIST;
std::vector<std::shared_ptr<DamageNumber>>DAMAGENUMBER_LIST;
std::vector<std::unique_ptr<Bullet>>BULLET_LIST;
safemap<std::string,Renderable>GFX;
safemap<std::string,MapName>LEVEL_NAMES;
utils::datafile DATA;
Crawler*game;
@ -62,6 +63,8 @@ Crawler::Crawler()
std::string MONSTERSTRATEGIES_CONFIG = CONFIG_PATH + "monsterstrategies_config"_S;
utils::datafile::Read(DATA,MONSTERSTRATEGIES_CONFIG);
DEBUG_PATHFINDING="debug_pathfinding"_I;
for(std::string&cl:DATA.GetProperty("class_list").GetValues()){
std::cout<<cl<<std::endl;
utils::datafile::Read(DATA,CONFIG_PATH + "class_directory"_S + cl + ".txt");
@ -70,7 +73,6 @@ Crawler::Crawler()
}
bool Crawler::OnUserCreate(){
InitializeLevels();
player=std::make_unique<Warrior>();
@ -82,41 +84,18 @@ bool Crawler::OnUserCreate(){
camera.SetWorldBoundary({0,0},WORLD_SIZE*24);
camera.EnableWorldBoundary(false);
#undef LoadImage //Dumb Windows.
auto LoadImage=[&](Renderable&r,std::string key){
r.Load(GetString("GFX_Prefix")+GetString(key));
};
#define LOADIMG(name) LoadImage(name,"Images."#name);
//Graphics
LOADIMG(GFX_Warrior_Sheet)
LOADIMG(GFX_Circle)
LOADIMG(GFX_Effect_GroundSlam_Back)
LOADIMG(GFX_Effect_GroundSlam_Front)
LOADIMG(GFX_Heart)
LOADIMG(GFX_BLOCK_BUBBLE)
LOADIMG(GFX_Ranger_Sheet)
LOADIMG(GFX_Wizard_Sheet)
LOADIMG(GFX_Battlecry_Effect)
LOADIMG(GFX_Mana)
LOADIMG(GFX_SonicSlash)
LOADIMG(GFX_BulletCircle)
LOADIMG(GFX_BulletCircleOutline)
LOADIMG(GFX_EnergyBolt)
LOADIMG(GFX_EnergyParticle)
LOADIMG(GFX_Splash_Effect)
LOADIMG(GFX_LightningBolt)
LOADIMG(GFX_LightningBoltParticle1)
LOADIMG(GFX_LightningBoltParticle2)
LOADIMG(GFX_LightningBoltParticle3)
LOADIMG(GFX_LightningBoltParticle4)
LOADIMG(GFX_ChainLightning)
LOADIMG(GFX_LightningSplash)
LOADIMG(GFX_Meteor)
LOADIMG(GFX_Arrow)
LOADIMG(GFX_Laser)
LOADIMG(GFX_ChargedArrow)
LOADIMG(GFX_RangeIndicator)
for(auto&val:DATA["Images"].GetKeys()){
std::string key=val.first;
std::string imgFile=DATA["Images"][key].GetString();
std::cout<<"Loading image "+imgFile+"..."<<std::endl;
GFX[imgFile];
if(GFX[imgFile].Load("GFX_Prefix"_S+imgFile)!=rcode::OK){
std::cout<<" WARNING! Failed to load "+imgFile+"!";
throw;
}
}
GFX.SetInitialized();
std::cout<<GFX.size()<<" images have been loaded."<<std::endl;
Monster::InitializeStrategies();
//Animations
@ -130,18 +109,22 @@ bool Crawler::OnUserCreate(){
InitializeClasses();
ChangePlayerClass(WARRIOR);
Warrior::ability4=Ranger::ability1; //Class ability swapping demonstration.
return true;
}
bool Crawler::OnUserUpdate(float fElapsedTime){
fElapsedTime=std::clamp(fElapsedTime,0.f,1/60.f); //HACK fix. We can't have a negative time. Although using a more precise system clock should make this never occur. Also make sure if the game is too slow we advance by only 1/60th of a second.
fElapsedTime=std::clamp(fElapsedTime,0.f,1/30.f); //HACK fix. We can't have a negative time. Although using a more precise system clock should make this never occur. Also make sure if the game is too slow we advance by only 1/30th of a second.
levelTime+=fElapsedTime;
HandleUserInput(fElapsedTime);
UpdateEffects(fElapsedTime);
player->Update(fElapsedTime);
for(Monster&m:MONSTER_LIST){
m.Update(fElapsedTime);
}
for(Monster&m:monstersToBeSpawned){
MONSTER_LIST.push_back(m);
}
monstersToBeSpawned.clear();
UpdateBullets(fElapsedTime);
UpdateCamera(fElapsedTime);
RenderWorld(fElapsedTime);
@ -212,8 +195,8 @@ void Crawler::HandleUserInput(float fElapsedTime){
int truncatedPlayerY=int(player->GetY())/24;
int tileID=layer.tiles[truncatedPlayerY][truncatedPlayerX];
TilesheetData dat=GetTileSheet(GetCurrentLevel(),tileID);
if (dat.tileset.staircaseTiles.find(tileID)!=dat.tileset.staircaseTiles.end()){
return dat.tileset.staircaseTiles[tileID].data["value"];
if (dat.tileset->staircaseTiles.find(tileID)!=dat.tileset->staircaseTiles.end()){
return dat.tileset->staircaseTiles[tileID].data["value"];
}
}
return std::string("NONE");
@ -399,6 +382,7 @@ void Crawler::UpdateEffects(float fElapsedTime){
std::erase_if(EMITTER_LIST,[](std::unique_ptr<Emitter>&e){return e->dead;});
std::erase_if(backgroundEffects,[](std::unique_ptr<Effect>&e){return e->dead;});
std::erase_if(foregroundEffects,[](std::unique_ptr<Effect>&e){return e->dead;});
std::erase_if(DAMAGENUMBER_LIST,[](std::shared_ptr<DamageNumber>&n){return n->lifeTime>1;});
for(auto it=foregroundEffectsToBeInserted.begin();it!=foregroundEffectsToBeInserted.end();++it){
foregroundEffects.push_back(std::move(*it));
@ -417,13 +401,10 @@ void Crawler::UpdateBullets(float fElapsedTime){
b->animation.UpdateState(b->internal_animState,fElapsedTime);
if(!b->deactivated){
float totalDistance=(b->vel*fElapsedTime).mag();
vf2d moveStep=b->vel*fElapsedTime;
if((b->vel*fElapsedTime).mag()>1){
moveStep=(b->vel*fElapsedTime).norm();
}
while(totalDistance>0){
totalDistance=std::max(0.f,totalDistance-1);
b->pos+=moveStep;
int iterations=std::max(1.f,(b->vel*fElapsedTime).mag());
int totalIterations=iterations;
vf2d finalBulletPos=b->pos+b->vel*fElapsedTime;
const auto CollisionCheck=[&](){
if(b->friendly){
for(Monster&m:MONSTER_LIST){
if(geom2d::overlaps(geom2d::circle(m.GetPos(),12*m.GetSizeMult()),geom2d::circle(b->pos,b->radius))){
@ -431,7 +412,7 @@ void Crawler::UpdateBullets(float fElapsedTime){
if(!b->hitsMultiple){
if(b->MonsterHit(m)){
b->dead=true;
continue;
return false;
}
}
b->hitList[&m]=true;
@ -443,13 +424,26 @@ void Crawler::UpdateBullets(float fElapsedTime){
if(player->Hurt(b->damage,b->OnUpperLevel(),0)){
if(b->PlayerHit(player.get())){
b->dead=true;
continue;
return false;
}
}
}
}
return true;
};
while(iterations>0){
iterations--;
b->pos+=(b->vel*fElapsedTime)/float(totalIterations);
if(!CollisionCheck()){
goto nextBullet;
}
}
} else {
b->pos=finalBulletPos;
if(!CollisionCheck()){
goto nextBullet;
}
}else{
b->pos+=b->vel*fElapsedTime;
}
if(b->pos.x+b->radius<view.GetWorldTL().x-WINDOW_SIZE.x||b->pos.x-b->radius>view.GetWorldBR().x+WINDOW_SIZE.x||b->pos.y+b->radius<view.GetWorldTL().y-WINDOW_SIZE.y||b->pos.y-b->radius>view.GetWorldBR().y+WINDOW_SIZE.y){
@ -461,6 +455,8 @@ void Crawler::UpdateBullets(float fElapsedTime){
b->dead=true;
continue;
}
nextBullet:
int a;
}
outsideBulletLoop:
std::erase_if(BULLET_LIST,[](std::unique_ptr<Bullet>&b){return b->dead;});
@ -473,7 +469,18 @@ void Crawler::HurtEnemies(vf2d pos,float radius,int damage,bool upperLevel,float
}
}
void Crawler::PopulateRenderLists(std::vector<Monster*>&monstersBeforeLower,std::vector<Monster*>&monstersBeforeUpper,std::vector<Monster*>&monstersAfterLower,std::vector<Monster*>&monstersAfterUpper,std::vector<Bullet*>&bulletsLower,std::vector<Bullet*>&bulletsUpper,std::vector<Effect*>&backgroundEffectsLower,std::vector<Effect*>&backgroundEffectsUpper,std::vector<Effect*>&foregroundEffectsLower,std::vector<Effect*>&foregroundEffectsUpper){
void Crawler::PopulateRenderLists(){
monstersBeforeLower.clear();
monstersAfterLower.clear();
monstersBeforeUpper.clear();
monstersAfterUpper.clear();
bulletsLower.clear();
bulletsUpper.clear();
backgroundEffectsLower.clear();
backgroundEffectsUpper.clear();
foregroundEffectsLower.clear();
foregroundEffectsUpper.clear();
Player*pl=GetPlayer();
for(auto it=MONSTER_LIST.begin();it!=MONSTER_LIST.end();++it){
Monster&m=*it;
@ -521,49 +528,157 @@ void Crawler::PopulateRenderLists(std::vector<Monster*>&monstersBeforeLower,std:
std::sort(monstersAfterLower.begin(),monstersAfterLower.end(),[](Monster*m1,Monster*m2){return m1->GetPos().y<m2->GetPos().y;});
}
void Crawler::RenderTile(vi2d pos,TilesheetData tileSheet,int tileSheetIndex,vi2d tileSheetPos){
if(tileSheet.tileset->animationData.count(tileSheetIndex)){
int animationDuration_ms=tileSheet.tileset->animationData[tileSheetIndex].size()*"animation_tile_precision"_I;
int animatedIndex=tileSheet.tileset->animationData[tileSheetIndex][int(fmod(levelTime*1000,animationDuration_ms)/"animation_tile_precision"_I)];
int tileSheetWidth=tileSheet.tileset->tileset->Sprite()->width/24;
int tileSheetX=animatedIndex%tileSheetWidth;
int tileSheetY=animatedIndex/tileSheetWidth;
view.DrawPartialDecal(pos*24,{24,24},tileSheet.tileset->tileset->Decal(),vi2d{tileSheetX,tileSheetY}*24,{24,24});
}else{
view.DrawPartialDecal(pos*24,{24,24},tileSheet.tileset->tileset->Decal(),tileSheetPos*24,{24,24});
}
}
void Crawler::RenderTile(TileRenderData&tileSheet,Pixel col){
if(tileSheet.tileSheet.tileset->animationData.count(tileSheet.tileID%1000000)){
int animationDuration_ms=tileSheet.tileSheet.tileset->animationData[tileSheet.tileID%1000000].size()*"animation_tile_precision"_I;
int animatedIndex=tileSheet.tileSheet.tileset->animationData[tileSheet.tileID%1000000][int(fmod(levelTime*1000,animationDuration_ms)/"animation_tile_precision"_I)];
int tileSheetWidth=tileSheet.tileSheet.tileset->tileset->Sprite()->width/24;
int tileSheetX=animatedIndex%tileSheetWidth;
int tileSheetY=animatedIndex/tileSheetWidth;
view.DrawPartialDecal(tileSheet.pos,{24,24},tileSheet.tileSheet.tileset->tileset->Decal(),vi2d{tileSheetX,tileSheetY},{24,24},col);
}else{
view.DrawPartialDecal(tileSheet.pos,{24,24},tileSheet.tileSheet.tileset->tileset->Decal(),tileSheet.tileSheetPos,{24,24},col);
}
}
void Crawler::RenderWorld(float fElapsedTime){
Clear({100,180,100});
Clear(BLANK);
LayerTag*bridgeLayer=nullptr;
bool bridgeLayerFade=false;
Player*pl=GetPlayer();
PopulateRenderLists();
auto RenderPlayer=[&](vf2d pos,vf2d scale){
vf2d playerScale=vf2d(player->GetSizeMult(),player->GetSizeMult());
int count=0;
for(vf2d&pos:player->ghostPositions){
view.DrawPartialRotatedDecal(pos,player->GetFrame().GetSourceImage()->Decal(),player->GetSpinAngle(),{12,12},player->GetFrame().GetSourceRect().pos,player->GetFrame().GetSourceRect().size,playerScale,{0,0,0,uint8_t(float(count)/player->RETREAT_GHOST_FRAMES*255)});
count++;
}
if(player->teleportAnimationTimer>0){
playerScale.x=120*abs(pow(player->teleportAnimationTimer-0.175,3));
pos=player->teleportStartPosition.lerp(player->teleportTarget,(0.35-player->teleportAnimationTimer)/0.35);
}
view.DrawPartialRotatedDecal(pos+vf2d{0,-player->GetZ()*(std::signbit(scale.y)?-1:1)},player->GetFrame().GetSourceImage()->Decal(),player->GetSpinAngle(),{12,12},player->GetFrame().GetSourceRect().pos,player->GetFrame().GetSourceRect().size,playerScale*scale,player->GetBuffs(BuffType::ATTACK_UP).size()>0?Pixel{255,uint8_t(255*abs(sin(1.4*player->GetBuffs(BuffType::ATTACK_UP)[0].duration))),uint8_t(255*abs(sin(1.4*player->GetBuffs(BuffType::ATTACK_UP)[0].duration)))}:WHITE);
};
enum class RenderMode{
REFLECTIVE_TILES,
NORMAL_TILES,
EMPTY_TILES,
};
reflectionUpdateTimer-=fElapsedTime;
if(reflectionUpdateTimer<=0){
reflectionStepTime+="water_reflection_time_step"_F;
reflectionUpdateTimer="water_reflection_update_time"_F;
}
#pragma region Basic Tile Layer Rendering
for(RenderMode mode=RenderMode::REFLECTIVE_TILES;mode<=RenderMode::EMPTY_TILES;mode=RenderMode(int(mode)+1)){
if(mode==RenderMode::NORMAL_TILES){
SetDecalMode(DecalMode::ADDITIVE);
float reflectionHeight=(float(player->GetFrame().GetSourceRect().size.y)-8)*player->GetSizeMult();
float reflectionBottom=player->GetPos().y+reflectionHeight;
float cutOff=reflectionBottom-WORLD_SIZE.y*24;
float multiplierX=0.9;
multiplierX*=(1-abs(sin(reflectionStepTime))*"water_reflection_scale_factor"_F);
multiplierX*=(1-abs(cos(1.5*reflectionStepTime))*"water_reflection_scale_factor"_F);
float reflectionRatioX=abs(sin(reflectionStepTime))*"water_reflection_scale_factor"_F;
RenderPlayer(player->GetPos()+vf2d{reflectionRatioX*player->GetFrame().GetSourceRect().size.x,float(player->GetFrame().GetSourceRect().size.y)-8}*player->GetSizeMult(),{multiplierX,-1});
for(Monster&m:MONSTER_LIST){
m.DrawReflection(reflectionRatioX,multiplierX);
}
SetDecalMode(DecalMode::NORMAL);
}
for (int x = view.GetTopLeftTile().x/24-1; x <= view.GetBottomRightTile().x/24; x++){
for (int y = view.GetTopLeftTile().y/24-1; y <= view.GetBottomRightTile().y/24; y++){
if(x>=0&&x<WORLD_SIZE.x&&y>=0&&y<WORLD_SIZE.y){
for(LayerTag&layer:MAP_DATA[currentLevel].LayerData){
if(IsBridgeLayer(layer)){
bridgeLayer=&layer;
if(!bridgeLayerFade&&!player->upperLevel){
switch(mode){
case RenderMode::NORMAL_TILES:{
for(LayerTag&layer:MAP_DATA[currentLevel].LayerData){
if(IsBridgeLayer(layer)){
bridgeLayer=&layer;
if(!bridgeLayerFade&&!player->upperLevel){
int tileID=layer.tiles[y][x]-1;
if(tileID!=-1){
int playerXTruncated=int(player->GetPos().x)/24;
int playerYTruncated=int(player->GetPos().y)/24;
if(playerXTruncated==x&&playerYTruncated==y){
bridgeLayerFade=true;
}
}
}
continue;
}
int tileID=layer.tiles[y][x]-1;
if(tileID!=-1){
int playerXTruncated=int(player->GetPos().x)/24;
int playerYTruncated=int(player->GetPos().y)/24;
if(playerXTruncated==x&&playerYTruncated==y){
bridgeLayerFade=true;
TilesheetData tileSheet=GetTileSheet(currentLevel,tileID);
int tileSheetWidth=tileSheet.tileset->tileset->Sprite()->width/24;
int tileSheetHeight=tileSheet.tileset->tileset->Sprite()->height/24;
int tileSheetIndex=tileID-(tileSheet.firstgid-1);
int tileSheetX=tileSheetIndex%tileSheetWidth;
int tileSheetY=tileSheetIndex/tileSheetWidth;
if(!IsForegroundTile(tileSheet,tileSheetIndex)&&!IsUpperForegroundTile(tileSheetIndex)&&!IsReflectiveTile(tileSheet,tileSheetIndex)){
if(layer.tag.data["class"]!="CollisionOnly"){visibleTiles.erase({x,y});}
RenderTile({x,y},tileSheet,tileSheetIndex,{tileSheetX,tileSheetY});
}
if("debug_collision_boxes"_I){
if(tileSheet.tileset->collision.find(tileSheetIndex)!=tileSheet.tileset->collision.end()){
geom2d::rect<int>collision=tileSheet.tileset->collision[tileSheetIndex].collision;
view.FillRectDecal(vi2d{x,y}*24+collision.pos,collision.size,{0,0,0,128});
view.DrawRectDecal(vi2d{x,y}*24+collision.pos,collision.size,GREY);
}
}
}
}
continue;
}
int tileID=layer.tiles[y][x]-1;
if(tileID!=-1){
TilesheetData tileSheet=GetTileSheet(currentLevel,tileID);
int tileSheetWidth=tileSheet.tileset.tileset->Sprite()->width/24;
int tileSheetHeight=tileSheet.tileset.tileset->Sprite()->height/24;
int tileSheetIndex=tileID-(tileSheet.firstgid-1);
int tileSheetX=tileSheetIndex%tileSheetWidth;
int tileSheetY=tileSheetIndex/tileSheetWidth;
if(!IsForegroundTile(tileSheet,tileSheetIndex)&&!IsUpperForegroundTile(tileSheet,tileSheetIndex)){
view.DrawPartialDecal(vi2d{x,y}*24,{24,24},tileSheet.tileset.tileset->Decal(),vi2d{tileSheetX,tileSheetY}*24,{24,24});
}
if("debug_collision_boxes"_I){
if(tileSheet.tileset.collision.find(tileSheetIndex)!=tileSheet.tileset.collision.end()){
geom2d::rect<int>collision=tileSheet.tileset.collision[tileSheetIndex].collision;
view.FillRectDecal(vi2d{x,y}*24+collision.pos,collision.size,{0,0,0,128});
view.DrawRectDecal(vi2d{x,y}*24+collision.pos,collision.size,GREY);
}break;
case RenderMode::REFLECTIVE_TILES:{
visibleTiles.insert({x,y});
for(LayerTag&layer:MAP_DATA[currentLevel].LayerData){
int tileID=layer.tiles[y][x]-1;
if(tileID!=-1){
TilesheetData tileSheet=GetTileSheet(currentLevel,tileID);
int tileSheetWidth=tileSheet.tileset->tileset->Sprite()->width/24;
int tileSheetHeight=tileSheet.tileset->tileset->Sprite()->height/24;
int tileSheetIndex=tileID-(tileSheet.firstgid-1);
int tileSheetX=tileSheetIndex%tileSheetWidth;
int tileSheetY=tileSheetIndex/tileSheetWidth;
if(IsReflectiveTile(tileSheet,tileSheetIndex)){
if(layer.tag.data["class"]!="CollisionOnly"){visibleTiles.erase({x,y});}
RenderTile({x,y},tileSheet,tileSheetIndex,{tileSheetX,tileSheetY});
}
if("debug_collision_boxes"_I){
if(tileSheet.tileset->collision.find(tileSheetIndex)!=tileSheet.tileset->collision.end()){
geom2d::rect<int>collision=tileSheet.tileset->collision[tileSheetIndex].collision;
view.FillRectDecal(vi2d{x,y}*24+collision.pos,collision.size,{0,0,0,128});
view.DrawRectDecal(vi2d{x,y}*24+collision.pos,collision.size,GREY);
}
}
}
}
}
}break;
case RenderMode::EMPTY_TILES:{
if(visibleTiles.count({x,y})){
view.FillRectDecal(vi2d{x,y}*24,{24,24},{100,180,100});
}
}break;
}
}
}
}
@ -572,18 +687,17 @@ void Crawler::RenderWorld(float fElapsedTime){
}else{
bridgeFadeFactor=std::max(bridgeFadeFactor-fElapsedTime,0.f);
}
}
#pragma endregion
//DrawDecal({0,0},MAP_TILESETS["assets/maps/"+MAP_DATA[LEVEL1].TilesetData[1].data["source"]]->Decal());
std::vector<Monster*>monstersBeforeLower,monstersAfterLower,monstersBeforeUpper,monstersAfterUpper;
std::vector<Bullet*>bulletsLower,bulletsUpper;
std::vector<Effect*>backgroundEffectsLower,backgroundEffectsUpper,foregroundEffectsLower,foregroundEffectsUpper;
Player*pl=GetPlayer();
PopulateRenderLists(monstersBeforeLower,monstersBeforeUpper,monstersAfterLower,monstersAfterUpper,bulletsLower,bulletsUpper,backgroundEffectsLower,backgroundEffectsUpper,foregroundEffectsLower,foregroundEffectsUpper);
for(Monster&m:MONSTER_LIST){
m.strategyDraw(this);
}
if(player->GetZ()>0){
vf2d shadowScale=vf2d{8*player->GetSizeMult()/3.f,1}/std::max(1.f,player->GetZ()/24);
view.DrawDecal(player->GetPos()-vf2d{3,3}*shadowScale/2+vf2d{0,6*player->GetSizeMult()},GFX_Circle.Decal(),shadowScale,BLACK);
view.DrawDecal(player->GetPos()-vf2d{3,3}*shadowScale/2+vf2d{0,6*player->GetSizeMult()},GFX["circle.png"].Decal(),shadowScale,BLACK);
}
for(Effect*e:backgroundEffectsLower){
e->Draw();
@ -591,28 +705,11 @@ void Crawler::RenderWorld(float fElapsedTime){
for(Monster*m:monstersBeforeLower){
m->Draw();
}
vf2d playerScale=vf2d(player->GetSizeMult(),player->GetSizeMult());
vf2d playerPosition=player->GetPos();
auto RenderPlayer=[&](){
int count=0;
for(vf2d&pos:player->ghostPositions){
view.DrawPartialRotatedDecal(pos,player->GetFrame().GetSourceImage()->Decal(),player->GetSpinAngle(),{12,12},player->GetFrame().GetSourceRect().pos,player->GetFrame().GetSourceRect().size,playerScale,{0,0,0,uint8_t(float(count)/player->RETREAT_GHOST_FRAMES*255)});
count++;
}
if(player->teleportAnimationTimer>0){
playerScale.x=120*abs(pow(player->teleportAnimationTimer-0.175,3));
playerPosition=player->teleportStartPosition.lerp(player->teleportTarget,(0.35-player->teleportAnimationTimer)/0.35);
view.DrawPartialRotatedDecal(playerPosition+vf2d{0,-player->GetZ()},player->GetFrame().GetSourceImage()->Decal(),player->GetSpinAngle(),{12,12},player->GetFrame().GetSourceRect().pos,player->GetFrame().GetSourceRect().size,playerScale,player->GetBuffs(BuffType::ATTACK_UP).size()>0?Pixel{255,uint8_t(255*abs(sin(1.4*player->GetBuffs(BuffType::ATTACK_UP)[0].duration))),uint8_t(255*abs(sin(1.4*player->GetBuffs(BuffType::ATTACK_UP)[0].duration)))}:WHITE);
} else {
view.DrawPartialRotatedDecal(playerPosition+vf2d{0,-player->GetZ()},player->GetFrame().GetSourceImage()->Decal(),player->GetSpinAngle(),{12,12},player->GetFrame().GetSourceRect().pos,player->GetFrame().GetSourceRect().size,playerScale,player->GetBuffs(BuffType::ATTACK_UP).size()>0?Pixel{255,uint8_t(255*abs(sin(1.4*player->GetBuffs(BuffType::ATTACK_UP)[0].duration))),uint8_t(255*abs(sin(1.4*player->GetBuffs(BuffType::ATTACK_UP)[0].duration)))}:WHITE);
}
};
//define end
if(!player->upperLevel){
RenderPlayer();
RenderPlayer(player->GetPos(),{1,1});
}
if(player->GetState()==State::BLOCK){
view.DrawDecal(player->GetPos()-vf2d{12,12},GFX_BLOCK_BUBBLE.Decal());
view.DrawDecal(player->GetPos()-vf2d{12,12},GFX["block.png"].Decal());
}
for(Monster*m:monstersAfterLower){
m->Draw();
@ -628,15 +725,15 @@ void Crawler::RenderWorld(float fElapsedTime){
float precastSize=GetPlayer()->castPrepAbility->precastInfo.size;
float precastRange=GetPlayer()->castPrepAbility->precastInfo.range;
vf2d scale=vf2d{precastSize,precastSize}*2/3.f;
vf2d centerPoint=GetWorldMousePos()-vf2d{game->GFX_Circle.Sprite()->width*scale.x/2,game->GFX_Circle.Sprite()->height*scale.y/2};
vf2d centerPoint=GetWorldMousePos()-vf2d{GFX["circle.png"].Sprite()->width*scale.x/2,GFX["circle.png"].Sprite()->height*scale.y/2};
float distance=sqrt(pow(player->GetX()-GetWorldMousePos().x,2)+pow(player->GetY()-GetWorldMousePos().y,2));
if(distance>precastRange){//Clamp the distance.
vf2d pointToCursor = {GetWorldMousePos().x-player->GetX(),GetWorldMousePos().y-player->GetY()};
pointToCursor=pointToCursor.norm()*precastRange;
vf2d centerPoint=player->GetPos()+pointToCursor-vf2d{game->GFX_Circle.Sprite()->width*scale.x/2,game->GFX_Circle.Sprite()->height*scale.y/2};
view.DrawDecal(centerPoint,GFX_Circle.Decal(),scale,{255,0,0,96});
vf2d centerPoint=player->GetPos()+pointToCursor-vf2d{GFX["circle.png"].Sprite()->width*scale.x/2,GFX["circle.png"].Sprite()->height*scale.y/2};
view.DrawDecal(centerPoint,GFX["circle.png"].Decal(),scale,{255,0,0,96});
} else {
view.DrawDecal(centerPoint,GFX_Circle.Decal(),scale,{255,0,0,96});
view.DrawDecal(centerPoint,GFX["circle.png"].Decal(),scale,{255,0,0,96});
}
}
};
@ -654,7 +751,7 @@ void Crawler::RenderWorld(float fElapsedTime){
group.fadeFactor=std::max(group.fadeFactor-fElapsedTime,0.f);
}
for(TileRenderData&tile:group.GetTiles()){
view.DrawPartialDecal(tile.pos,{24,24},tile.tileset,tile.tileSheetPos,{24,24},{255,255,255,uint8_t(255-group.fadeFactor/TileGroup::FADE_TIME*TileGroup::FADE_AMT)});
RenderTile(tile,{255,255,255,uint8_t(255-group.fadeFactor/TileGroup::FADE_TIME*TileGroup::FADE_AMT)});
}
}
}
@ -667,12 +764,12 @@ void Crawler::RenderWorld(float fElapsedTime){
int tileID=bridgeLayer->tiles[y][x]-1;
if(tileID!=-1){
TilesheetData tileSheet=GetTileSheet(currentLevel,tileID);
int tileSheetWidth=tileSheet.tileset.tileset->Sprite()->width/24;
int tileSheetHeight=tileSheet.tileset.tileset->Sprite()->height/24;
int tileSheetWidth=tileSheet.tileset->tileset->Sprite()->width/24;
int tileSheetHeight=tileSheet.tileset->tileset->Sprite()->height/24;
int tileSheetIndex=tileID-(tileSheet.firstgid-1);
int tileSheetX=tileSheetIndex%tileSheetWidth;
int tileSheetY=tileSheetIndex/tileSheetWidth;
view.DrawPartialDecal(vi2d{x,y}*24,{24,24},tileSheet.tileset.tileset->Decal(),vi2d{tileSheetX,tileSheetY}*24,{24,24},{255,255,255,uint8_t(255-bridgeFadeFactor/TileGroup::FADE_TIME*TileGroup::FADE_AMT)});
view.DrawPartialDecal(vi2d{x,y}*24,{24,24},tileSheet.tileset->tileset->Decal(),vi2d{tileSheetX,tileSheetY}*24,{24,24},{255,255,255,uint8_t(255-bridgeFadeFactor/TileGroup::FADE_TIME*TileGroup::FADE_AMT)});
#ifdef DEBUG_COLLISIONS
if(tileSheet.tileset.collision.find(tileSheetIndex)!=tileSheet.tileset.collision.end()){
geom2d::rect<int>collision=tileSheet.tileset.collision[tileSheetIndex].collision;
@ -693,7 +790,7 @@ void Crawler::RenderWorld(float fElapsedTime){
m->Draw();
}
if(player->upperLevel){
RenderPlayer();
RenderPlayer(player->GetPos(),{1,1});
}
for(Monster*m:monstersAfterUpper){
m->Draw();
@ -717,7 +814,7 @@ void Crawler::RenderWorld(float fElapsedTime){
group.fadeFactor=std::max(group.fadeFactor-fElapsedTime,0.f);
}
for(TileRenderData&tile:group.GetTiles()){
view.DrawPartialDecal(tile.pos,{24,24},tile.tileset,tile.tileSheetPos,{24,24},{255,255,255,uint8_t(255-group.fadeFactor/TileGroup::FADE_TIME*TileGroup::FADE_AMT)});
RenderTile(tile,{255,255,255,uint8_t(255-group.fadeFactor/TileGroup::FADE_TIME*TileGroup::FADE_AMT)});
}
}
#pragma endregion
@ -727,21 +824,22 @@ void Crawler::RenderWorld(float fElapsedTime){
dn->pauseTime-=fElapsedTime;
} else{
dn->lifeTime+=fElapsedTime;
if(dn->lifeTime>1){
it=DAMAGENUMBER_LIST.erase(it);
if(it==DAMAGENUMBER_LIST.end()){
break;
}
} else {
if(dn->lifeTime<=1){
if(dn->lifeTime<DamageNumber::MOVE_UP_TIME){
dn->pos.y-=20*fElapsedTime;
}
}
}
std::string text=std::to_string(dn->damage);
view.DrawStringPropDecal(dn->pos-GetTextSizeProp(text)/2,text,DARK_RED);
}
if(DEBUG_PATHFINDING){
std::vector<vf2d>pathing=game->pathfinder.Solve_AStar(player.get()->GetPos(),GetWorldMousePos(),8,player.get()->OnUpperLevel());
for(vf2d&square:pathing){
view.FillRectDecal(square*24,{24,24},DARK_GREEN);
}
}
}
Player*Crawler::GetPlayer(){
@ -798,8 +896,8 @@ void Crawler::RenderHud(){
DrawShadowStringPropDecal(vf2d{ScreenWidth()/2.f-GetTextSizeProp(castText).x*2/2,ScreenHeight()-64.f},castText,WHITE,BLACK,{2,3},2.f);
}
DrawDecal({2,2},GFX_Heart.Decal());
DrawDecal({2,20},GFX_Mana.Decal());
DrawDecal({2,2},GFX["heart.png"].Decal());
DrawDecal({2,20},GFX["mana.png"].Decal());
std::string text=player->GetHealth()>0?std::to_string(player->GetHealth()):"X";
std::string text_mana=std::to_string(player->GetMana());
DrawShadowStringPropDecal({20,3},text,WHITE,BLACK,{2,2});
@ -862,6 +960,9 @@ void Crawler::InitializeLevel(std::string mapFile,MapName map){
MAP_TILESETS["assets/maps/"+baseSourceDir].upperForegroundTiles=tileset.GetData().UpperForegroundTileData;
MAP_TILESETS["assets/maps/"+baseSourceDir].collision=tileset.GetData().CollisionData;
MAP_TILESETS["assets/maps/"+baseSourceDir].staircaseTiles=tileset.GetData().StaircaseData;
MAP_TILESETS["assets/maps/"+baseSourceDir].animationData=tileset.GetData().AnimationData;
MAP_TILESETS["assets/maps/"+baseSourceDir].reflectiveData=tileset.GetData().ReflectiveData;
std::cout<<"assets/maps/"+baseSourceDir<<" Animation Data Size: "<<MAP_TILESETS["assets/maps/"+baseSourceDir].animationData.size()<<std::endl;
r->Load("assets/maps/"+tileset.GetData().ImageData.data["source"]);
}
}
@ -872,103 +973,148 @@ void Crawler::LoadLevel(MapName map){
foregroundTileGroups.clear();
currentLevel=map;
WORLD_SIZE={MAP_DATA[map].MapData.width,MAP_DATA[map].MapData.height};
levelTime=0;
for(auto key:MAP_DATA[map].SpawnerData){
SpawnerTag&spawnData=MAP_DATA[map].SpawnerData[key.first];
std::vector<std::pair<int,vf2d>>monster_list;
#pragma region Monster Spawn Data Setup
for(auto key:MAP_DATA[map].SpawnerData){
SpawnerTag&spawnData=MAP_DATA[map].SpawnerData[key.first];
std::vector<std::pair<int,vf2d>>monster_list;
vf2d spawnerRadius=vf2d{spawnData.ObjectData.GetFloat("width"),spawnData.ObjectData.GetFloat("height")}/2;
for(XMLTag&monster:spawnData.monsters){
int monsterTypeID=monster.GetInteger("value")-1;
monster_list.push_back({monsterTypeID,{monster.GetInteger("x")-spawnData.ObjectData.GetFloat("x"),monster.GetInteger("y")-spawnData.ObjectData.GetFloat("y")}});
vf2d spawnerRadius=vf2d{spawnData.ObjectData.GetFloat("width"),spawnData.ObjectData.GetFloat("height")}/2;
for(XMLTag&monster:spawnData.monsters){
int monsterTypeID=monster.GetInteger("value")-1;
monster_list.push_back({monsterTypeID,{monster.GetInteger("x")-spawnData.ObjectData.GetFloat("x"),monster.GetInteger("y")-spawnData.ObjectData.GetFloat("y")}});
}
SPAWNER_LIST.push_back(MonsterSpawner{{spawnData.ObjectData.GetFloat("x"),spawnData.ObjectData.GetFloat("y")},spawnerRadius*2,monster_list,spawnData.upperLevel});
}
SPAWNER_LIST.push_back(MonsterSpawner{{spawnData.ObjectData.GetFloat("x"),spawnData.ObjectData.GetFloat("y")},spawnerRadius*2,monster_list,spawnData.upperLevel});
}
#pragma endregion
#pragma region Identify Upper Foreground Tiles
auto GetUpperZones=[&](){
for(auto&zoneSet:MAP_DATA[map].ZoneData){
if(zoneSet.first=="UpperZone"){ //We are interested in all upper zones.
return zoneSet.second;
}
}
return std::vector<geom2d::rect<int>>{};
};
for(geom2d::rect<int>&zone:GetUpperZones()){
int zoneX=zone.pos.x/24; //snap to grid
int zoneY=zone.pos.y/24;
int zoneW=zone.right().start.x/24-zoneX;
int zoneH=zone.bottom().start.y/24-zoneY;
for(int x=zoneX;x<zoneX+zoneW;x++){
for(int y=zoneY;y<zoneY+zoneH;y++){
for(LayerTag&layer:MAP_DATA[map].LayerData){
int tile=layer.tiles[y][x]-1;
TilesheetData tileSheet=GetTileSheet(currentLevel,tile);
int tileSheetIndex=tile-(tileSheet.firstgid-1);
if(IsForegroundTile(tileSheet,tileSheetIndex)){
layer.tiles[y][x]+=1000000;
}
}
}
}
}
#pragma endregion
std::set<vi2d>foregroundTilesAdded,upperForegroundTilesAdded;
for(int x=0;x<WORLD_SIZE.x;x++){
for(int y=0;y<WORLD_SIZE.y;y++){
for(LayerTag&layer:MAP_DATA[currentLevel].LayerData){
int tileID=layer.tiles[y][x]-1;
if(tileID!=-1){
TilesheetData tileSheet=GetTileSheet(currentLevel,tileID);
int tileSheetWidth=tileSheet.tileset.tileset->Sprite()->width/24;
int tileSheetHeight=tileSheet.tileset.tileset->Sprite()->height/24;
int tileSheetIndex=tileID-(tileSheet.firstgid-1);
int tileSheetX=tileSheetIndex%tileSheetWidth;
int tileSheetY=tileSheetIndex/tileSheetWidth;
#pragma region TileGroupShenanigans
auto SetupTileGroups=[&](std::function<bool(TilesheetData,int)>IsForeground,TileRenderData tile,std::set<vi2d>&foregroundTilesIncluded,std::vector<TileGroup>&groups){
int layerID=layer.tag.GetInteger("id");
if(IsForeground(tileSheet,tileSheetIndex)&&foregroundTilesIncluded.find({x,y})==foregroundTilesIncluded.end()){
std::queue<vi2d>tileGroupChecks;
TileGroup group;
foregroundTilesIncluded.insert({x,y});
group.originatingLayer=layerID;
group.InsertTile(tile);
if(x>0)tileGroupChecks.push({x-1,y});
if(x<WORLD_SIZE.x-1)tileGroupChecks.push({x+1,y});
if(y>0)tileGroupChecks.push({x,y-1});
if(y<WORLD_SIZE.y-1)tileGroupChecks.push({x,y+1});
auto IterateThroughOtherLayers=[&](vi2d pos){
for(LayerTag&layer2:MAP_DATA[currentLevel].LayerData){
if(&layer==&layer2)continue;
int tileID=layer2.tiles[pos.y][pos.x]-1;
TilesheetData tileSheet=GetTileSheet(currentLevel,tileID);
int tileSheetWidth=tileSheet.tileset.tileset->Sprite()->width/24;
int tileSheetHeight=tileSheet.tileset.tileset->Sprite()->height/24;
int tileSheetIndex=tileID-(tileSheet.firstgid-1);
int tileSheetX=tileSheetIndex%tileSheetWidth;
int tileSheetY=tileSheetIndex/tileSheetWidth;
TileRenderData tile={tileSheet.tileset.tileset->Decal(),vi2d{pos.x,pos.y}*24,vi2d{tileSheetX,tileSheetY}*24};
if(IsForeground(tileSheet,tileSheetIndex)){
foregroundTilesIncluded.insert({pos.x,pos.y});
group.InsertTile(tile);
#pragma region Foreground and Upper Foreground Tile Fade Group Setup
std::set<vi2d>foregroundTilesAdded,upperForegroundTilesAdded;
for(int x=0;x<WORLD_SIZE.x;x++){
for(int y=0;y<WORLD_SIZE.y;y++){
int layerID=0;
for(LayerTag&layer:MAP_DATA[currentLevel].LayerData){
int tileID=layer.tiles[y][x]-1;
if(tileID!=-1){
TilesheetData tileSheet=GetTileSheet(currentLevel,tileID);
int tileSheetWidth=tileSheet.tileset->tileset->Sprite()->width/24;
int tileSheetHeight=tileSheet.tileset->tileset->Sprite()->height/24;
int tileSheetIndex=tileID-(tileSheet.firstgid-1);
int realTileSheetIndex=(tileID%1000000)-(tileSheet.firstgid-1);
int tileSheetX=realTileSheetIndex%tileSheetWidth;
int tileSheetY=realTileSheetIndex/tileSheetWidth;
#pragma region TileGroupShenanigans
auto SetupTileGroups=[&](std::function<bool(TilesheetData,int)>IsForeground,TileRenderData tile,std::set<vi2d>&foregroundTilesIncluded,std::vector<TileGroup>&groups){
if(foregroundTilesIncluded.find({x,y})==foregroundTilesIncluded.end()&&IsForeground(tileSheet,tileSheetIndex)){
std::queue<vi2d>tileGroupChecks;
TileGroup group;
foregroundTilesIncluded.insert({x,y});
group.InsertTile(tile);
if(x>0&&foregroundTilesIncluded.find(vi2d{x,y}+vi2d{-1,0})==foregroundTilesIncluded.end())tileGroupChecks.push({x-1,y});
if(x<WORLD_SIZE.x-1&&foregroundTilesIncluded.find(vi2d{x,y}+vi2d{1,0})==foregroundTilesIncluded.end())tileGroupChecks.push({x+1,y});
if(y>0&&foregroundTilesIncluded.find(vi2d{x,y}+vi2d{0,-1})==foregroundTilesIncluded.end())tileGroupChecks.push({x,y-1});
if(y<WORLD_SIZE.y-1&&foregroundTilesIncluded.find(vi2d{x,y}+vi2d{0,1})==foregroundTilesIncluded.end())tileGroupChecks.push({x,y+1});
auto IterateThroughOtherLayers=[&](vi2d pos,bool loopAll=false){
int layer2ID=0;
bool hadForeground=false;
for(LayerTag&layer2:MAP_DATA[currentLevel].LayerData){
if(!loopAll&&&layer==&layer2){layer2ID++;continue;};
int tileID=layer2.tiles[pos.y][pos.x]-1;
TilesheetData tileSheet=GetTileSheet(currentLevel,tileID%1000000);
int tileSheetWidth=tileSheet.tileset->tileset->Sprite()->width/24;
int tileSheetHeight=tileSheet.tileset->tileset->Sprite()->height/24;
int tileSheetIndex=tileID-(tileSheet.firstgid-1);
int realTileSheetIndex=(tileID%1000000)-(tileSheet.firstgid-1);
int tileSheetX=realTileSheetIndex%tileSheetWidth;
int tileSheetY=realTileSheetIndex/tileSheetWidth;
TileRenderData tile={tileSheet,vi2d{pos.x,pos.y}*24,vi2d{tileSheetX,tileSheetY}*24,realTileSheetIndex,layer2ID};
if(IsForeground(tileSheet,tileSheetIndex)){
foregroundTilesIncluded.insert({pos.x,pos.y});
group.InsertTile(tile);
hadForeground=true;
}
layer2ID++;
}
return hadForeground;
};
IterateThroughOtherLayers({x,y});
while(!tileGroupChecks.empty()){
vi2d&pos=tileGroupChecks.front();
if(IterateThroughOtherLayers(pos,true)){
foregroundTilesIncluded.insert({pos.x,pos.y}); //Regardless of if we found a foreground tile or not, we need to add this to not get stuck in an infinite loop.
vi2d targetPos=pos+vi2d{-1,0};
if(pos.x>0&&foregroundTilesIncluded.find(targetPos)==foregroundTilesIncluded.end()){tileGroupChecks.push(targetPos);foregroundTilesIncluded.insert(targetPos);}
targetPos=pos+vi2d{1,0};
if(pos.x<WORLD_SIZE.x-1&&foregroundTilesIncluded.find(targetPos)==foregroundTilesIncluded.end()){tileGroupChecks.push(targetPos);foregroundTilesIncluded.insert(targetPos);}
targetPos=pos+vi2d{0,-1};
if(pos.y>0&&foregroundTilesIncluded.find(targetPos)==foregroundTilesIncluded.end()){tileGroupChecks.push(targetPos);foregroundTilesIncluded.insert(targetPos);}
targetPos=pos+vi2d{0,1};
if(pos.y<WORLD_SIZE.y-1&&foregroundTilesIncluded.find(targetPos)==foregroundTilesIncluded.end()){tileGroupChecks.push(targetPos);foregroundTilesIncluded.insert(targetPos);}
}
tileGroupChecks.pop();
}
};
IterateThroughOtherLayers({x,y});
while(!tileGroupChecks.empty()){
vi2d&pos=tileGroupChecks.front();
tileGroupChecks.pop();
int tileID=layer.tiles[pos.y][pos.x]-1;
TilesheetData tileSheet=GetTileSheet(currentLevel,tileID);
int tileSheetWidth=tileSheet.tileset.tileset->Sprite()->width/24;
int tileSheetHeight=tileSheet.tileset.tileset->Sprite()->height/24;
int tileSheetIndex=tileID-(tileSheet.firstgid-1);
int tileSheetX=tileSheetIndex%tileSheetWidth;
int tileSheetY=tileSheetIndex/tileSheetWidth;
TileRenderData tile={tileSheet.tileset.tileset->Decal(),pos*24,vi2d{tileSheetX,tileSheetY}*24};
if(IsForeground(tileSheet,tileSheetIndex)&&foregroundTilesIncluded.find(pos)==foregroundTilesIncluded.end()){
foregroundTilesIncluded.insert(pos);
group.InsertTile(tile);
if(pos.x>0)tileGroupChecks.push(pos+vi2d{-1,0});
if(pos.x<WORLD_SIZE.x-1)tileGroupChecks.push(pos+vi2d{1,0});
if(pos.y>0)tileGroupChecks.push(pos+vi2d{0,-1});
if(pos.y<WORLD_SIZE.y-1)tileGroupChecks.push(pos+vi2d{0,1});
IterateThroughOtherLayers(pos);
}
groups.push_back(group);
}
groups.push_back(group);
}
};
TileRenderData tile={tileSheet.tileset.tileset->Decal(),vi2d{x,y}*24,vi2d{tileSheetX,tileSheetY}*24};
SetupTileGroups([&](TilesheetData sheet,int tileID){return IsForegroundTile(sheet,tileID);},tile,foregroundTilesAdded,foregroundTileGroups);
SetupTileGroups([&](TilesheetData sheet,int tileID){return IsUpperForegroundTile(sheet,tileID);},tile,upperForegroundTilesAdded,upperForegroundTileGroups);
#pragma endregion
};
TileRenderData tile={tileSheet,vi2d{x,y}*24,vi2d{tileSheetX,tileSheetY}*24,tileID,layerID};
SetupTileGroups([&](TilesheetData sheet,int tileID){return IsForegroundTile(sheet,tileID);},tile,foregroundTilesAdded,foregroundTileGroups);
SetupTileGroups([&](TilesheetData sheet,int tileID){return IsUpperForegroundTile(tileID);},tile,upperForegroundTilesAdded,upperForegroundTileGroups);
#pragma endregion
}
layerID++;
}
}
}
}
for(TileGroup&group:foregroundTileGroups){
std::sort(group.GetTiles().begin(),group.GetTiles().end(),[](TileRenderData&t1,TileRenderData&t2){return t1.layerID<t2.layerID;});
}
for(TileGroup&group:upperForegroundTileGroups){
std::sort(group.GetTiles().begin(),group.GetTiles().end(),[](TileRenderData&t1,TileRenderData&t2){return t1.layerID<t2.layerID;});
}
#pragma endregion
int counter=0;
bridgeLayerIndex=-1;
for(LayerTag&layer:MAP_DATA[map].LayerData){
if(IsBridgeLayer(layer)){
bridgeLayerIndex=counter;
#pragma region Bridge Layer Setup
int counter=0;
bridgeLayerIndex=-1;
for(LayerTag&layer:MAP_DATA[map].LayerData){
if(IsBridgeLayer(layer)){
bridgeLayerIndex=counter;
}
counter++;
}
counter++;
}
#pragma endregion
player->upperLevel=false; //Assume player starts on lower level.
player->SetPos(MAP_DATA[map].MapData.playerSpawnLocation);
@ -987,12 +1133,12 @@ vi2d Crawler::GetWorldSize(){
return WORLD_SIZE;
}
bool Crawler::IsUpperForegroundTile(TilesheetData sheet,int tileID){
return sheet.tileset.upperForegroundTiles.find(tileID)!=sheet.tileset.upperForegroundTiles.end();
bool Crawler::IsUpperForegroundTile(int tileID){
return tileID>=1000000;
}
bool Crawler::IsForegroundTile(TilesheetData sheet,int tileID){
return sheet.tileset.foregroundTiles.find(tileID)!=sheet.tileset.foregroundTiles.end();
return sheet.tileset->foregroundTiles.find(tileID)!=sheet.tileset->foregroundTiles.end();
}
TilesheetData Crawler::GetTileSheet(MapName map,int tileID){
@ -1000,18 +1146,18 @@ TilesheetData Crawler::GetTileSheet(MapName map,int tileID){
if(tileData.size()==1){
size_t slashMarkerSourceDir = tileData[0].data["source"].find_last_of('/');
std::string baseSourceDir=tileData[0].data["source"].substr(slashMarkerSourceDir+1);
return {MAP_TILESETS["assets/maps/"+baseSourceDir],1};
return {&MAP_TILESETS["assets/maps/"+baseSourceDir],1};
} else {
for (int i=1;i<tileData.size();i++){
if(tileID<stoi(tileData[i].data["firstgid"])){
if(tileID%1000000<stoi(tileData[i].data["firstgid"])-1){
size_t slashMarkerSourceDir = tileData[i-1].data["source"].find_last_of('/');
std::string baseSourceDir=tileData[i-1].data["source"].substr(slashMarkerSourceDir+1);
return {MAP_TILESETS["assets/maps/"+baseSourceDir],stoi(tileData[i-1].data["firstgid"])};
return {&MAP_TILESETS["assets/maps/"+baseSourceDir],stoi(tileData[i-1].data["firstgid"])};
}
}
size_t slashMarkerSourceDir = tileData[tileData.size()-1].data["source"].find_last_of('/');
std::string baseSourceDir=tileData[tileData.size()-1].data["source"].substr(slashMarkerSourceDir+1);
return {MAP_TILESETS["assets/maps/"+baseSourceDir],stoi(tileData[tileData.size()-1].data["firstgid"])};
return {&MAP_TILESETS["assets/maps/"+baseSourceDir],stoi(tileData[tileData.size()-1].data["firstgid"])};
}
}
@ -1032,7 +1178,7 @@ geom2d::rect<int>Crawler::GetTileCollision(MapName map,vf2d pos,bool upperLevel)
if(!upperLevel){ //We are looking for lower bridge collisions.
for(geom2d::rect<int>&zone:MAP_DATA[map].ZoneData["LowerBridgeCollision"]){
if(geom2d::contains(zone,pos)){
return {{0,0},{32,32}};
return {{0,0},{24,24}};
}
}
}
@ -1041,24 +1187,34 @@ geom2d::rect<int>Crawler::GetTileCollision(MapName map,vf2d pos,bool upperLevel)
if(upperLevel&&bridgeLayerIndex!=-1){
int tileID=MAP_DATA[map].LayerData[bridgeLayerIndex].tiles[int(pos.y)/24][int(pos.x)/24]-1;
if(tileID!=-1){
if (GetTileSheet(map,tileID).tileset.collision.find(tileID-GetTileSheet(map,tileID).firstgid+1)!=GetTileSheet(map,tileID).tileset.collision.end()){
return GetTileSheet(map,tileID).tileset.collision[tileID-GetTileSheet(map,tileID).firstgid+1].collision;
if (GetTileSheet(map,tileID%1000000).tileset->collision.find(tileID%1000000-GetTileSheet(map,tileID%1000000).firstgid+1)!=GetTileSheet(map,tileID%1000000).tileset->collision.end()){
return GetTileSheet(map,tileID%1000000).tileset->collision[tileID%1000000-GetTileSheet(map,tileID%1000000).firstgid+1].collision;
}
return NO_COLLISION;
}
}
int counter=0;
geom2d::rect<int>foundRect=NO_COLLISION;
for(LayerTag&layer:MAP_DATA[map].LayerData){
auto HasNoClass=[&](){return layer.tag.data.find("class")==layer.tag.data.end();};
if(HasNoClass()&&counter!=bridgeLayerIndex){
//auto HasNoClass=[&](){return layer.tag.data.find("class")==layer.tag.data.end();};
if(counter!=bridgeLayerIndex){
int tileID=layer.tiles[int(pos.y)/24][int(pos.x)/24]-1;
if(tileID!=-1&&GetTileSheet(map,tileID).tileset.collision.find(tileID-GetTileSheet(map,tileID).firstgid+1)!=GetTileSheet(map,tileID).tileset.collision.end()){
return GetTileSheet(map,tileID).tileset.collision[tileID-GetTileSheet(map,tileID).firstgid+1].collision;
if(tileID!=-1&&GetTileSheet(map,tileID%1000000).tileset->collision.find(tileID%1000000-GetTileSheet(map,tileID%1000000).firstgid+1)!=GetTileSheet(map,tileID%1000000).tileset->collision.end()){
geom2d::rect<int>collisionRect=GetTileSheet(map,tileID%1000000).tileset->collision[tileID%1000000-GetTileSheet(map,tileID%1000000).firstgid+1].collision;
if(foundRect.pos==NO_COLLISION.pos&&foundRect.size==NO_COLLISION.size){
foundRect=collisionRect;
}else{
//When we find another rectangle in the same square, we expand it to consume the area, whichever tile creates a larger surface or the combination of the two.
foundRect.pos.x=std::min(foundRect.pos.x,collisionRect.pos.x);
foundRect.pos.y=std::min(foundRect.pos.y,collisionRect.pos.y);
foundRect.size.x=std::max(foundRect.size.x,collisionRect.size.x);
foundRect.size.y=std::max(foundRect.size.y,collisionRect.size.y);
}
}
}
counter++;
}
return NO_COLLISION;
return foundRect;
}
MapName Crawler::GetCurrentLevel(){
@ -1143,9 +1299,8 @@ datafiledoubledata Crawler::GetDoubleList(std::string key){
int main()
{
std::cout<<"I change this"<<std::endl;
Crawler demo;
if (demo.Construct(WINDOW_SIZE.x, WINDOW_SIZE.y, 4, 4))
if (demo.Construct(WINDOW_SIZE.x, WINDOW_SIZE.y, 4, 4, false))
demo.Start();
return 0;
@ -1215,6 +1370,15 @@ void Crawler::OutputDebugInfo(const char*key,std::size_t len){
}
}
bool Crawler::IsReflectiveTile(TilesheetData tileSheet,int tileID){
return tileSheet.tileset->reflectiveData.find(tileID)!=tileSheet.tileset->reflectiveData.end();
}
bool Crawler::OnUserDestroy(){
GFX.Reset();
return true;
}
void Crawler::InitializeLevels(){
#define INITLEVEL(map) \
InitializeLevel("map_path"_S + "Levels."#map ## _S,map); \
@ -1226,4 +1390,8 @@ void Crawler::InitializeLevels(){
INITLEVEL(CAMPAIGN_1_2);
LEVEL_NAMES.SetInitialized();
}
void Crawler::SpawnMonster(vf2d pos,MonsterData*data,bool upperLevel){
monstersToBeSpawned.push_back(Monster(pos,*data,upperLevel));
}

@ -12,32 +12,19 @@
#include "TMXParser.h"
#include "olcUTIL_DataFile.h"
struct TilesheetData{
TilesetData&tileset;
int firstgid;
};
class Crawler : public olc::PixelGameEngine
{
friend class sig::Animation;
Camera2D camera;
std::unique_ptr<Player>player;
Renderable GFX_Warrior_Sheet,
GFX_Effect_GroundSlam_Back,GFX_Effect_GroundSlam_Front,
GFX_Heart,GFX_BLOCK_BUBBLE,GFX_Ranger_Sheet,GFX_Wizard_Sheet,
GFX_Battlecry_Effect,GFX_Mana,GFX_SonicSlash,GFX_EnergyParticle,
GFX_Splash_Effect,GFX_LightningBolt,GFX_LightningBoltParticle1,
GFX_LightningBoltParticle2,GFX_LightningBoltParticle3,GFX_LightningBoltParticle4,
GFX_ChainLightning,GFX_LightningSplash,GFX_Meteor,GFX_Arrow,
GFX_Laser,GFX_ChargedArrow,GFX_RangeIndicator;
public:
Renderable GFX_BulletCircle,GFX_BulletCircleOutline,GFX_EnergyBolt,GFX_Circle;
Pathfinding pathfinder;
static Key KEY_ABILITY1;
static Key KEY_ABILITY2;
static Key KEY_ABILITY3;
static Key KEY_ABILITY4;
static float SIZE_CHANGE_SPEED;
float levelTime;
private:
std::vector<std::unique_ptr<Effect>>foregroundEffects,backgroundEffects,foregroundEffectsToBeInserted,backgroundEffectsToBeInserted;
std::map<MapName,Map>MAP_DATA;
@ -53,10 +40,19 @@ private:
int bridgeLayerIndex=-1;
float bridgeFadeFactor=0.f;
void InitializeClasses();
int DEBUG_PATHFINDING=0;
std::vector<Monster*>monstersBeforeLower,monstersAfterLower,monstersBeforeUpper,monstersAfterUpper;
std::vector<Bullet*>bulletsLower,bulletsUpper;
std::vector<Effect*>backgroundEffectsLower,backgroundEffectsUpper,foregroundEffectsLower,foregroundEffectsUpper;
float reflectionUpdateTimer=0;
float reflectionStepTime=0;
std::set<vi2d>visibleTiles;
std::vector<Monster>monstersToBeSpawned;
public:
Crawler();
bool OnUserCreate() override;
bool OnUserUpdate(float fElapsedTime) override;
bool OnUserDestroy() override;
public:
geom2d::rect<int>NO_COLLISION={};
vi2d WORLD_SIZE={120,8};
@ -88,7 +84,7 @@ public:
//tileID is the tile number from the tilesets.
bool IsForegroundTile(TilesheetData sheet,int tileID);
//tileID is the tile number from the tilesets.
bool IsUpperForegroundTile(TilesheetData sheet,int tileID);
bool IsUpperForegroundTile(int tileID);
//tileID is the tile number from the tilesets.
TilesheetData GetTileSheet(MapName map,int tileID);
//Gets the rectangle of the tile collision at this tile. If upperLevel is set to true, the collision tile must be in a Bridge class layer for the tile to hit. Also, zones containing LowerBridgeCollision will apply when upperLevel is set to false.
@ -98,7 +94,7 @@ public:
MapName GetCurrentLevel();
bool IsBridgeLayer(LayerTag&layer);
std::map<std::string,std::vector<geom2d::rect<int>>>&GetZoneData(MapName map);
void PopulateRenderLists(std::vector<Monster*>&monstersBeforeLower,std::vector<Monster*>&monstersBeforeUpper,std::vector<Monster*>&monstersAfterLower,std::vector<Monster*>&monstersAfterUpper,std::vector<Bullet*>&bulletsLower,std::vector<Bullet*>&bulletsUpper,std::vector<Effect*>&backgroundEffectsLower,std::vector<Effect*>&backgroundEffectsUpper,std::vector<Effect*>&foregroundEffectsLower,std::vector<Effect*>&foregroundEffectsUpper);
void PopulateRenderLists();
void ChangePlayerClass(Class cl);
std::string GetString(std::string key);
datafilestringdata GetStringList(std::string key);
@ -110,6 +106,10 @@ public:
datafiledoubledata GetDoubleList(std::string key);
static void OutputDebugInfo(const char*key,std::size_t len);
void InitializeLevels();
void RenderTile(vi2d pos,TilesheetData tileSheet,int tileSheetIndex,vi2d tileSheetPos);
void RenderTile(TileRenderData&tileSheet,Pixel col);
bool IsReflectiveTile(TilesheetData tileSheet,int tileID);
void SpawnMonster(vf2d pos,MonsterData*data,bool upperLevel=false); //Queues a monster for spawning on the next frame.
struct TileGroupData{
vi2d tilePos;

@ -21,6 +21,18 @@
"layer"
]
},
{
"color": "#ffa44949",
"drawFill": true,
"id": 18,
"members": [
],
"name": "CollisionOnly",
"type": "class",
"useAs": [
"layer"
]
},
{
"color": "#ffbdc34c",
"drawFill": true,
@ -141,6 +153,19 @@
"object"
]
},
{
"color": "#ff0574a4",
"drawFill": true,
"id": 16,
"members": [
],
"name": "Reflective",
"type": "class",
"useAs": [
"property",
"tile"
]
},
{
"color": "#ffe67300",
"drawFill": true,
@ -170,13 +195,7 @@
"type": "class",
"useAs": [
"property",
"map",
"layer",
"object",
"tile",
"tileset",
"wangcolor",
"wangset"
"tile"
]
},
{
@ -208,32 +227,6 @@
"object"
]
},
{
"color": "#ff35e500",
"drawFill": true,
"id": 13,
"members": [
],
"name": "UpperForegroundTile",
"type": "class",
"useAs": [
"property",
"tile"
]
},
{
"color": "#ffff74fd",
"drawFill": true,
"id": 16,
"members": [
],
"name": "UpperSpawnGroup",
"type": "class",
"useAs": [
"property",
"object"
]
},
{
"color": "#ffa40aa4",
"drawFill": true,

@ -302,6 +302,7 @@
<ClCompile Include="Effect.cpp" />
<ClCompile Include="Emitter.cpp" />
<ClCompile Include="EnergyBolt.cpp" />
<ClCompile Include="FallingDebris.h" />
<ClCompile Include="FireBolt.cpp" />
<ClCompile Include="LightningBolt.cpp" />
<ClCompile Include="LightningBoltEmitter.cpp" />
@ -327,6 +328,7 @@
<ClCompile Include="Wizard.cpp" />
</ItemGroup>
<ItemGroup>
<None Include="ClassDiagram2.cd" />
<None Include="cpp.hint" />
</ItemGroup>
<ItemGroup>

@ -239,9 +239,13 @@
<ClCompile Include="SlimeKing.cpp">
<Filter>Source Files\Monster Strategies</Filter>
</ClCompile>
<ClCompile Include="FallingDebris.h">
<Filter>Source Files\Effects</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="cpp.hint" />
<None Include="ClassDiagram2.cd" />
</ItemGroup>
<ItemGroup>
<Text Include="InitialConcept.txt">

@ -5,12 +5,14 @@
#define INCLUDE_DAMAGENUMBER_LIST extern std::vector<std::shared_ptr<DamageNumber>>DAMAGENUMBER_LIST;
#define INCLUDE_game extern Crawler*game;
#define INCLUDE_MONSTER_DATA extern std::map<int,MonsterData>MONSTER_DATA;
#define INCLUDE_MONSTER_NAME_DATA extern safemap<std::string,MonsterData*>MONSTER_NAME_DATA;
#define INCLUDE_BULLET_LIST extern std::vector<std::unique_ptr<Bullet>>BULLET_LIST;
#define INCLUDE_PARTICLE_LIST extern std::vector<Particle>PARTICLE_LIST;
#define INCLUDE_EMITTER_LIST extern std::vector<std::unique_ptr<Emitter>>EMITTER_LIST;
#define INCLUDE_DATA extern utils::datafile DATA;
#define INCLUDE_STRATEGY_DATA extern safemap<std::string,int>STRATEGY_DATA;
#define INCLUDE_STRATEGY_ID_DATA extern safemap<std::string,int>STRATEGY_ID_DATA;
#define INCLUDE_TILE_ANIMATION_DATA extern std::map<int,std::vector<std::pair<int,float>>>TILE_ANIMATION_DATA;
#define INCLUDE_GFX extern safemap<std::string,Renderable>GFX;
#define ACCESS_PLAYER Player*p=game->GetPlayer();

@ -6,14 +6,14 @@
INCLUDE_ANIMATION_DATA
INCLUDE_game
Effect::Effect(vf2d pos,float lifetime,std::string animation,bool upperLevel,float size,float fadeout,vf2d spd,Pixel col,float rotation,float rotationSpd,bool additiveBlending)
:Effect::Effect(pos,lifetime,animation,upperLevel,vf2d{size,size},fadeout,spd,col,rotation,rotationSpd,additiveBlending){
this->animation.AddState(animation,ANIMATION_DATA[animation]);
Effect::Effect(vf2d pos,float lifetime,std::string imgFile,bool upperLevel,float size,float fadeout,vf2d spd,Pixel col,float rotation,float rotationSpd,bool additiveBlending)
:Effect::Effect(pos,lifetime,imgFile,upperLevel,vf2d{size,size},fadeout,spd,col,rotation,rotationSpd,additiveBlending){
this->animation.AddState(imgFile,ANIMATION_DATA[imgFile]);
}
Effect::Effect(vf2d pos,float lifetime,std::string animation,bool upperLevel,vf2d size,float fadeout,vf2d spd,Pixel col,float rotation,float rotationSpd,bool additiveBlending)
Effect::Effect(vf2d pos,float lifetime,std::string imgFile,bool upperLevel,vf2d size,float fadeout,vf2d spd,Pixel col,float rotation,float rotationSpd,bool additiveBlending)
:pos(pos),lifetime(lifetime),upperLevel(upperLevel),size(size),fadeout(fadeout),original_fadeoutTime(fadeout),spd(spd),col(col),rotation(rotation),rotationSpd(rotationSpd),additiveBlending(additiveBlending){
this->animation.AddState(animation,ANIMATION_DATA[animation]);
this->animation.AddState(imgFile,ANIMATION_DATA[imgFile]);
}
bool Effect::Update(float fElapsedTime){

@ -17,8 +17,8 @@ struct Effect{
private:
bool dead=false;
public:
Effect(vf2d pos,float lifetime,std::string animation,bool upperLevel,float size=1.0f,float fadeout=0.0f,vf2d spd={},Pixel col=WHITE,float rotation=0,float rotationSpd=0,bool additiveBlending=false);
Effect(vf2d pos,float lifetime,std::string animation,bool upperLevel,vf2d size={1,1},float fadeout=0.0f,vf2d spd={},Pixel col=WHITE,float rotation=0,float rotationSpd=0,bool additiveBlending=false);
Effect(vf2d pos,float lifetime,std::string imgFile,bool upperLevel,float size=1.0f,float fadeout=0.0f,vf2d spd={},Pixel col=WHITE,float rotation=0,float rotationSpd=0,bool additiveBlending=false);
Effect(vf2d pos,float lifetime,std::string imgFile,bool upperLevel,vf2d size={1,1},float fadeout=0.0f,vf2d spd={},Pixel col=WHITE,float rotation=0,float rotationSpd=0,bool additiveBlending=false);
virtual bool Update(float fElapsedTime);
Animate2D::Frame GetFrame();
virtual void Draw();
@ -32,7 +32,7 @@ private:
};
struct Meteor:Effect{
Meteor(vf2d pos,float lifetime,std::string animation,bool upperLevel,vf2d size={1,1},float fadeout=0.0f,vf2d spd={},Pixel col=WHITE,float rotation=0,float rotationSpd=0,bool additiveBlending=false);
Meteor(vf2d pos,float lifetime,std::string imgFile,bool upperLevel,vf2d size={1,1},float fadeout=0.0f,vf2d spd={},Pixel col=WHITE,float rotation=0,float rotationSpd=0,bool additiveBlending=false);
float startLifetime=0;
bool shakeField=false;
bool Update(float fElapsedTime)override;
@ -40,7 +40,7 @@ struct Meteor:Effect{
};
struct PulsatingFire:Effect{
PulsatingFire(vf2d pos,float lifetime,std::string animation,bool upperLevel,vf2d size={1,1},float fadeout=0.0f,vf2d spd={},Pixel col=WHITE,float rotation=0,float rotationSpd=0,bool additiveBlending=false);
PulsatingFire(vf2d pos,float lifetime,std::string imgFile,bool upperLevel,vf2d size={1,1},float fadeout=0.0f,vf2d spd={},Pixel col=WHITE,float rotation=0,float rotationSpd=0,bool additiveBlending=false);
std::vector<float>pulsatingFireValues;
float lastParticleTimer=0;
float lastDamageTimer=0;

@ -8,13 +8,13 @@ INCLUDE_game
EnergyBolt::EnergyBolt(vf2d pos,vf2d vel,float radius,int damage,bool upperLevel,bool friendly,Pixel col)
:Bullet(pos,vel,radius,damage,
"ENERGY_BOLT",upperLevel,false,INFINITE,true,friendly,col){}
"energy_bolt.png",upperLevel,false,INFINITE,true,friendly,col){}
void EnergyBolt::Update(float fElapsedTime){
lastParticleSpawn=std::max(0.f,lastParticleSpawn-fElapsedTime);
if(lastParticleSpawn==0){
lastParticleSpawn="Wizard.Auto Attack.ParticleFrequency"_F;
game->AddEffect(std::make_unique<Effect>(pos,"Wizard.Auto Attack.ParticleLifetimeRange"_FRange,"ENERGY_PARTICLE",upperLevel,"Wizard.Auto Attack.ParticleSizeRange"_FRange,"Wizard.Auto Attack.ParticleFadeoutTime"_F,vf2d{"Wizard.Auto Attack.ParticleSpeedRange"_FRange,"Wizard.Auto Attack.ParticleSpeedRange"_FRange}));
game->AddEffect(std::make_unique<Effect>(pos,"Wizard.Auto Attack.ParticleLifetimeRange"_FRange,"energy_particle.png",upperLevel,"Wizard.Auto Attack.ParticleSizeRange"_FRange,"Wizard.Auto Attack.ParticleFadeoutTime"_F,vf2d{"Wizard.Auto Attack.ParticleSpeedRange"_FRange,"Wizard.Auto Attack.ParticleSpeedRange"_FRange}));
}
}
@ -22,7 +22,7 @@ bool EnergyBolt::PlayerHit(Player*player)
{
deactivated=true;
fadeOutTime="Wizard.Auto Attack.BulletHitFadeoutTime"_F;
game->AddEffect(std::make_unique<Effect>(player->GetPos(),0,"SPLASH_EFFECT",upperLevel,player->GetSizeMult(),"Wizard.Auto Attack.SplashEffectFadeoutTime"_F));
game->AddEffect(std::make_unique<Effect>(player->GetPos(),0,"splash_effect.png",upperLevel,player->GetSizeMult(),"Wizard.Auto Attack.SplashEffectFadeoutTime"_F));
return false;
}
@ -30,6 +30,6 @@ bool EnergyBolt::MonsterHit(Monster& monster)
{
deactivated=true;
fadeOutTime="Wizard.Auto Attack.BulletHitFadeoutTime"_F;
game->AddEffect(std::make_unique<Effect>(monster.GetPos(),0,"SPLASH_EFFECT",upperLevel,monster.GetSizeMult(),"Wizard.Auto Attack.SplashEffectFadeoutTime"_F));
game->AddEffect(std::make_unique<Effect>(monster.GetPos(),0,"splash_effect.png",upperLevel,monster.GetSizeMult(),"Wizard.Auto Attack.SplashEffectFadeoutTime"_F));
return false;
}

@ -0,0 +1,19 @@
#include "Effect.h"
#include "DEFINES.h"
#include "safemap.h"
INCLUDE_GFX
class FallingDebris:public Effect{
const float GRAVITY=20;
public:
inline FallingDebris(vf2d pos, float lifetime, std::string imgFile, bool upperLevel,vf2d size={1,1},float fadeout=0.0f,vf2d spd={},Pixel col=WHITE,float rotation=0,float rotationSpd=0,bool additiveBlending=false)
:Effect(pos,lifetime,imgFile,upperLevel,size,fadeout,spd,col,rotation,rotationSpd,additiveBlending){
}
inline bool Update(float fElapsedTime)override{
spd.y+=GRAVITY*fElapsedTime;
return Effect::Update(fElapsedTime);
}
};

@ -9,13 +9,13 @@ INCLUDE_MONSTER_LIST
FireBolt::FireBolt(vf2d pos,vf2d vel,float radius,int damage,bool upperLevel,bool friendly,Pixel col)
:Bullet(pos,vel,radius,damage,
"ENERGY_BOLT",upperLevel,false,INFINITE,true,friendly,col){}
"energy_bolt.png",upperLevel,false,INFINITE,true,friendly,col){}
void FireBolt::Update(float fElapsedTime){
lastParticleSpawn=std::max(0.f,lastParticleSpawn-fElapsedTime);
if(lastParticleSpawn==0){
lastParticleSpawn="Wizard.Ability 1.ParticleFrequency"_F;
game->AddEffect(std::make_unique<Effect>(pos,"Wizard.Ability 1.ParticleLifetimeRange"_FRange,"ENERGY_PARTICLE",upperLevel,"Wizard.Ability 1.ParticleSizeRange"_FRange,"Wizard.Ability 1.ParticleFadeoutTime"_F,vf2d{"Wizard.Ability 1.ParticleXSpeedRange"_FRange,"Wizard.Ability 1.ParticleYSpeedRange"_FRange},Pixel{uint8_t("Wizard.Ability 1.ParticleRedRange"_FRange),uint8_t("Wizard.Ability 1.ParticleGreenRange"_FRange),uint8_t("Wizard.Ability 1.ParticleBlueRange"_FRange),uint8_t("Wizard.Ability 1.ParticleAlphaRange"_FRange)}));
game->AddEffect(std::make_unique<Effect>(pos,"Wizard.Ability 1.ParticleLifetimeRange"_FRange,"energy_particle.png",upperLevel,"Wizard.Ability 1.ParticleSizeRange"_FRange,"Wizard.Ability 1.ParticleFadeoutTime"_F,vf2d{"Wizard.Ability 1.ParticleXSpeedRange"_FRange,"Wizard.Ability 1.ParticleYSpeedRange"_FRange},Pixel{uint8_t("Wizard.Ability 1.ParticleRedRange"_FRange),uint8_t("Wizard.Ability 1.ParticleGreenRange"_FRange),uint8_t("Wizard.Ability 1.ParticleBlueRange"_FRange),uint8_t("Wizard.Ability 1.ParticleAlphaRange"_FRange)}));
}
}
@ -23,7 +23,7 @@ bool FireBolt::PlayerHit(Player*player)
{
deactivated=true;
fadeOutTime="Wizard.Ability 1.BulletHitFadeoutTime"_F;
game->AddEffect(std::make_unique<Effect>(player->GetPos(),0,"SPLASH_EFFECT",upperLevel,5,0.25,vf2d{},Pixel{240,120,60}));
game->AddEffect(std::make_unique<Effect>(player->GetPos(),0,"splash_effect.png",upperLevel,5,0.25,vf2d{},Pixel{240,120,60}));
return false;
}
@ -32,10 +32,10 @@ bool FireBolt::MonsterHit(Monster& monster)
deactivated=true;
fadeOutTime="Wizard.Ability 1.BulletHitFadeoutTime"_F;
for(int i=0;i<"Wizard.Ability 1.BulletHitExplosionParticleCount"_I;i++){
game->AddEffect(std::make_unique<Effect>(monster.GetPos(),"Wizard.Ability 1.BulletHitExplosionParticleLifetimeRange"_FRange,"DOT_PARTICLE",upperLevel,"Wizard.Ability 1.BulletHitExplosionParticleSizeRange"_FRange,"Wizard.Ability 1.BulletHitExplosionParticleFadeoutTimeRange"_FRange,vf2d{"Wizard.Ability 1.BulletHitExplosionParticleSpeedRange"_FRange,"Wizard.Ability 1.BulletHitExplosionParticleSpeedRange"_FRange},Pixel{uint8_t("Wizard.Ability 1.BulletHitExplosionParticleRedRange"_FRange),uint8_t("Wizard.Ability 1.BulletHitExplosionParticleGreenRange"_FRange),uint8_t("Wizard.Ability 1.BulletHitExplosionParticleBlueRange"_FRange),uint8_t("Wizard.Ability 1.BulletHitExplosionParticleAlphaRange"_FRange)}));
game->AddEffect(std::make_unique<Effect>(monster.GetPos(),"Wizard.Ability 1.BulletHitExplosionParticleLifetimeRange"_FRange,"circle.png",upperLevel,"Wizard.Ability 1.BulletHitExplosionParticleSizeRange"_FRange,"Wizard.Ability 1.BulletHitExplosionParticleFadeoutTimeRange"_FRange,vf2d{"Wizard.Ability 1.BulletHitExplosionParticleSpeedRange"_FRange,"Wizard.Ability 1.BulletHitExplosionParticleSpeedRange"_FRange},Pixel{uint8_t("Wizard.Ability 1.BulletHitExplosionParticleRedRange"_FRange),uint8_t("Wizard.Ability 1.BulletHitExplosionParticleGreenRange"_FRange),uint8_t("Wizard.Ability 1.BulletHitExplosionParticleBlueRange"_FRange),uint8_t("Wizard.Ability 1.BulletHitExplosionParticleAlphaRange"_FRange)}));
}
game->SetupWorldShake("Wizard.Ability 1.WorldShakeTime"_F);
game->HurtEnemies(monster.GetPos(),"Wizard.Ability 1.BulletHitExplosionRange"_F/100*12,"Wizard.Ability 1.BulletHitExplosionDamageMult"_F*game->GetPlayer()->GetAttack(),OnUpperLevel(),0);
game->AddEffect(std::make_unique<Effect>(monster.GetPos(),0,"SPLASH_EFFECT",upperLevel,"Wizard.Ability 1.BulletHitExplosionRange"_F/100*2,"Wizard.Ability 1.BulletHitExplosionFadeoutTime"_F,vf2d{},"Wizard.Ability 1.BulletHitExplosionColor"_Pixel));
game->AddEffect(std::make_unique<Effect>(monster.GetPos(),0,"splash_effect.png",upperLevel,"Wizard.Ability 1.BulletHitExplosionRange"_F/100*2,"Wizard.Ability 1.BulletHitExplosionFadeoutTime"_F,vf2d{},"Wizard.Ability 1.BulletHitExplosionColor"_Pixel));
return false;
}

@ -11,7 +11,7 @@ INCLUDE_EMITTER_LIST
LightningBolt::LightningBolt(vf2d pos,vf2d vel,float radius,int damage,bool upperLevel,bool friendly,Pixel col)
:Bullet(pos,vel,radius,damage,
"LIGHTNING_BOLT",upperLevel,false,INFINITE,true,friendly,col){}
"lightning_bolt.png",upperLevel,false,INFINITE,true,friendly,col){}
void LightningBolt::Update(float fElapsedTime){
lastParticleSpawn=std::max(0.f,lastParticleSpawn-fElapsedTime);
@ -21,16 +21,16 @@ void LightningBolt::Update(float fElapsedTime){
uint8_t brightness=uint8_t("Wizard.Ability 2.ParticleColorRange"_FRange);
switch(rand()%4){
case 0:{
game->AddEffect(std::make_unique<Effect>(pos+vf2d{"Wizard.Ability 2.ParticleSpawnRadiusRange"_FRange,"Wizard.Ability 2.ParticleSpawnRadiusRange"_FRange},"Wizard.Ability 2.ParticleLifetimeRange"_FRange,"LIGHTNING_BOLT_PARTICLE1",upperLevel,"Wizard.Ability 2.ParticleSizeRange"_FRange,"Wizard.Ability 2.ParticleFadeoutTime"_F,vel*"Wizard.Ability 2.ParticleSpeedMultRange"_FRange,Pixel{brightness,brightness,brightness}));
game->AddEffect(std::make_unique<Effect>(pos+vf2d{"Wizard.Ability 2.ParticleSpawnRadiusRange"_FRange,"Wizard.Ability 2.ParticleSpawnRadiusRange"_FRange},"Wizard.Ability 2.ParticleLifetimeRange"_FRange,"lightning_bolt_part1.png",upperLevel,"Wizard.Ability 2.ParticleSizeRange"_FRange,"Wizard.Ability 2.ParticleFadeoutTime"_F,vel*"Wizard.Ability 2.ParticleSpeedMultRange"_FRange,Pixel{brightness,brightness,brightness}));
}break;
case 1:{
game->AddEffect(std::make_unique<Effect>(pos+vf2d{"Wizard.Ability 2.ParticleSpawnRadiusRange"_FRange,"Wizard.Ability 2.ParticleSpawnRadiusRange"_FRange},"Wizard.Ability 2.ParticleLifetimeRange"_FRange,"LIGHTNING_BOLT_PARTICLE2",upperLevel,"Wizard.Ability 2.ParticleSizeRange"_FRange,"Wizard.Ability 2.ParticleFadeoutTime"_F,vel*"Wizard.Ability 2.ParticleSpeedMultRange"_FRange,Pixel{brightness,brightness,brightness}));
game->AddEffect(std::make_unique<Effect>(pos+vf2d{"Wizard.Ability 2.ParticleSpawnRadiusRange"_FRange,"Wizard.Ability 2.ParticleSpawnRadiusRange"_FRange},"Wizard.Ability 2.ParticleLifetimeRange"_FRange,"lightning_bolt_part2.png",upperLevel,"Wizard.Ability 2.ParticleSizeRange"_FRange,"Wizard.Ability 2.ParticleFadeoutTime"_F,vel*"Wizard.Ability 2.ParticleSpeedMultRange"_FRange,Pixel{brightness,brightness,brightness}));
}break;
case 2:{
game->AddEffect(std::make_unique<Effect>(pos+vf2d{"Wizard.Ability 2.ParticleSpawnRadiusRange"_FRange,"Wizard.Ability 2.ParticleSpawnRadiusRange"_FRange},"Wizard.Ability 2.ParticleLifetimeRange"_FRange,"LIGHTNING_BOLT_PARTICLE3",upperLevel,"Wizard.Ability 2.ParticleSizeRange"_FRange,"Wizard.Ability 2.ParticleFadeoutTime"_F,vel*"Wizard.Ability 2.ParticleSpeedMultRange"_FRange,Pixel{brightness,brightness,brightness}));
game->AddEffect(std::make_unique<Effect>(pos+vf2d{"Wizard.Ability 2.ParticleSpawnRadiusRange"_FRange,"Wizard.Ability 2.ParticleSpawnRadiusRange"_FRange},"Wizard.Ability 2.ParticleLifetimeRange"_FRange,"lightning_bolt_part3.png",upperLevel,"Wizard.Ability 2.ParticleSizeRange"_FRange,"Wizard.Ability 2.ParticleFadeoutTime"_F,vel*"Wizard.Ability 2.ParticleSpeedMultRange"_FRange,Pixel{brightness,brightness,brightness}));
}break;
case 3:{
game->AddEffect(std::make_unique<Effect>(pos+vf2d{"Wizard.Ability 2.ParticleSpawnRadiusRange"_FRange,"Wizard.Ability 2.ParticleSpawnRadiusRange"_FRange},"Wizard.Ability 2.ParticleLifetimeRange"_FRange,"LIGHTNING_BOLT_PARTICLE4",upperLevel,"Wizard.Ability 2.ParticleSizeRange"_FRange,"Wizard.Ability 2.ParticleFadeoutTime"_F,vel*"Wizard.Ability 2.ParticleSpeedMultRange"_FRange,Pixel{brightness,brightness,brightness}));
game->AddEffect(std::make_unique<Effect>(pos+vf2d{"Wizard.Ability 2.ParticleSpawnRadiusRange"_FRange,"Wizard.Ability 2.ParticleSpawnRadiusRange"_FRange},"Wizard.Ability 2.ParticleLifetimeRange"_FRange,"lightning_bolt_part4.png",upperLevel,"Wizard.Ability 2.ParticleSizeRange"_FRange,"Wizard.Ability 2.ParticleFadeoutTime"_F,vel*"Wizard.Ability 2.ParticleSpeedMultRange"_FRange,Pixel{brightness,brightness,brightness}));
}break;
}
}
@ -40,7 +40,7 @@ bool LightningBolt::PlayerHit(Player*player)
{
deactivated=true;
fadeOutTime="Wizard.Ability 2.BulletFadeoutTime"_F;
game->AddEffect(std::make_unique<Effect>(player->GetPos(),"Wizard.Ability 2.SplashLifetime"_F,"LIGHTNING_SPLASH",upperLevel,player->GetSizeMult(),"Wizard.Ability 2.SplashFadeoutTime"_F,vf2d{},WHITE,"Wizard.Ability 2.SplashRotationRange"_FRange));
game->AddEffect(std::make_unique<Effect>(player->GetPos(),"Wizard.Ability 2.SplashLifetime"_F,"lightning_splash_effect.png",upperLevel,player->GetSizeMult(),"Wizard.Ability 2.SplashFadeoutTime"_F,vf2d{},WHITE,"Wizard.Ability 2.SplashRotationRange"_FRange));
return false;
}
@ -48,7 +48,7 @@ bool LightningBolt::MonsterHit(Monster& monster)
{
deactivated=true;
fadeOutTime="Wizard.Ability 2.BulletFadeoutTime"_F;
game->AddEffect(std::make_unique<Effect>(monster.GetPos(),"Wizard.Ability 2.SplashLifetime"_F,"LIGHTNING_SPLASH",upperLevel,monster.GetSizeMult(),"Wizard.Ability 2.SplashFadeoutTime"_F,vf2d{},WHITE,"Wizard.Ability 2.SplashRotationRange"_FRange));
game->AddEffect(std::make_unique<Effect>(monster.GetPos(),"Wizard.Ability 2.SplashLifetime"_F,"lightning_splash_effect.png",upperLevel,monster.GetSizeMult(),"Wizard.Ability 2.SplashFadeoutTime"_F,vf2d{},WHITE,"Wizard.Ability 2.SplashRotationRange"_FRange));
int targetsHit=0;
for(Monster&m:MONSTER_LIST){
if(&m==&monster||monster.OnUpperLevel()!=m.OnUpperLevel())continue;
@ -57,7 +57,7 @@ bool LightningBolt::MonsterHit(Monster& monster)
if(dist<="Wizard.Ability 2.LightningChainRadius"_F/100*24){
if(m.Hurt(game->GetPlayer()->GetAttack()*"Wizard.Ability 2.LightningChainDamageMult"_F,OnUpperLevel(),0)){
EMITTER_LIST.push_back(std::make_unique<LightningBoltEmitter>(LightningBoltEmitter(monster.GetPos(),m.GetPos(),"Wizard.Ability 2.LightningChainFrequency"_F,"Wizard.Ability 2.LightningChainLifetime"_F,upperLevel)));
game->AddEffect(std::make_unique<Effect>(m.GetPos(),"Wizard.Ability 2.LightningChainSplashLifetime"_F,"LIGHTNING_SPLASH",upperLevel,monster.GetSizeMult(),"Wizard.Ability 2.LightningChainSplashFadeoutTime"_F,vf2d{},WHITE,"Wizard.Ability 2.LightningChainSplashRotationRange"_FRange));
game->AddEffect(std::make_unique<Effect>(m.GetPos(),"Wizard.Ability 2.LightningChainSplashLifetime"_F,"lightning_splash_effect.png",upperLevel,monster.GetSizeMult(),"Wizard.Ability 2.LightningChainSplashFadeoutTime"_F,vf2d{},WHITE,"Wizard.Ability 2.LightningChainSplashRotationRange"_FRange));
targetsHit++;
}
}

@ -22,7 +22,7 @@ void LightningBoltEmitter::DrawLightningBolt(){
float targetDist=lineToTarget.length()*util::random(0.5);
targetAngle+=util::random((PI/2))-PI/4;
geom2d::line<float>lightningLine=geom2d::line<float>(currentPos,currentPos+vf2d{cos(targetAngle)*targetDist,sin(targetAngle)*targetDist});
game->AddEffect(std::make_unique<Effect>(lightningLine.upoint(0),0,"CHAIN_LIGHTNING",upperLevel,vf2d{lightningLine.length(),0.2},0.2,vf2d{},WHITE,targetAngle,0,true));
game->AddEffect(std::make_unique<Effect>(lightningLine.upoint(0),0,"chain_lightning.png",upperLevel,vf2d{lightningLine.length(),0.2},0.2,vf2d{},WHITE,targetAngle,0,true));
int iterations=1;
currentPos+=vf2d{cos(targetAngle)*targetDist,sin(targetAngle)*targetDist};
while(iterations<MAX_ITERATIONS&&geom2d::line<float>(currentPos,endPos).length()>1){
@ -31,7 +31,7 @@ void LightningBoltEmitter::DrawLightningBolt(){
float targetDist=lineToTarget.length()*util::random(0.5);
targetAngle+=util::random((PI/2))-PI/4;
geom2d::line<float>lightningLine=geom2d::line<float>(currentPos,currentPos+vf2d{cos(targetAngle)*targetDist,sin(targetAngle)*targetDist});
game->AddEffect(std::make_unique<Effect>(lightningLine.upoint(0),0,"CHAIN_LIGHTNING",upperLevel,vf2d{lightningLine.length(),0.2},0.2,vf2d{},WHITE,targetAngle,0,true));
game->AddEffect(std::make_unique<Effect>(lightningLine.upoint(0),0,"chain_lightning.png",upperLevel,vf2d{lightningLine.length(),0.2},0.2,vf2d{},WHITE,targetAngle,0,true));
currentPos+=vf2d{cos(targetAngle)*targetDist,sin(targetAngle)*targetDist};
iterations++;
}

@ -33,7 +33,7 @@ geom2d::rect<int>TileGroup::GetRange(){
}
geom2d::rect<int>TileGroup::GetFadeRange(){
return {range.pos+vi2d{-24,-24},range.size+vi2d{48,48}};
return {range.pos+vi2d{-24,-24},range.size+vi2d{48,24}};
}
std::vector<TileRenderData>&TileGroup::GetTiles(){

@ -1,5 +1,6 @@
#pragma once
#include "olcUTIL_Geometry2D.h"
#include <set>
struct XMLTag;
@ -20,12 +21,21 @@ struct TilesetData{
std::map<int,XMLTag>upperForegroundTiles;
std::map<int,TileCollisionData>collision;
std::map<int,XMLTag>staircaseTiles;
std::map<int,std::vector<int>>animationData;
std::set<int>reflectiveData;
};
struct TilesheetData{
TilesetData*tileset;
int firstgid;
};
struct TileRenderData{
Decal*tileset;
TilesheetData tileSheet;
vi2d pos;
vi2d tileSheetPos;
int tileID;
int layerID;
};
struct TileGroup{
@ -44,5 +54,4 @@ public:
void InsertTile(TileRenderData tile);
bool playerBehind=false;
float fadeFactor=0.f;
int originatingLayer=-1;
};

@ -2,12 +2,14 @@
#include "DEFINES.h"
#include "Crawler.h"
#include "utils.h"
#include "safemap.h"
INCLUDE_game
INCLUDE_MONSTER_LIST
INCLUDE_GFX
Meteor::Meteor(vf2d pos, float lifetime, std::string animation, bool upperLevel, vf2d size, float fadeout, vf2d spd, Pixel col, float rotation, float rotationSpd, bool additiveBlending)
:Effect(pos,lifetime,animation,upperLevel,size,fadeout,spd,col,rotation,rotationSpd,additiveBlending),startLifetime(lifetime){
Meteor::Meteor(vf2d pos, float lifetime, std::string imgFile, bool upperLevel, vf2d size, float fadeout, vf2d spd, Pixel col, float rotation, float rotationSpd, bool additiveBlending)
:Effect(pos,lifetime,imgFile,upperLevel,size,fadeout,spd,col,rotation,rotationSpd,additiveBlending),startLifetime(lifetime){
}
@ -22,10 +24,10 @@ bool Meteor::Update(float fElapsedTime){
float randomColorTintG=256*(1-util::random("Wizard.Ability 3.MeteorImpactParticleColorGVariance"_F))*(1-util::random("Wizard.Ability 3.MeteorImpactParticleColorGVariance"_F));
float randomColorTintB="Wizard.Ability 3.MeteorImpactParticleColorBlueRange"_FRange;
vf2d effectPos=vf2d{cos(randomAngle),sin(randomAngle)}*randomRange+meteorOffset;
game->AddEffect(std::make_unique<Effect>(effectPos,0,"DOT_PARTICLE",OnUpperLevel(),vf2d{util::random(2)+1,util::random(3)+1},util::random(3)+1,vf2d{util::random(10)-5,-util::random(20)-5},Pixel{255,uint8_t(randomColorTintG),uint8_t(randomColorTintB),uint8_t("Wizard.Ability 3.MeteorImpactParticleAlphaRange"_FRange)},0,0,true),effectPos.y<meteorOffset.y);
game->AddEffect(std::make_unique<Effect>(effectPos,0,"circle.png",OnUpperLevel(),vf2d{util::random(2)+1,util::random(3)+1},util::random(3)+1,vf2d{util::random(10)-5,-util::random(20)-5},Pixel{255,uint8_t(randomColorTintG),uint8_t(randomColorTintB),uint8_t("Wizard.Ability 3.MeteorImpactParticleAlphaRange"_FRange)},0,0,true),effectPos.y<meteorOffset.y);
}
game->HurtEnemies(pos,"Wizard.Ability 3.MeteorRadius"_F/100*24,game->GetPlayer()->GetAttack()*"Wizard.Ability 3.MeteorDamageMult"_F,OnUpperLevel(),0);
game->AddEffect(std::make_unique<PulsatingFire>(pos,"Wizard.Ability 3.FireRingLifetime"_F,"FIRE_RING1",OnUpperLevel(),vf2d{"Wizard.Ability 3.MeteorRadius"_F/100*2,"Wizard.Ability 3.MeteorRadius"_F/100*2},"Wizard.Ability 3.FireRingFadeoutTime"_F),true);
game->AddEffect(std::make_unique<PulsatingFire>(pos,"Wizard.Ability 3.FireRingLifetime"_F,"fire_ring1.png",OnUpperLevel(),vf2d{"Wizard.Ability 3.MeteorRadius"_F/100*2,"Wizard.Ability 3.MeteorRadius"_F/100*2},"Wizard.Ability 3.FireRingFadeoutTime"_F),true);
}
return Effect::Update(fElapsedTime);
}
@ -34,8 +36,8 @@ void Meteor::Draw(){
if(lifetime>0){
vf2d scale=vf2d{192,64}/3.f*(startLifetime+1-lifetime)*0.25*size;
vf2d meteorOffset=vf2d{lifetime*"Wizard.Ability 3.MeteorXMovementMult"_I,0}*"Wizard.Ability 3.MeteorShadowStartingDist"_F;
vf2d centerPoint=pos-vf2d{game->GFX_Circle.Sprite()->width*scale.x/2,game->GFX_Circle.Sprite()->height*scale.y/2};
game->view.DrawDecal(centerPoint+meteorOffset,game->GFX_Circle.Decal(),scale,{0,0,0,192});
vf2d centerPoint=pos-vf2d{GFX["circle.png"].Sprite()->width*scale.x/2,GFX["circle.png"].Sprite()->height*scale.y/2};
game->view.DrawDecal(centerPoint+meteorOffset,GFX["circle.png"].Decal(),scale,{0,0,0,192});
}
vf2d meteorOffset=pos+vf2d{lifetime*"Wizard.Ability 3.MeteorXMovementMult"_I,lifetime*"Wizard.Ability 3.MeteorYMovementMult"_I}*"Wizard.Ability 3.MeteorStartingDist"_F-vf2d{0,GetFrame().GetSourceRect().size.y/4.f}*size;
if(lifetime<=0){

@ -5,6 +5,8 @@
#include "BulletTypes.h"
#include "DEFINES.h"
#include "safemap.h"
#include "MonsterStrategyHelpers.h"
#include "utils.h"
INCLUDE_ANIMATION_DATA
INCLUDE_MONSTER_DATA
@ -14,6 +16,7 @@ INCLUDE_game
INCLUDE_BULLET_LIST
INCLUDE_DATA
INCLUDE_STRATEGY_DATA
INCLUDE_GFX
safemap<std::string,int>STRATEGY_DATA;
safemap<int,std::string>STRATEGY_ID_DATA;
@ -139,7 +142,7 @@ bool Monster::Update(float fElapsedTime){
}
}
}
if(!game->GetPlayer()->HasIframes()&&game->GetPlayer()->OnUpperLevel()==OnUpperLevel()&&geom2d::overlaps(geom2d::circle(pos,12*size/2),geom2d::circle(game->GetPlayer()->GetPos(),12*game->GetPlayer()->GetSizeMult()/2))){
if(!game->GetPlayer()->HasIframes()&&abs(game->GetPlayer()->GetZ()-GetZ())<=1&&game->GetPlayer()->OnUpperLevel()==OnUpperLevel()&&geom2d::overlaps(geom2d::circle(pos,12*size/2),geom2d::circle(game->GetPlayer()->GetPos(),12*game->GetPlayer()->GetSizeMult()/2))){
geom2d::line line(pos,game->GetPlayer()->GetPos());
float dist = line.length();
SetPos(line.rpoint(-0.1));
@ -183,16 +186,16 @@ Key Monster::GetFacingDirection(){
return facingDirection;
}
void Monster::Draw(){
strategyDraw(game);
if(GetZ()>0){
vf2d shadowScale=vf2d{8*GetSizeMult()/3.f,1}/std::max(1.f,GetZ()/24);
game->view.DrawDecal(GetPos()-vf2d{3,3}*shadowScale/2+vf2d{0,6*GetSizeMult()},game->GFX_Circle.Decal(),shadowScale,BLACK);
}
if(GetFacingDirection()==RIGHT){
game->view.DrawPartialDecal((GetPos()+vf2d{float(GetFrame().GetSourceRect().size.x),0}*GetSizeMult())-vf2d{12,12}*GetSizeMult()-vf2d{0,GetZ()},GetFrame().GetSourceImage()->Decal(),GetFrame().GetSourceRect().pos,GetFrame().GetSourceRect().size,vf2d(GetSizeMult()*-1,GetSizeMult()),GetBuffs(BuffType::SLOWDOWN).size()>0?Pixel{uint8_t(255*abs(sin(1.4*GetBuffs(BuffType::SLOWDOWN)[0].duration))),uint8_t(255*abs(sin(1.4*GetBuffs(BuffType::SLOWDOWN)[0].duration))),uint8_t(128+127*abs(sin(1.4*GetBuffs(BuffType::SLOWDOWN)[0].duration)))}:WHITE);
} else {
game->view.DrawPartialDecal(GetPos()-vf2d{12,12}*GetSizeMult()-vf2d{0,GetZ()},GetFrame().GetSourceImage()->Decal(),GetFrame().GetSourceRect().pos,GetFrame().GetSourceRect().size,vf2d(GetSizeMult(),GetSizeMult()),GetBuffs(BuffType::SLOWDOWN).size()>0?Pixel{uint8_t(255*abs(sin(1.4*GetBuffs(BuffType::SLOWDOWN)[0].duration))),uint8_t(255*abs(sin(1.4*GetBuffs(BuffType::SLOWDOWN)[0].duration))),uint8_t(128+127*abs(sin(1.4*GetBuffs(BuffType::SLOWDOWN)[0].duration)))}:WHITE);
game->view.DrawDecal(GetPos()-vf2d{3,3}*shadowScale/2+vf2d{0,6*GetSizeMult()},GFX["circle.png"].Decal(),shadowScale,BLACK);
}
game->view.DrawPartialRotatedDecal(GetPos()-vf2d{0,GetZ()},GetFrame().GetSourceImage()->Decal(),0,GetFrame().GetSourceRect().size/2,GetFrame().GetSourceRect().pos,GetFrame().GetSourceRect().size,vf2d(GetSizeMult()*(GetFacingDirection()==RIGHT?-1:1),GetSizeMult()),GetBuffs(BuffType::SLOWDOWN).size()>0?Pixel{uint8_t(255*abs(sin(1.4*GetBuffs(BuffType::SLOWDOWN)[0].duration))),uint8_t(255*abs(sin(1.4*GetBuffs(BuffType::SLOWDOWN)[0].duration))),uint8_t(128+127*abs(sin(1.4*GetBuffs(BuffType::SLOWDOWN)[0].duration)))}:WHITE);
}
void Monster::DrawReflection(float drawRatioX,float multiplierX){
game->SetDecalMode(DecalMode::ADDITIVE);
game->view.DrawPartialRotatedDecal(GetPos()+vf2d{drawRatioX*GetFrame().GetSourceRect().size.x,GetZ()+(GetFrame().GetSourceRect().size.y-16)*GetSizeMult()},GetFrame().GetSourceImage()->Decal(),0,GetFrame().GetSourceRect().size/2,GetFrame().GetSourceRect().pos,GetFrame().GetSourceRect().size,vf2d(GetSizeMult()*(GetFacingDirection()==RIGHT?-1:1)*multiplierX,GetSizeMult()*-1),GetBuffs(BuffType::SLOWDOWN).size()>0?Pixel{uint8_t(255*abs(sin(1.4*GetBuffs(BuffType::SLOWDOWN)[0].duration))),uint8_t(255*abs(sin(1.4*GetBuffs(BuffType::SLOWDOWN)[0].duration))),uint8_t(128+127*abs(sin(1.4*GetBuffs(BuffType::SLOWDOWN)[0].duration)))}:WHITE);
game->SetDecalMode(DecalMode::NORMAL);
}
void Monster::Collision(Player*p){
if(MONSTER_DATA[id].GetCollisionDmg()>0&&!hasHitPlayer){
@ -206,7 +209,7 @@ void Monster::Collision(Monster&m){
Collision();
}
void Monster::Collision(){
if(strategy==0&&GetState()==State::MOVE_TOWARDS){//The run towards strategy causes state to return to normal upon a collision.
if(strategy==0&&GetState()==State::MOVE_TOWARDS&&util::random(Monster::STRATEGY::_GetInt(*this,"BumpStopChance",strategy))<1){//The run towards strategy causes state to return to normal upon a collision.
SetState(State::NORMAL);
}
}
@ -285,7 +288,7 @@ void MonsterSpawner::SetTriggered(bool trigger,bool spawnMonsters){
triggered=trigger;
if(spawnMonsters){
for(std::pair<int,vf2d>&monsterInfo:monsters){
MONSTER_LIST.push_back(Monster(pos+monsterInfo.second,MONSTER_DATA[monsterInfo.first],DoesUpperLevelSpawning()));
game->SpawnMonster(pos+monsterInfo.second,&MONSTER_DATA[monsterInfo.first],DoesUpperLevelSpawning());
}
}
}

@ -92,7 +92,6 @@ private:
bool diesNormally=true; //If set to false, the monster death is handled in a special way. Set it to true when it's time to die.
float targetSize=0;
std::map<Attribute,std::variant<VARIANTS>>attributes;
std::function<void(Crawler*)>strategyDraw=[](Crawler*pge){};
protected:
public:
Monster()=delete;
@ -112,6 +111,7 @@ public:
vf2d&GetTargetPos();
Key GetFacingDirection();
void Draw();
void DrawReflection(float drawRatioX,float multiplierX);
void Collision(Player*p);
void Collision(Monster&p);
void Collision();
@ -145,6 +145,7 @@ public:
bool&GetBool(Attribute a);
vf2d&GetVf2d(Attribute a);
void SetStrategyDrawFunction(std::function<void(Crawler*)>func);
std::function<void(Crawler*)>strategyDraw=[](Crawler*pge){};
private:
struct STRATEGY{
static int _GetInt(Monster&m,std::string param,int strategyNumber,int index=0);

@ -20,4 +20,6 @@ enum class Attribute{
JUMP_TARGET_POS,
JUMP_ORIGINAL_POS,
RECOVERY_TIME,
SHOOT_ANIMATION_TIME,
SHOOT_TIMER,
};

@ -10,6 +10,7 @@ INCLUDE_STRATEGY_DATA
INCLUDE_ANIMATION_DATA
std::map<int,MonsterData>MONSTER_DATA;
safemap<std::string,MonsterData*>MONSTER_NAME_DATA;
MonsterData::MonsterData()
:atk(0),collisionDmg(0),hp(0),id(0),moveSpd(0),size(0),strategy(0){}
@ -98,6 +99,7 @@ void MonsterData::InitializeMonsterData(){
);
MONSTER_DATA[id]=monster;
MONSTER_NAME_DATA[MonsterName]=&MONSTER_DATA[id];
id++;
}

@ -88,6 +88,7 @@ std::vector<vf2d> Pathfinding::Solve_AStar(vf2d startPos,vf2d endPos,float maxRa
nodeStart->fGlobalGoal = heuristic(nodeStart, nodeEnd);
std::list<sNode*> listNotTestedNodes;
//if((!upperLevel && nodeStart->bObstacle)||(upperLevel && nodeStart->bObstacleUpper))return {};
listNotTestedNodes.push_back(nodeStart);
while (!listNotTestedNodes.empty() && nodeCurrent != nodeEnd)

@ -6,6 +6,7 @@
#include "BulletTypes.h"
#include "DEFINES.h"
#include "safemap.h"
#include "utils.h"
INCLUDE_MONSTER_DATA
INCLUDE_MONSTER_LIST
@ -230,7 +231,7 @@ void Player::Update(float fElapsedTime){
spin_angle-=spin_spd*fElapsedTime;
}
if(spin_attack_timer>0){
z="Warrior.Ability 2.SpinMaxHeight"_I*sin(3.3*(GROUND_SLAM_SPIN_TIME-spin_attack_timer)/GROUND_SLAM_SPIN_TIME);
z=float("Warrior.Ability 2.SpinMaxHeight"_I)*sin(3.3*(GROUND_SLAM_SPIN_TIME-spin_attack_timer)/GROUND_SLAM_SPIN_TIME);
spin_attack_timer=std::max(0.f,spin_attack_timer-fElapsedTime);
} else {
SetState(State::NORMAL);
@ -238,7 +239,7 @@ void Player::Update(float fElapsedTime){
z=0;
float numb=4;
game->HurtEnemies(pos,"Warrior.Ability 2.Range"_F/100*12,GetAttack()*"Warrior.Ability 2.DamageMult"_F,OnUpperLevel(),0);
game->AddEffect(std::make_unique<Effect>(GetPos(),"Warrior.Ability 2.EffectLifetime"_F,"GROUND_SLAM_ATTACK_FRONT",upperLevel,"Warrior.Ability 2.Range"_F/300*1.33f,"Warrior.Ability 2.EffectFadetime"_F),std::make_unique<Effect>(GetPos(),"Warrior.Ability 2.EffectLifetime"_F,"GROUND_SLAM_ATTACK_BACK",upperLevel,"Warrior.Ability 2.Range"_F/300*1.33f,"Warrior.Ability 2.EffectFadetime"_F));
game->AddEffect(std::make_unique<Effect>(GetPos(),"Warrior.Ability 2.EffectLifetime"_F,"ground-slam-attack-front.png",upperLevel,"Warrior.Ability 2.Range"_F/300*1.33f,"Warrior.Ability 2.EffectFadetime"_F),std::make_unique<Effect>(GetPos(),"Warrior.Ability 2.EffectLifetime"_F,"ground-slam-attack-back.png",upperLevel,"Warrior.Ability 2.Range"_F/300*1.33f,"Warrior.Ability 2.EffectFadetime"_F));
}
if(lastAnimationFlip>0){
lastAnimationFlip=std::max(0.f,lastAnimationFlip-fElapsedTime);
@ -310,7 +311,11 @@ void Player::Update(float fElapsedTime){
}
geom2d::line line(pos,m.GetPos());
float dist = line.length();
m.SetPos(line.rpoint(dist*1.1));
if(dist<=0.001){
m.SetPos(m.GetPos()+vf2d{util::random(2)-1,util::random(2)-1});
}else{
m.SetPos(line.rpoint(dist*1.1));
}
if(m.IsAlive()){
vel=line.vector().norm()*-128;
}
@ -341,9 +346,13 @@ void Player::Update(float fElapsedTime){
//If pressed is set to false, uses held instead.
auto CheckAndPerformAbility=[&](Ability&ability,HWButton key){
if(ability.name!="???"){
if(CanAct()){
if(CanAct(ability)){
if(ability.cooldown==0&&GetMana()>=ability.manaCost){
if(key.bHeld||key.bReleased&&&ability==castPrepAbility&&GetState()==State::PREP_CAST){
if(GetState()==State::CASTING){
SetState(State::NORMAL);
castInfo.castTimer=castInfo.castTotalTime=0;
}
if(AllowedToCast(ability)&&ability.action(this,{})){
ability.cooldown=ability.COOLDOWN_TIME;
mana-=ability.manaCost;
@ -483,7 +492,12 @@ bool Player::CanMove(){
}
bool Player::CanAct(){
return state!=State::CASTING&&state!=State::ANIMATION_LOCK;
Ability dummyAbility{"Dummy Ability",0,0};
return CanAct(dummyAbility);
}
bool Player::CanAct(Ability&ability){
return (ability.canCancelCast||state!=State::CASTING)&&state!=State::ANIMATION_LOCK;
}
bool Player::HasIframes(){
@ -669,4 +683,8 @@ void Player::SetAnimationBasedOnTargetingDirection(float targetDirection){
UpdateAnimation("RANGER_SHOOT_N");
}
}
}
void Player::SetIframes(float duration){
iframe_time=duration;
}

@ -53,6 +53,7 @@ private:
float lastHitTimer=0; //When this is greater than zero, if we get hit again it adds to our displayed combo number.
std::shared_ptr<DamageNumber>damageNumberPtr;
void Initialize();
float iframe_time=0;
protected:
const float ATTACK_COOLDOWN="Warrior.Auto Attack.Cooldown"_F;
const float MAGIC_ATTACK_COOLDOWN="Wizard.Auto Attack.Cooldown"_F;
@ -69,10 +70,8 @@ protected:
void SetZ(float z);
//Returns true if the move was valid and successful.
bool SetPos(vf2d pos);
void Knockback(vf2d vel);
float friction="Player.Friction"_F;
float attack_cooldown_timer=0;
float iframe_time=0;
float teleportAnimationTimer=0;
vf2d teleportTarget={};
vf2d teleportStartPosition={};
@ -130,6 +129,9 @@ public:
bool CanPathfindTo(vf2d pos,vf2d targetPos,float range=8);
bool CanMove();
bool CanAct();
bool CanAct(Ability&ability);
void Knockback(vf2d vel);
void SetIframes(float duration);
void AddBuff(BuffType type,float duration,float intensity);
std::vector<Buff>GetBuffs(BuffType buff);
@ -352,7 +354,8 @@ struct Witch:Player{
#class".Right Click Ability.Mana Cost"_I, \
{uint8_t(#class".Right Click Ability.Cooldown Bar Color 1"_f[0]),uint8_t(#class".Right Click Ability.Cooldown Bar Color 1"_f[1]),uint8_t(#class".Right Click Ability.Cooldown Bar Color 1"_f[2]),uint8_t(#class".Right Click Ability.Cooldown Bar Color 1"_f[3]==0?255:#class".Right Click Ability.Cooldown Bar Color 1"_f[3])}, \
{uint8_t(#class".Right Click Ability.Cooldown Bar Color 2"_f[0]),uint8_t(#class".Right Click Ability.Cooldown Bar Color 2"_f[1]),uint8_t(#class".Right Click Ability.Cooldown Bar Color 2"_f[2]),uint8_t(#class".Right Click Ability.Cooldown Bar Color 2"_f[3]==0?255:#class".Right Click Ability.Cooldown Bar Color 2"_f[3])}, \
{#class".Right Click Ability.Precast Time"_F,#class".Right Click Ability.Casting Range"_I/100.f*24,#class".Right Click Ability.Casting Size"_I/100.f*24} \
{#class".Right Click Ability.Precast Time"_F,#class".Right Click Ability.Casting Range"_I/100.f*24,#class".Right Click Ability.Casting Size"_I/100.f*24}, \
bool( #class".Right Click Ability.CancelCast"_I ) \
}; \
class::ability1={ \
#class".Ability 1.Name"_S, \
@ -360,7 +363,8 @@ struct Witch:Player{
#class".Ability 1.Mana Cost"_I, \
{uint8_t(#class".Ability 1.Cooldown Bar Color 1"_f[0]),uint8_t(#class".Ability 1.Cooldown Bar Color 1"_f[1]),uint8_t(#class".Ability 1.Cooldown Bar Color 1"_f[2]),uint8_t(#class".Ability 1.Cooldown Bar Color 1"_f[3]==0?255:#class".Ability 1.Cooldown Bar Color 1"_f[3])}, \
{uint8_t(#class".Ability 1.Cooldown Bar Color 2"_f[0]),uint8_t(#class".Ability 1.Cooldown Bar Color 2"_f[1]),uint8_t(#class".Ability 1.Cooldown Bar Color 2"_f[2]),uint8_t(#class".Ability 1.Cooldown Bar Color 2"_f[3]==0?255:#class".Ability 1.Cooldown Bar Color 2"_f[3])}, \
{#class".Ability 1.Precast Time"_F,#class".Ability 1.Casting Range"_I/100.f*24,#class".Ability 1.Casting Size"_I/100.f*24} \
{#class".Ability 1.Precast Time"_F,#class".Ability 1.Casting Range"_I/100.f*24,#class".Ability 1.Casting Size"_I/100.f*24}, \
bool(#class".Ability 1.CancelCast"_I) \
}; \
class::ability2={ \
#class".Ability 2.Name"_S, \
@ -368,7 +372,8 @@ struct Witch:Player{
#class".Ability 2.Mana Cost"_I, \
{uint8_t(#class".Ability 2.Cooldown Bar Color 1"_f[0]),uint8_t(#class".Ability 2.Cooldown Bar Color 1"_f[1]),uint8_t(#class".Ability 2.Cooldown Bar Color 1"_f[2]),uint8_t(#class".Ability 2.Cooldown Bar Color 1"_f[3]==0?255:#class".Ability 2.Cooldown Bar Color 1"_f[3])}, \
{uint8_t(#class".Ability 2.Cooldown Bar Color 2"_f[0]),uint8_t(#class".Ability 2.Cooldown Bar Color 2"_f[1]),uint8_t(#class".Ability 2.Cooldown Bar Color 2"_f[2]),uint8_t(#class".Ability 2.Cooldown Bar Color 2"_f[3]==0?255:#class".Ability 2.Cooldown Bar Color 2"_f[3])}, \
{#class".Ability 2.Precast Time"_F,#class".Ability 2.Casting Range"_I/100.f*24,#class".Ability 2.Casting Size"_I/100.f*24} \
{#class".Ability 2.Precast Time"_F,#class".Ability 2.Casting Range"_I/100.f*24,#class".Ability 2.Casting Size"_I/100.f*24}, \
bool(#class".Ability 2.CancelCast"_I) \
}; \
class::ability3={ \
#class".Ability 3.Name"_S, \
@ -376,6 +381,7 @@ struct Witch:Player{
#class".Ability 3.Mana Cost"_I, \
{uint8_t(#class".Ability 3.Cooldown Bar Color 1"_f[0]),uint8_t(#class".Ability 3.Cooldown Bar Color 1"_f[1]),uint8_t(#class".Ability 3.Cooldown Bar Color 1"_f[2]),uint8_t(#class".Ability 3.Cooldown Bar Color 1"_f[3]==0?255:#class".Ability 3.Cooldown Bar Color 1"_f[3])}, \
{uint8_t(#class".Ability 3.Cooldown Bar Color 2"_f[0]),uint8_t(#class".Ability 3.Cooldown Bar Color 2"_f[1]),uint8_t(#class".Ability 3.Cooldown Bar Color 2"_f[2]),uint8_t(#class".Ability 3.Cooldown Bar Color 2"_f[3]==0?255:#class".Ability 3.Cooldown Bar Color 2"_f[3])}, \
{#class".Ability 3.Precast Time"_F,#class".Ability 3.Casting Range"_I/100.f*24,#class".Ability 3.Casting Size"_I/100.f*24} \
{#class".Ability 3.Precast Time"_F,#class".Ability 3.Casting Range"_I/100.f*24,#class".Ability 3.Casting Size"_I/100.f*24}, \
bool(#class".Ability 3.CancelCast"_I) \
}; \
class::ability4={"???",0,0};

@ -25,7 +25,7 @@ bool PulsatingFire::Update(float fElapsedTime){
float randomRange=12*size.x*(1-util::random("Wizard.Ability 3.FireRingParticleRandomVariance"_F))*(1-util::random("Wizard.Ability 3.FireRingParticleRandomVariance"_F));
float randomColorTintG=128*(1-util::random("Wizard.Ability 3.FireRingParticleColorGVariance"_F))*(1-util::random("Wizard.Ability 3.FireRingParticleColorGVariance"_F));
float randomColorTint="Wizard.Ability 3.FireRingParticleColorBlueRange"_FRange;
game->AddEffect(std::make_unique<Effect>(pos+vf2d{cos(randomAngle),sin(randomAngle)}*randomRange,0,"DOT_PARTICLE",OnUpperLevel(),vf2d{"Wizard.Ability 3.FireRingParticleXSizeRange"_FRange,"Wizard.Ability 3.FireRingParticleYSizeRange"_FRange},"Wizard.Ability 3.FireRingParticleFadeoutTimeRange"_FRange,vf2d{"Wizard.Ability 3.FireRingParticleXSpeedRange"_FRange,"Wizard.Ability 3.FireRingParticleYSpeedRange"_FRange},Pixel{128,uint8_t(randomColorTintG),uint8_t(randomColorTint),uint8_t("Wizard.Ability 3.FireRingParticleAlphaRange"_FRange)}));
game->AddEffect(std::make_unique<Effect>(pos+vf2d{cos(randomAngle),sin(randomAngle)}*randomRange,0,"circle.png",OnUpperLevel(),vf2d{"Wizard.Ability 3.FireRingParticleXSizeRange"_FRange,"Wizard.Ability 3.FireRingParticleYSizeRange"_FRange},"Wizard.Ability 3.FireRingParticleFadeoutTimeRange"_FRange,vf2d{"Wizard.Ability 3.FireRingParticleXSpeedRange"_FRange,"Wizard.Ability 3.FireRingParticleYSpeedRange"_FRange},Pixel{128,uint8_t(randomColorTintG),uint8_t(randomColorTint),uint8_t("Wizard.Ability 3.FireRingParticleAlphaRange"_FRange)}));
}
lastParticleTimer="Wizard.Ability 3.FireRingParticleFreqRange"_FRange;
}
@ -41,22 +41,22 @@ void PulsatingFire::Draw(){
Animate2D::FrameSequence*effectSpr=nullptr;
switch(int(pulsatingFireValues[i]*5)){
case 0:{
effectSpr=&ANIMATION_DATA["FIRE_RING1"];
effectSpr=&ANIMATION_DATA["fire_ring0.png"];
}break;
case 1:{
effectSpr=&ANIMATION_DATA["FIRE_RING2"];
effectSpr=&ANIMATION_DATA["fire_ring1.png"];
}break;
case 2:{
effectSpr=&ANIMATION_DATA["FIRE_RING3"];
effectSpr=&ANIMATION_DATA["fire_ring2.png"];
}break;
case 3:{
effectSpr=&ANIMATION_DATA["FIRE_RING4"];
effectSpr=&ANIMATION_DATA["fire_ring3.png"];
}break;
case 4:{
effectSpr=&ANIMATION_DATA["FIRE_RING5"];
effectSpr=&ANIMATION_DATA["fire_ring4.png"];
}break;
default:
effectSpr=&ANIMATION_DATA["FIRE_RING1"];
effectSpr=&ANIMATION_DATA["fire_ring0.png"];
}
const Renderable*img=effectSpr->GetFrame(0).GetSourceImage();
game->view.DrawPartialDecal(pos-effectSpr->GetFrame(0).GetSourceRect().size/2*size,img->Decal(),effectSpr->GetFrame(0).GetSourceRect().pos,effectSpr->GetFrame(0).GetSourceRect().size,size,{255,uint8_t(pulsatingFireValues[i]*256),0,uint8_t((63*(sin("Wizard.Ability 3.FireRingOscillatingFrequency"_F*lifetime+PI*pulsatingFireValues[i]))+63)*(fadeout/original_fadeoutTime))});

@ -4,29 +4,77 @@
#include "Crawler.h"
#include "utils.h"
#include "safemap.h"
#include "Effect.h"
#include "FallingDebris.h"
INCLUDE_game
INCLUDE_BULLET_LIST
INCLUDE_ANIMATION_DATA
INCLUDE_MONSTER_NAME_DATA
typedef Attribute A;
void Monster::STRATEGY::SLIMEKING(Monster&m,float fElapsedTime,int strategyNumber){
float bulletSpd=ConfigFloat("BulletSpd")/100*24;
m.F(A::SHOOT_TIMER)=std::max(0.f,m.F(A::SHOOT_TIMER)-fElapsedTime);
m.F(A::SHOOT_RING_TIMER)=std::max(0.f,m.F(A::SHOOT_RING_TIMER)-fElapsedTime);
m.F(A::SHOOT_RING_DELAY)=std::max(0.f,m.F(A::SHOOT_RING_DELAY)-fElapsedTime);
m.F(A::JUMP_LANDING_TIMER)=std::max(0.f,m.F(A::JUMP_LANDING_TIMER)-fElapsedTime);
auto ShootBulletRing=[&](float angleOffset){
const auto ShootBulletRing=[&](float angleOffset){
int bulletCount=ConfigInt("Phase1.RingBulletCount");
for(int i=0;i<bulletCount;i++){
float angle=((2*PI)/bulletCount)*i+angleOffset;
BULLET_LIST.emplace_back(std::make_unique<Bullet>(m.GetPos(),vf2d{cos(angle),sin(angle)}*bulletSpd,6,ConfigInt("ProjectileDamage"),m.OnUpperLevel(),false,YELLOW,vf2d{6,6}));
}
};
auto StartJump=[&](float jumpDuration,vf2d targetPos,float recoveryTime){
const auto Landed=[&ShootBulletRing,&m](int currentPhase){
if(currentPhase==1){
ShootBulletRing(m.F(A::SHOOT_RING_OFFSET));
}
};
const auto TransitionPhase=[&](int newPhase){
const int MAX_ATTEMPTS=100; //Maximum number of tries to find a valid location.
Player*player=game->GetPlayer();
const auto PositionInRangeOfPlayer=[&player](vf2d&pos,float radius){
return geom2d::line<float>(player->GetPos(),pos).length()<=player->GetSizeMult()*12*2+radius;
};
const auto SpawnMonsterFromConfig=[&](int phase){
std::string spawnMonster=ConfigStringArr("Phase"+std::to_string(phase)+".MonsterSpawnOnChange",0);
int spawnCount=ConfigIntArr("Phase"+std::to_string(phase)+".MonsterSpawnOnChange",1);
for(int i=0;i<spawnCount;i++){
float randomAngle=util::random(2*PI);
vf2d spawnPos=m.pos+vf2d{cos(randomAngle),sin(randomAngle)}*m.GetSizeMult()*12;
for(int attempts=0;attempts<MAX_ATTEMPTS&&PositionInRangeOfPlayer(spawnPos,MONSTER_NAME_DATA[spawnMonster]->GetSizeMult()*12);attempts++){
randomAngle=util::random(2*PI);
spawnPos=m.pos+vf2d{cos(randomAngle),sin(randomAngle)}*m.GetSizeMult()*12;
}
game->SpawnMonster(spawnPos,MONSTER_NAME_DATA[spawnMonster]);
}
};
switch(newPhase){
case 2:{
SpawnMonsterFromConfig(2);
}break;
case 3:{
SpawnMonsterFromConfig(3);
}break;
case 4:{
SpawnMonsterFromConfig(4);
}break;
case 5:{
}break;
}
};
const auto StartJump=[&](float jumpDuration,vf2d targetPos,float recoveryTime){
m.V(A::JUMP_ORIGINAL_POS)=m.GetPos();
m.F(A::JUMP_ORIGINAL_LANDING_TIMER)=m.F(A::JUMP_LANDING_TIMER)=jumpDuration;
m.V(A::JUMP_TARGET_POS)=targetPos;
@ -44,7 +92,6 @@ void Monster::STRATEGY::SLIMEKING(Monster&m,float fElapsedTime,int strategyNumbe
if(m.state==State::JUMP){
float jumpLandingTimerRatio=m.F(A::JUMP_LANDING_TIMER)/m.F(A::JUMP_ORIGINAL_LANDING_TIMER);
vf2d moveVel;
if(m.GetPos().x>game->GetPlayer()->GetPos().x){
m.SetX(std::max(game->GetPlayer()->GetPos().x,m.GetPos().x-ConfigInt("JumpMoveSpd")*game->GetElapsedTime()));
} else
@ -65,29 +112,52 @@ void Monster::STRATEGY::SLIMEKING(Monster&m,float fElapsedTime,int strategyNumbe
if(m.F(A::JUMP_LANDING_TIMER)==0){
m.state=State::RECOVERY;
game->SetupWorldShake(0.6);
geom2d::line<float>lineToPlayer(m.GetPos(),game->GetPlayer()->GetPos());
float dist=lineToPlayer.length();
for(int i=0;i<200;i++){
float randomDir=util::random(2*PI);
game->AddEffect(std::make_unique<FallingDebris>(m.GetPos()+vf2d{cos(randomDir),sin(randomDir)}*m.GetSizeMult()*8,util::random(1),"circle.png",m.OnUpperLevel(),vf2d{1,1},0.5,vf2d{cos(randomDir)*util::random(5),sin(randomDir)*-util::random(15)-5}*30,BLACK),true);
}
if(dist<12*m.GetSizeMult()){
game->GetPlayer()->Hurt(ConfigInt("JumpAttackDamage"),m.OnUpperLevel(),m.GetZ());
if(dist<0.001){
float randomDir=util::random(2*PI);
lineToPlayer={m.GetPos(),m.GetPos()+vf2d{cos(randomDir),sin(randomDir)}*1};
}
game->GetPlayer()->Knockback(lineToPlayer.vector().norm()*ConfigInt("JumpKnockbackFactor"));
game->GetPlayer()->SetIframes(1);
}
Landed(m.phase);
m.SetStrategyDrawFunction([](Crawler*game){});
} else
if(m.F(A::JUMP_LANDING_TIMER)<=ConfigFloat("JumpWarningIndicatorTime")){
m.SetStrategyDrawFunction([&](Crawler*game){
Decal*dec=ANIMATION_DATA["RANGE_INDICATOR"].GetFrame(game->GetElapsedTime()).GetSourceImage()->Decal();
game->view.DrawRotatedDecal(m.GetPos(),dec,0,dec->sprite->Size()/2,vf2d{m.GetSizeMult(),m.GetSizeMult()}/2,RED);
Decal*dec=ANIMATION_DATA["range_indicator.png"].GetFrame(game->GetElapsedTime()).GetSourceImage()->Decal();
game->view.DrawRotatedDecal(m.GetPos(),dec,0,dec->sprite->Size()/2,vf2d{m.GetSizeMult(),m.GetSizeMult()},RED);
});
}
return;
}
if(m.state==State::CASTING){
m.UpdateAnimation("monsters/Slime King - Cast.png");
return;
}
switch(m.phase){
case 0:{
m.size=ConfigInt("Phase1.Size")/100;
m.diesNormally=false;
m.F(A::IFRAME_TIME_UPON_HIT)=0;
m.iframe_timer=ConfigFloat("Phase5.IframeTimePerHit");
m.phase=1;
m.phase=ConfigInt("StartPhase");
}break;
case 1:{
if(m.hp<=m.maxhp*ConfigFloat("Phase2.Change")/100){
m.phase=2;
m.SetSize(ConfigFloat("Phase2.Size")/100,false);
TransitionPhase(m.phase);
return;
}
if(m.F(A::SHOOT_RING_TIMER)==0){
if(m.I(A::PATTERN_REPEAT_COUNT)>=ConfigInt("Phase1.JumpAfter")){
@ -119,18 +189,38 @@ void Monster::STRATEGY::SLIMEKING(Monster&m,float fElapsedTime,int strategyNumbe
if(m.hp<=m.maxhp*ConfigFloat("Phase3.Change")/100){
m.phase=3;
m.SetSize(ConfigFloat("Phase3.Size")/100,false);
TransitionPhase(m.phase);
return;
}
if(m.F(A::SHOOT_TIMER)==0){
m.F(A::SHOOT_TIMER)=ConfigInt("Phase2.ShootRate");
m.I(A::PATTERN_REPEAT_COUNT)++;
int bulletCount=ConfigInt("Phase2.ShootProjectileCount");
for(int i=0;i<bulletCount;i++){
float initialAngle=util::angleTo(m.GetPos(),game->GetPlayer()->GetPos());
float angle=(i-(bulletCount/2))*util::degToRad(ConfigFloat("Phase2.ShootAngleSpread"))+initialAngle;
BULLET_LIST.emplace_back(std::make_unique<Bullet>(m.GetPos(),vf2d{cos(angle),sin(angle)}*bulletSpd,6,ConfigInt("ProjectileDamage"),m.OnUpperLevel(),false,YELLOW,vf2d{6,6}));
}
}
if(m.I(A::PATTERN_REPEAT_COUNT)>ConfigInt("Phase2.ShootCount")){
m.I(A::PATTERN_REPEAT_COUNT)=0;
m.SetState(State::CASTING);
}
}break;
case 3:{
if(m.hp<=m.maxhp*ConfigFloat("Phase4.Change")/100){
m.phase=4;
m.SetSize(ConfigFloat("Phase4.Size")/100,false);
TransitionPhase(m.phase);
return;
}
}break;
case 4:{
if(m.hp<=0){
m.phase=5;
m.F(A::IFRAME_TIME_UPON_HIT)=1;
TransitionPhase(m.phase);
return;
}
}break;
}

@ -1,7 +1,7 @@
#pragma once
#include "olcPixelGameEngine.h"
#include "olcUTIL_Geometry2D.h"
#include <strstream>
#include <sstream>
using namespace olc;
@ -223,10 +223,6 @@ typedef std::map<std::string,std::vector<geom2d::rect<int>>> ZoneData;
LayerTag l = {newTag};
parsedMapInfo.LayerData.push_back(l);
}else
if (newTag.tag=="object"&&newTag.data["type"]=="UpperSpawnGroup") {
parsedMapInfo.SpawnerData[newTag.GetInteger("id")]={newTag};
parsedMapInfo.SpawnerData[newTag.GetInteger("id")].upperLevel=true;
} else
if (newTag.tag=="object"&&newTag.data["type"]=="SpawnGroup") {
parsedMapInfo.SpawnerData[newTag.GetInteger("id")]={newTag};
} else
@ -318,6 +314,26 @@ typedef std::map<std::string,std::vector<geom2d::rect<int>>> ZoneData;
for(XMLTag&monster:accumulatedMonsterTags){
parsedMapInfo.SpawnerData[monster.GetInteger("spawnerLink")].monsters.push_back(monster);
}
for(auto&spawnerData:parsedMapInfo.SpawnerData){
SpawnerTag&spawner=spawnerData.second;
for(auto&zoneData:parsedMapInfo.ZoneData){
if(zoneData.first=="UpperZone"){
std::vector<geom2d::rect<int>>&zones=zoneData.second;
for(geom2d::rect<int>&zone:zones){
if(geom2d::overlaps(zone,geom2d::rect<int>{{spawner.ObjectData.GetInteger("x"),spawner.ObjectData.GetInteger("y")},{spawner.ObjectData.GetInteger("width"),spawner.ObjectData.GetInteger("height")}})){
spawner.upperLevel=true;
goto continueSpawnerLoop;
}
}
}
}
continueSpawnerLoop:
continue;
}
std::sort(parsedMapInfo.TilesetData.begin(),parsedMapInfo.TilesetData.end(),[](XMLTag&t1,XMLTag&t2){return t1.GetInteger("firstgid")<t2.GetInteger("firstgid");});
std::cout<<"Parsed Map Data:\n"<<parsedMapInfo<<"\n";
}
#endif

@ -1,9 +1,10 @@
#pragma once
#include "olcPixelGameEngine.h"
#include <strstream>
#include <sstream>
#include "TMXParser.h"
#include "Map.h"
#include "olcUTIL_Geometry2D.h"
#include "olcUTIL_DataFile.h"
using namespace olc;
@ -13,6 +14,8 @@ struct Tileset{
std::map<int,XMLTag> UpperForegroundTileData;
std::map<int,TileCollisionData> CollisionData;
std::map<int,XMLTag> StaircaseData;
std::map<int,std::vector<int>> AnimationData;
std::set<int> ReflectiveData;
friend std::ostream& operator << (std::ostream& os, Tileset& rhs);
};
@ -89,19 +92,35 @@ class TSXParser{
parsedTilesetInfo.ImageData=newTag;
} else
if (newTag.tag=="tile"&&newTag.data["type"]=="ForegroundTile"){
previousTag=newTag.tag;
previousTagID=newTag.GetInteger("id");
parsedTilesetInfo.ForegroundTileData[newTag.GetInteger("id")]=newTag;
} else
if (newTag.tag=="tile"&&newTag.data["type"]=="UpperForegroundTile"){
previousTag=newTag.tag;
previousTagID=newTag.GetInteger("id");
parsedTilesetInfo.UpperForegroundTileData[newTag.GetInteger("id")]=newTag;
} else
if (newTag.tag=="tile"&&newTag.data["type"]=="Staircase"){
previousTag=newTag.tag;
staircaseTag=newTag.tag;
previousTagID=newTag.GetInteger("id");
} else
if (newTag.tag=="tile"&&newTag.data["type"]=="Reflective"){
previousTag=newTag.tag;
previousTagID=newTag.GetInteger("id");
parsedTilesetInfo.ReflectiveData.insert(newTag.GetInteger("id"));
} else
if (newTag.tag=="tile"){
previousTag=newTag.tag;
previousTagID=newTag.GetInteger("id");
} else
if (newTag.tag=="frame"){
//The way animation data is stored is every "animation_tile_precision" ms indicating which frame we should be on.
for(int i=0;i<newTag.GetInteger("duration")/"animation_tile_precision"_I;i++){
parsedTilesetInfo.AnimationData[previousTagID].push_back(newTag.GetInteger("tileid"));
}
} else
if (newTag.tag=="property"&&staircaseTag=="tile"){
parsedTilesetInfo.StaircaseData[previousTagID]=newTag;
staircaseTag="";
@ -109,6 +128,10 @@ class TSXParser{
if (newTag.tag=="object"&&previousTag=="tile"){
TileCollisionData data;
data.collision=geom2d::rect<int>{{newTag.GetInteger("x"),newTag.GetInteger("y")},{newTag.GetInteger("width"),newTag.GetInteger("height")}};
if(parsedTilesetInfo.CollisionData.count(previousTagID)){
std::cout<<"WARNING! There was already collision data defined for tile "<<previousTagID<<"!"<<std::endl;
throw;
}
parsedTilesetInfo.CollisionData[previousTagID]=data;
}
std::cout<<"\n"<<"=============\n";

@ -4,11 +4,19 @@
#include "Crawler.h"
#include "utils.h"
typedef Attribute A;
INCLUDE_game
INCLUDE_BULLET_LIST
void Monster::STRATEGY::TURRET(Monster&m,float fElapsedTime,int strategyNumber){
m.attackCooldownTimer=std::max(0.f,m.attackCooldownTimer-fElapsedTime);
if(m.F(A::SHOOT_ANIMATION_TIME)>0){
m.F(A::SHOOT_ANIMATION_TIME)=std::max(0.f,m.F(A::SHOOT_ANIMATION_TIME)-fElapsedTime);
if(m.F(A::SHOOT_ANIMATION_TIME)==0){
m.PerformIdleAnimation();
}
}
if(m.queueShotTimer>0){
m.queueShotTimer-=fElapsedTime;
@ -23,6 +31,7 @@ void Monster::STRATEGY::TURRET(Monster&m,float fElapsedTime,int strategyNumber){
if(m.attackCooldownTimer==0){
m.attackCooldownTimer=ConfigFloat("ShootingSpeed");
m.queueShotTimer=std::min(m.attackCooldownTimer-0.001,0.3);
m.F(A::SHOOT_ANIMATION_TIME)=ConfigIntArr("ShootAnimation",0)*ConfigFloatArr("ShootAnimation",1);
m.PerformShootAnimation();
}
}

@ -2,7 +2,7 @@
#define VERSION_MAJOR 0
#define VERSION_MINOR 2
#define VERSION_PATCH 0
#define VERSION_BUILD 1147
#define VERSION_BUILD 1372
#define stringify(a) stringify_(a)
#define stringify_(a) #a

@ -80,7 +80,7 @@ void Warrior::InitializeClassAbilities(){
#pragma region Warrior Ability 1 (Battlecry)
Warrior::ability1.action=
[](Player*p,vf2d pos={}){
game->AddEffect(std::make_unique<Effect>(p->GetPos(),"Warrior.Ability 1.EffectLifetime"_F,"BATTLECRY_EFFECT",p->upperLevel,"Warrior.Ability 1.Range"_F/350,"Warrior.Ability 1.EffectFadetime"_F));
game->AddEffect(std::make_unique<Effect>(p->GetPos(),"Warrior.Ability 1.EffectLifetime"_F,"battlecry_effect.png",p->upperLevel,"Warrior.Ability 1.Range"_F/350,"Warrior.Ability 1.EffectFadetime"_F));
p->AddBuff(BuffType::ATTACK_UP,"Warrior.Ability 1.AttackUpDuration"_F,"Warrior.Ability 1.AttackIncrease"_F);
p->AddBuff(BuffType::DAMAGE_REDUCTION,"Warrior.Ability 1.DamageReductionDuration"_F,"Warrior.Ability 1.DamageReduction"_F);
for(Monster&m:MONSTER_LIST){
@ -127,7 +127,7 @@ void Warrior::InitializeClassAbilities(){
p->UpdateAnimation("WARRIOR_SWINGSONICSWORD_S",WARRIOR);
}break;
}
BULLET_LIST.push_back(std::make_unique<Bullet>(p->GetPos(),bulletVel,"Warrior.Ability 3.Radius"_F,p->GetAttack()*"Warrior.Ability 3.DamageMult"_F,"SONICSLASH",p->upperLevel,true,"Warrior.Ability 3.Lifetime"_F,true,true,WHITE,vf2d{"Warrior.Ability 3.Radius"_F/30,"Warrior.Ability 3.Radius"_F/30}));
BULLET_LIST.push_back(std::make_unique<Bullet>(p->GetPos(),bulletVel,"Warrior.Ability 3.Radius"_F,p->GetAttack()*"Warrior.Ability 3.DamageMult"_F,"sonicslash.png",p->upperLevel,true,"Warrior.Ability 3.Lifetime"_F,true,true,WHITE,vf2d{"Warrior.Ability 3.Radius"_F/30,"Warrior.Ability 3.Radius"_F/30}));
game->SetupWorldShake("Warrior.Ability 3.ShakeTime"_F);
return true;
};

@ -74,14 +74,13 @@ void Wizard::InitializeClassAbilities(){
#pragma region Wizard Right-click Ability (Teleport)
Wizard::rightClickAbility.action=
[](Player*p,vf2d pos={}){
if(p->GetState()==State::CASTING)return false;
float pointMouseDirection=atan2(game->GetWorldMousePos().y-p->GetPos().y,game->GetWorldMousePos().x-p->GetPos().x);
vf2d pointTowardsMouse={cos(pointMouseDirection),sin(pointMouseDirection)};
float dist=std::clamp(geom2d::line<float>{p->GetPos(),game->GetWorldMousePos()}.length(),0.f,"Wizard.Right Click Ability.TeleportRange"_F/100*24);
if(dist<"Wizard.Right Click Ability.TilesMin"_I*12)return false;
vf2d teleportPoint=p->GetPos()+pointTowardsMouse*dist;
while(dist>0&&game->HasTileCollision(game->GetCurrentLevel(),teleportPoint)&&p->CanPathfindTo(p->GetPos(),teleportPoint,"Wizard.Right Click Ability.TilesMax"_I)){
dist-=24;
dist-=4;
teleportPoint=p->GetPos()+pointTowardsMouse*dist;
}
if(dist>0&&p->CanPathfindTo(p->GetPos(),teleportPoint,"Wizard.Right Click Ability.TilesMax"_I)){
@ -91,7 +90,7 @@ void Wizard::InitializeClassAbilities(){
p->teleportStartPosition=p->GetPos();
p->iframe_time="Wizard.Right Click Ability.IframeTime"_F;
for(int i=0;i<"Wizard.Right Click Ability.ParticleCount"_I;i++){
game->AddEffect(std::make_unique<Effect>(p->GetPos()+vf2d{(util::random("Wizard.Right Click Ability.ParticleRange"_F/100*2)-"Wizard.Right Click Ability.ParticleRange"_F/100)*12,(util::random("Wizard.Right Click Ability.ParticleRange"_F/100*2)-"Wizard.Right Click Ability.ParticleRange"_F/100)*12},util::random("Wizard.Right Click Ability.ParticleLifetimeMax"_F)+"Wizard.Right Click Ability.ParticleLifetimeMin"_F,"DOT_PARTICLE",p->upperLevel,"Wizard.Right Click Ability.ParticleSize"_F,"Wizard.Right Click Ability.ParticleFadetime"_F,vf2d{util::random("Wizard.Right Click Ability.ParticleSpeedMax"_F*2)+"Wizard.Right Click Ability.ParticleSpeedMin"_F,util::random("Wizard.Right Click Ability.ParticleSpeedMax"_F*2)+"Wizard.Right Click Ability.ParticleSpeedMin"_F},"Wizard.Right Click Ability.ParticleColor"_Pixel));
game->AddEffect(std::make_unique<Effect>(p->GetPos()+vf2d{(util::random("Wizard.Right Click Ability.ParticleRange"_F/100*2)-"Wizard.Right Click Ability.ParticleRange"_F/100)*12,(util::random("Wizard.Right Click Ability.ParticleRange"_F/100*2)-"Wizard.Right Click Ability.ParticleRange"_F/100)*12},util::random("Wizard.Right Click Ability.ParticleLifetimeMax"_F)+"Wizard.Right Click Ability.ParticleLifetimeMin"_F,"circle.png",p->upperLevel,"Wizard.Right Click Ability.ParticleSize"_F,"Wizard.Right Click Ability.ParticleFadetime"_F,vf2d{util::random("Wizard.Right Click Ability.ParticleSpeedMax"_F*2)+"Wizard.Right Click Ability.ParticleSpeedMin"_F,util::random("Wizard.Right Click Ability.ParticleSpeedMax"_F*2)+"Wizard.Right Click Ability.ParticleSpeedMin"_F},"Wizard.Right Click Ability.ParticleColor"_Pixel));
}
return true;
} else {
@ -120,7 +119,7 @@ void Wizard::InitializeClassAbilities(){
Wizard::ability3.action=
[](Player*p,vf2d pos={}){
p->CastSpell(Wizard::ability3);
game->AddEffect(std::make_unique<Meteor>(pos,3,"METEOR",p->OnUpperLevel(),vf2d{"Wizard.Ability 3.MeteorRadius"_F/100/4,"Wizard.Ability 3.MeteorRadius"_F/100/4},"Wizard.Ability 3.MeteorFadeoutTime"_F));
game->AddEffect(std::make_unique<Meteor>(pos,3,"meteor.png",p->OnUpperLevel(),vf2d{"Wizard.Ability 3.MeteorRadius"_F/100/4,"Wizard.Ability 3.MeteorRadius"_F/100/4},"Wizard.Ability 3.MeteorFadeoutTime"_F));
return true;
};
#pragma endregion

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 MiB

File diff suppressed because it is too large Load Diff

@ -43,6 +43,8 @@ MonsterStrategy
WaitTime = 3
# How far the monster will travel before reassessing for a new path.
MaxDistance = 999999
# 1 of X chance to stop after bumping into something.
BumpStopChance = 5
}
1
{
@ -63,7 +65,7 @@ MonsterStrategy
# How far away the monster starts shooting from
Range = 800
# How often the enemy shoots.
ShootingSpeed = 0.6
ShootingSpeed = 2
BulletSpeed = 450
BulletSize = 30
BulletColor = 0, 255, 0, 255
@ -72,13 +74,17 @@ MonsterStrategy
{
# The Slime King Boss script.
Name = Slime King
# Which phase to start on. Should be 1 most of the time.
StartPhase = 1
# How much time a jump will be pre-telegraphed.
JumpWarningIndicatorTime = 1.0
# Distance to jump up into the sky. A higher value causes it to launch up and down seemingly faster.
JumpHeight = 2400
ProjectileDamage = 10
JumpAttackDamage = 20
JumpMoveSpd = 95
JumpMoveSpd = 75
# How far the player gets knocked back if hit.
JumpKnockbackFactor = 250
BulletSpd = 250

@ -12,6 +12,7 @@ Monsters
Size = 80
Strategy = Run Towards
BumpStopChance = 2
#Size of each animation frame
SheetFrameSize = 24,24
@ -138,6 +139,7 @@ Monsters
Size = 800
Strategy = Slime King
StartPhase = 2
#Size of each animation frame
SheetFrameSize = 24,24
@ -149,6 +151,6 @@ Monsters
DeathAnimation = 10, 0.1, OneShot
#Additional custom animations go down below. Start with ANIMATION[0]
#ANIMATION[0] = MY_NEW_ANIMATION
ANIMATION[0] = monsters/Slime King - Cast.png
}
}

@ -7,14 +7,19 @@ Ranger
DamageMult = 1
Radius = 100
Cooldown = 0.6
# Whether or not this ability cancels casts.
CancelCast = 0
ArrowSpd = 250
}
Right Click Ability
{
Name = Retreat
Cooldown = 7
Mana Cost = 0
# Whether or not this ability cancels casts.
CancelCast = 0
#RGB Values. Color 1 is the left side of the bar, Color 2 is the right side.
Cooldown Bar Color 1 = 0, 0, 64, 255
@ -34,6 +39,8 @@ Ranger
Name = Rapid Fire
Cooldown = 12
Mana Cost = 35
# Whether or not this ability cancels casts.
CancelCast = 0
#RGB Values. Color 1 is the left side of the bar, Color 2 is the right side.
Cooldown Bar Color 1 = 64, 0, 0, 255
@ -62,6 +69,8 @@ Ranger
Name = Charged Shot
Cooldown = 15
Mana Cost = 40
# Whether or not this ability cancels casts.
CancelCast = 0
#RGB Values. Color 1 is the left side of the bar, Color 2 is the right side.
Cooldown Bar Color 1 = 64, 0, 0, 255
@ -88,6 +97,8 @@ Ranger
Name = Multishot
Cooldown = 25
Mana Cost = 50
# Whether or not this ability cancels casts.
CancelCast = 0
#RGB Values. Color 1 is the left side of the bar, Color 2 is the right side.
Cooldown Bar Color 1 = 64, 0, 0, 255

@ -7,6 +7,8 @@ Thief
Name = ???
Cooldown = 8
Mana Cost = 5
# Whether or not this ability cancels casts.
CancelCast = 0
#RGB Values. Color 1 is the left side of the bar, Color 2 is the right side.
Cooldown Bar Color 1 = 0, 0, 64, 255
@ -21,6 +23,8 @@ Thief
Name = ???
Cooldown = 6
Mana Cost = 30
# Whether or not this ability cancels casts.
CancelCast = 0
#RGB Values. Color 1 is the left side of the bar, Color 2 is the right side.
Cooldown Bar Color 1 = 64, 0, 0, 255
@ -35,6 +39,8 @@ Thief
Name = ???
Cooldown = 6
Mana Cost = 25
# Whether or not this ability cancels casts.
CancelCast = 0
#RGB Values. Color 1 is the left side of the bar, Color 2 is the right side.
Cooldown Bar Color 1 = 64, 0, 0, 255
@ -49,6 +55,8 @@ Thief
Name = ???
Cooldown = 40
Mana Cost = 75
# Whether or not this ability cancels casts.
CancelCast = 0
#RGB Values. Color 1 is the left side of the bar, Color 2 is the right side.
Cooldown Bar Color 1 = 64, 0, 0, 255

@ -7,6 +7,8 @@ Trapper
Name = ???
Cooldown = 8
Mana Cost = 5
# Whether or not this ability cancels casts.
CancelCast = 0
#RGB Values. Color 1 is the left side of the bar, Color 2 is the right side.
Cooldown Bar Color 1 = 0, 0, 64, 255
@ -21,6 +23,8 @@ Trapper
Name = ???
Cooldown = 6
Mana Cost = 30
# Whether or not this ability cancels casts.
CancelCast = 0
#RGB Values. Color 1 is the left side of the bar, Color 2 is the right side.
Cooldown Bar Color 1 = 64, 0, 0, 255
@ -35,6 +39,8 @@ Trapper
Name = ???
Cooldown = 6
Mana Cost = 25
# Whether or not this ability cancels casts.
CancelCast = 0
#RGB Values. Color 1 is the left side of the bar, Color 2 is the right side.
Cooldown Bar Color 1 = 64, 0, 0, 255
@ -49,6 +55,8 @@ Trapper
Name = ???
Cooldown = 40
Mana Cost = 75
# Whether or not this ability cancels casts.
CancelCast = 0
#RGB Values. Color 1 is the left side of the bar, Color 2 is the right side.
Cooldown Bar Color 1 = 64, 0, 0, 255

@ -7,6 +7,8 @@ Warrior
DamageMult = 1
Range = 150
Cooldown = 0.35
# Whether or not this ability cancels casts.
CancelCast = 0
SwordSwingTime = 0.2
}
@ -15,6 +17,8 @@ Warrior
Name = Block
Cooldown = 15
Mana Cost = 0
# Whether or not this ability cancels casts.
CancelCast = 0
#RGB Values. Color 1 is the left side of the bar, Color 2 is the right side.
Cooldown Bar Color 1 = 0, 0, 64, 255
@ -37,6 +41,8 @@ Warrior
Name = Battlecry
Cooldown = 12
Mana Cost = 40
# Whether or not this ability cancels casts.
CancelCast = 0
#RGB Values. Color 1 is the left side of the bar, Color 2 is the right side.
Cooldown Bar Color 1 = 64, 0, 0, 255
@ -79,6 +85,8 @@ Warrior
Name = Ground Slam
Cooldown = 15
Mana Cost = 50
# Whether or not this ability cancels casts.
CancelCast = 0
#RGB Values. Color 1 is the left side of the bar, Color 2 is the right side.
Cooldown Bar Color 1 = 64, 0, 0, 255
@ -107,6 +115,8 @@ Warrior
Name = Sonic Slash
Cooldown = 40
Mana Cost = 60
# Whether or not this ability cancels casts.
CancelCast = 0
#RGB Values. Color 1 is the left side of the bar, Color 2 is the right side.
Cooldown Bar Color 1 = 64, 0, 0, 255

@ -7,6 +7,8 @@ Witch
Name = ???
Cooldown = 8
Mana Cost = 5
# Whether or not this ability cancels casts.
CancelCast = 0
#RGB Values. Color 1 is the left side of the bar, Color 2 is the right side.
Cooldown Bar Color 1 = 0, 0, 64, 255
@ -21,6 +23,8 @@ Witch
Name = ???
Cooldown = 6
Mana Cost = 30
# Whether or not this ability cancels casts.
CancelCast = 0
#RGB Values. Color 1 is the left side of the bar, Color 2 is the right side.
Cooldown Bar Color 1 = 64, 0, 0, 255
@ -35,6 +39,8 @@ Witch
Name = ???
Cooldown = 6
Mana Cost = 25
# Whether or not this ability cancels casts.
CancelCast = 0
#RGB Values. Color 1 is the left side of the bar, Color 2 is the right side.
Cooldown Bar Color 1 = 64, 0, 0, 255
@ -49,6 +55,8 @@ Witch
Name = ???
Cooldown = 40
Mana Cost = 75
# Whether or not this ability cancels casts.
CancelCast = 0
#RGB Values. Color 1 is the left side of the bar, Color 2 is the right side.
Cooldown Bar Color 1 = 64, 0, 0, 255

@ -8,6 +8,8 @@ Wizard
Radius = 100
Speed = 200
Cooldown = 0.85
# Whether or not this ability cancels casts.
CancelCast = 0
# When bullet makes contact, how fast the bullet will fade out.
BulletHitFadeoutTime = 0.2
@ -28,6 +30,8 @@ Wizard
Name = Teleport
Cooldown = 8
Mana Cost = 5
# Whether or not this ability cancels casts.
CancelCast = 1
#RGB Values. Color 1 is the left side of the bar, Color 2 is the right side.
Cooldown Bar Color 1 = 0, 0, 64, 255
@ -64,6 +68,8 @@ Wizard
Name = Firebolt
Cooldown = 6
Mana Cost = 30
# Whether or not this ability cancels casts.
CancelCast = 0
#RGB Values. Color 1 is the left side of the bar, Color 2 is the right side.
Cooldown Bar Color 1 = 64, 0, 0, 255
@ -126,6 +132,8 @@ Wizard
Name = Lightning Bolt
Cooldown = 6
Mana Cost = 25
# Whether or not this ability cancels casts.
CancelCast = 0
#RGB Values. Color 1 is the left side of the bar, Color 2 is the right side.
Cooldown Bar Color 1 = 64, 0, 0, 255
@ -178,6 +186,8 @@ Wizard
Name = Meteor
Cooldown = 40
Mana Cost = 75
# Whether or not this ability cancels casts.
CancelCast = 0
#RGB Values. Color 1 is the left side of the bar, Color 2 is the right side.
Cooldown Bar Color 1 = 64, 0, 0, 255

@ -34,4 +34,19 @@ debug_access_options = 0
debug_player_info = 0
# Shows collision boxes of tiles.
debug_collision_boxes = 0
debug_collision_boxes = 0
# Shows pathfinding debugging
debug_pathfinding = 0
# ms precision of animation tile caching.
animation_tile_precision = 50
# frequency of water reflection moving update.
water_reflection_update_time = 0.5
# amount of time step of water reflection moving update.
water_reflection_time_step = 0.6
# the amount of scaling done to the water reflection.
water_reflection_scale_factor = 0.05

@ -2,32 +2,38 @@ GFX_Prefix = assets/
Images
{
GFX_Warrior_Sheet = nico-warrior.png
GFX_Circle = circle.png
GFX_Effect_GroundSlam_Back = ground-slam-attack-back.png
GFX_Effect_GroundSlam_Front = ground-slam-attack-front.png
GFX_Heart = heart.png
GFX_BLOCK_BUBBLE = block.png
GFX_Ranger_Sheet = nico-ranger.png
GFX_Wizard_Sheet = nico-wizard.png
GFX_Arrow = arrow.png
GFX_Battlecry_Effect = battlecry_effect.png
GFX_Mana = mana.png
GFX_SonicSlash = sonicslash.png
GFX_BLOCK_BUBBLE = block.png
GFX_BulletCircle = circle.png
GFX_BulletCircleOutline = circle_outline.png
GFX_ChainLightning = chain_lightning.png
GFX_ChargedArrow = charged_shot_arrow.png
GFX_Circle = circle.png
GFX_Effect_GroundSlam_Back = ground-slam-attack-back.png
GFX_Effect_GroundSlam_Front = ground-slam-attack-front.png
GFX_EnergyBolt = energy_bolt.png
GFX_EnergyParticle = energy_particle.png
GFX_Splash_Effect = splash_effect.png
GFX_FireRing0 = fire_ring0.png
GFX_FireRing1 = fire_ring1.png
GFX_FireRing2 = fire_ring2.png
GFX_FireRing3 = fire_ring3.png
GFX_FireRing4 = fire_ring4.png
GFX_Heart = heart.png
GFX_Laser = laser.png
GFX_LightningBolt = lightning_bolt.png
GFX_LightningBoltParticle1 = lightning_bolt_part1.png
GFX_LightningBoltParticle2 = lightning_bolt_part2.png
GFX_LightningBoltParticle3 = lightning_bolt_part3.png
GFX_LightningBoltParticle4 = lightning_bolt_part4.png
GFX_ChainLightning = chain_lightning.png
GFX_LightningSplash = lightning_splash_effect.png
GFX_Mana = mana.png
GFX_Meteor = meteor.png
GFX_Arrow = arrow.png
GFX_Laser = laser.png
GFX_ChargedArrow = charged_shot_arrow.png
GFX_RangeIndicator = range_indicator.png
GFX_Ranger_Sheet = nico-ranger.png
GFX_SonicSlash = sonicslash.png
GFX_Splash_Effect = splash_effect.png
GFX_Warrior_Sheet = nico-warrior.png
GFX_Wizard_Sheet = nico-wizard.png
GFX_SlimeKing_Cast = monsters/Slime King - Cast.png
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 627 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 706 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 683 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 681 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 672 B

@ -0,0 +1,124 @@
<?xml version="1.0" encoding="UTF-8"?>
<tileset version="1.10" tiledversion="1.10.1" name="24x24_Waterfall" tilewidth="24" tileheight="24" tilecount="80" columns="8">
<image source="24x24_Waterfall.png" width="192" height="240"/>
<tile id="0">
<animation>
<frame tileid="0" duration="100"/>
<frame tileid="1" duration="100"/>
<frame tileid="2" duration="100"/>
<frame tileid="3" duration="100"/>
<frame tileid="4" duration="100"/>
<frame tileid="5" duration="100"/>
<frame tileid="6" duration="100"/>
<frame tileid="7" duration="100"/>
</animation>
</tile>
<tile id="8">
<animation>
<frame tileid="8" duration="100"/>
<frame tileid="9" duration="100"/>
<frame tileid="10" duration="100"/>
<frame tileid="11" duration="100"/>
<frame tileid="12" duration="100"/>
<frame tileid="13" duration="100"/>
<frame tileid="14" duration="100"/>
<frame tileid="15" duration="100"/>
</animation>
</tile>
<tile id="16">
<animation>
<frame tileid="16" duration="100"/>
<frame tileid="17" duration="100"/>
<frame tileid="18" duration="100"/>
<frame tileid="19" duration="100"/>
<frame tileid="20" duration="100"/>
<frame tileid="21" duration="100"/>
<frame tileid="22" duration="100"/>
<frame tileid="23" duration="100"/>
</animation>
</tile>
<tile id="24">
<animation>
<frame tileid="24" duration="100"/>
<frame tileid="25" duration="100"/>
<frame tileid="26" duration="100"/>
<frame tileid="27" duration="100"/>
<frame tileid="28" duration="100"/>
<frame tileid="29" duration="100"/>
<frame tileid="30" duration="100"/>
<frame tileid="31" duration="100"/>
</animation>
</tile>
<tile id="32">
<animation>
<frame tileid="32" duration="100"/>
<frame tileid="33" duration="100"/>
<frame tileid="34" duration="100"/>
<frame tileid="35" duration="100"/>
<frame tileid="36" duration="100"/>
<frame tileid="37" duration="100"/>
<frame tileid="38" duration="100"/>
<frame tileid="39" duration="100"/>
</animation>
</tile>
<tile id="40">
<animation>
<frame tileid="40" duration="100"/>
<frame tileid="41" duration="100"/>
<frame tileid="42" duration="100"/>
<frame tileid="43" duration="100"/>
<frame tileid="44" duration="100"/>
<frame tileid="45" duration="100"/>
<frame tileid="46" duration="100"/>
<frame tileid="47" duration="100"/>
</animation>
</tile>
<tile id="48">
<animation>
<frame tileid="48" duration="100"/>
<frame tileid="49" duration="100"/>
<frame tileid="50" duration="100"/>
<frame tileid="51" duration="100"/>
<frame tileid="52" duration="100"/>
<frame tileid="53" duration="100"/>
<frame tileid="54" duration="100"/>
<frame tileid="55" duration="100"/>
</animation>
</tile>
<tile id="56">
<animation>
<frame tileid="56" duration="100"/>
<frame tileid="57" duration="100"/>
<frame tileid="58" duration="100"/>
<frame tileid="59" duration="100"/>
<frame tileid="60" duration="100"/>
<frame tileid="61" duration="100"/>
<frame tileid="62" duration="100"/>
<frame tileid="63" duration="100"/>
</animation>
</tile>
<tile id="64">
<animation>
<frame tileid="64" duration="100"/>
<frame tileid="65" duration="100"/>
<frame tileid="66" duration="100"/>
<frame tileid="67" duration="100"/>
<frame tileid="68" duration="100"/>
<frame tileid="69" duration="100"/>
<frame tileid="70" duration="100"/>
<frame tileid="71" duration="100"/>
</animation>
</tile>
<tile id="72">
<animation>
<frame tileid="72" duration="100"/>
<frame tileid="73" duration="100"/>
<frame tileid="74" duration="100"/>
<frame tileid="75" duration="100"/>
<frame tileid="76" duration="100"/>
<frame tileid="77" duration="100"/>
<frame tileid="78" duration="100"/>
<frame tileid="79" duration="100"/>
</animation>
</tile>
</tileset>

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

@ -35,7 +35,7 @@ var Module = {
})(),
};
</script>
<script async type="text/javascript" src="pge.js"></script>
<script async type="text/javascript" src="_REPLACEME_"></script>
<script type="text/javascript">
Module.canvas.addEventListener("resize", (e) => {

@ -324,7 +324,7 @@ namespace olc
olc::vf2d TransformedView::WorldToScreen(const olc::vf2d& vWorldPos) const
{
olc::vf2d vFloat = ((vd2d(vWorldPos) - vd2d(m_vWorldOffset)) * vd2d(m_vWorldScale));
olc::vf2d vFloat = ((vf2d(vWorldPos) - vf2d(m_vWorldOffset)) * vf2d(m_vWorldScale));
//vFloat = { std::floor(vFloat.x + 0.5f), std::floor(vFloat.y + 0.5f) };
return vFloat;
}

@ -2891,8 +2891,8 @@ namespace olc
di.decal = decal;
di.tint = { tint, tint, tint, tint };
di.pos = { { vScreenSpacePos.x, vScreenSpacePos.y }, { vScreenSpacePos.x, vScreenSpaceDim.y }, { vScreenSpaceDim.x, vScreenSpaceDim.y }, { vScreenSpaceDim.x, vScreenSpacePos.y } };
olc::vf2d uvtl = (source_pos) * decal->vUVScale;
olc::vf2d uvbr = uvtl + ((source_size) * decal->vUVScale);
olc::vf2d uvtl = (source_pos + olc::vf2d(0.0001f, 0.0001f)) * decal->vUVScale;
olc::vf2d uvbr = uvtl + ((source_size - olc::vf2d(0.0001f, 0.0001f)) * decal->vUVScale);
di.uv = { { uvtl.x, uvtl.y }, { uvtl.x, uvbr.y }, { uvbr.x, uvbr.y }, { uvbr.x, uvtl.y } };
di.w = { 1,1,1,1 };
di.mode = nDecalMode;

@ -130,11 +130,26 @@ namespace olc::utils
return m_vContent;
}
inline std::unordered_map<std::string,size_t> GetKeys() const{
return m_mapObjects;
}
// Checks if a property exists - useful to avoid creating properties
// via reading them, though non-essential
inline bool HasProperty(const std::string& sName) const
inline bool HasProperty(const std::string& sName)
{
return m_mapObjects.count(sName) > 0;
size_t x = sName.find_first_of('.');
if (x != std::string::npos)
{
std::string sProperty = sName.substr(0, x);
if(HasProperty(sProperty)){
return GetProperty(sName.substr(0, x)).HasProperty(sName.substr(x + 1, sName.size()));
}else{
return false;
}
}else{
return m_mapObjects.count(sName) > 0;
}
}
// Access a datafile via a convenient name - "root.node.something.property"

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

@ -1,3 +1,4 @@
//#define OLC_PGE_HEADLESS
#define OLC_PGE_APPLICATION
#include "olcPixelGameEngine.h"
#define OLC_PGEX_TRANSFORMEDVIEW

@ -0,0 +1,75 @@
<!doctype html>
<html lang="en-us">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Emscripten-Generated Code</title>
<style>
html,body { width: 100%; height: 100%; }
body { font-family: arial; margin: 0; padding: 0; background: #000; }
.emscripten { padding-right: 0; margin-left: auto; margin-right: auto; display: block; }
div.emscripten_border { border: none; }
/* the canvas *must not* have any border or padding, or mouse coords will be wrong */
canvas.emscripten { border: 0px none; background-color: black; }
</style>
</head>
<body>
<canvas class="emscripten" id="canvas" oncontextmenu="event.preventDefault()" tabindex=-1></canvas>
<script type='text/javascript'>
var Module = {
preRun: [],
postRun: [],
canvas: (function() {
var canvas = document.getElementById('canvas');
// As a default initial behavior, pop up an alert when webgl context is lost. To make your
// application robust, you may want to override this behavior before shipping!
// See http://www.khronos.org/registry/webgl/specs/latest/1.0/#5.15.2
canvas.addEventListener("webglcontextlost", function(e) { alert('WebGL context lost. You will need to reload the page.'); e.preventDefault(); }, false);
return canvas;
})(),
};
</script>
<script async type="text/javascript" src="pge.js"></script>
<script type="text/javascript">
Module.canvas.addEventListener("resize", (e) => {
var viewWidth = e.detail.width;
var viewHeight = e.detail.width / Module._olc_WindowAspectRatio;
if(viewHeight > e.detail.height)
{
viewHeight = e.detail.height;
viewWidth = e.detail.height * Module._olc_WindowAspectRatio;
}
// update dom attributes
Module.canvas.setAttribute("width", viewWidth);
Module.canvas.setAttribute("height", viewHeight);
var top = (e.detail.height - viewHeight) / 2;
var left = (e.detail.width - viewWidth) / 2;
// update styles
Module.canvas.style.position = "fixed";
Module.canvas.style.top = top.toString() + "px";
Module.canvas.style.left = left.toString() + "px";
Module.canvas.style.width = "";
Module.canvas.style.height = "";
// trigger PGE update
Module._olc_PGE_UpdateWindowSize(viewWidth, viewHeight);
// ensure canvas has focus
Module.canvas.focus();
e.preventDefault();
});
</script>
</body>
</html>

@ -14,7 +14,24 @@ public:
}
return map[key];
}
size_t count(T key){
return map.count(key);
}
void SetInitialized(){
initialized=true;
}
size_t size(){
return map.size();
}
//Clears the entire map and unlocks the map so items can be added to it again.
void Reset(){
initialized=false;
map.clear();
}
auto begin()const{
return map.begin();
}
auto end()const{
return map.end();
}
};

@ -1,9 +1,10 @@
export AUTO_UPDATE=false
export AUTO_UPDATE=true
source utils/define.sh
define PROJECT_NAME "Crawler"
define CUSTOM_PARAMS "-std=c++20 -lX11 -lGL -lpthread -lpng -lstdc++fs -I/usr/include/lua5.3"
define CUSTOM_PARAMS "-std=c++20 -lX11 -lpthread -lpng -lstdc++fs -I/usr/include/lua5.3"
define EMSCRIPTEN_CUSTOM_PARAMS "-s MAXIMUM_MEMORY=4GB"
define LANGUAGE "C++"
source utils/main.sh

@ -8,6 +8,10 @@ vf2d util::pointTo(vf2d posFrom,vf2d posTo){
return geom2d::line(posFrom,posTo).vector().norm();
}
float util::angleTo(vf2d posFrom,vf2d posTo){
return geom2d::line<float>(posFrom,posTo).vector().polar().y;
}
float util::degToRad(float deg){
return deg*(PI/180);
}

@ -6,6 +6,8 @@ namespace util{
float random(float range);
//Returns a normalized vector pointing from posFrom towards posTo.
vf2d pointTo(vf2d posFrom,vf2d posTo);
//Returns the angle (in radians) pointing from posFrom towards posTo.
float angleTo(vf2d posFrom,vf2d posTo);
float degToRad(float deg);
float radToDeg(float rad);
float lerp(float n1,float n2,double t);

Binary file not shown.
Loading…
Cancel
Save