|
|
|
#include "olcPGEX_TransformedView.h"
|
|
|
|
#include "Crawler.h"
|
|
|
|
#include "olcUTIL_Camera2D.h"
|
|
|
|
#include "DamageNumber.h"
|
|
|
|
#include "Bullet.h"
|
|
|
|
#include "Ability.h"
|
|
|
|
#include "Class.h"
|
|
|
|
#include "Version.h"
|
|
|
|
#include "TMXParser.h"
|
|
|
|
#include "TSXParser.h"
|
|
|
|
#include "Map.h"
|
|
|
|
#include "DEFINES.h"
|
|
|
|
#include "utils.h"
|
|
|
|
|
|
|
|
INCLUDE_CLASS_DATA
|
|
|
|
|
|
|
|
//192x192
|
|
|
|
const vi2d WINDOW_SIZE={24*15,24*10};
|
|
|
|
std::map<AnimationState,Animate2D::FrameSequence>ANIMATION_DATA;
|
|
|
|
std::vector<Monster>MONSTER_LIST;
|
|
|
|
std::vector<MonsterSpawner>SPAWNER_LIST;
|
|
|
|
std::vector<DamageNumber>DAMAGENUMBER_LIST;
|
|
|
|
std::vector<std::unique_ptr<Bullet>>BULLET_LIST;
|
|
|
|
std::vector<std::unique_ptr<Bullet>>PLAYER_BULLET_LIST;
|
|
|
|
Crawler*game;
|
|
|
|
|
|
|
|
Crawler::Crawler()
|
|
|
|
{
|
|
|
|
sAppName = "Crawler Concept";
|
|
|
|
game=this;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Crawler::OnUserCreate(){
|
|
|
|
|
|
|
|
InitializeLevel("assets/maps/Level1.tmx",LEVEL1);
|
|
|
|
InitializeLevel("assets/maps/Level2.tmx",LEVEL2);
|
|
|
|
InitializeLevel("assets/Campaigns/1_1_test.tmx",CAMPAIGN_1_1);
|
|
|
|
|
|
|
|
ClassData::InitializeClassData();
|
|
|
|
|
|
|
|
//Initialize Camera.
|
|
|
|
camera=Camera2D{WINDOW_SIZE};
|
|
|
|
camera.SetMode(olc::utils::Camera2D::Mode::LazyFollow);
|
|
|
|
camera.SetTarget(player.GetPos());
|
|
|
|
camera.SetWorldBoundary({0,0},WORLD_SIZE*24);
|
|
|
|
camera.EnableWorldBoundary(false);
|
|
|
|
|
|
|
|
//Graphics
|
|
|
|
GFX_Warrior_Sheet.Load("assets/nico-warrior.png");
|
|
|
|
GFX_Slime_Sheet.Load("assets/slime.png");
|
|
|
|
GFX_Circle.Load("assets/circle.png");
|
|
|
|
GFX_Effect_GroundSlam_Back.Load("assets/ground-slam-attack-back.png");
|
|
|
|
GFX_Effect_GroundSlam_Front.Load("assets/ground-slam-attack-front.png");
|
|
|
|
GFX_Heart.Load("assets/heart.png");
|
|
|
|
GFX_BLOCK_BUBBLE.Load("assets/block.png");
|
|
|
|
GFX_Ranger_Sheet.Load("assets/nico-ranger.png");
|
|
|
|
GFX_Wizard_Sheet.Load("assets/nico-wizard.png");
|
|
|
|
GFX_Battlecry_Effect.Load("assets/battlecry_effect.png");
|
|
|
|
GFX_Mana.Load("assets/mana.png");
|
|
|
|
GFX_SonicSlash.Load("assets/sonicslash.png");
|
|
|
|
GFX_BulletCircle.Load("assets/circle.png");
|
|
|
|
GFX_BulletCircleOutline.Load("assets/circle_outline.png");
|
|
|
|
GFX_EnergyBolt.Load("assets/energy_bolt.png");
|
|
|
|
GFX_EnergyParticle.Load("assets/energy_particle.png");
|
|
|
|
GFX_Splash_Effect.Load("assets/splash_effect.png");
|
|
|
|
|
|
|
|
//Animations
|
|
|
|
InitializeAnimations();
|
|
|
|
|
|
|
|
player.AddAnimation(AnimationState::WARRIOR_WALK_N);
|
|
|
|
player.AddAnimation(AnimationState::WARRIOR_WALK_E);
|
|
|
|
player.AddAnimation(AnimationState::WARRIOR_WALK_S);
|
|
|
|
player.AddAnimation(AnimationState::WARRIOR_WALK_W);
|
|
|
|
player.AddAnimation(AnimationState::WARRIOR_IDLE_N);
|
|
|
|
player.AddAnimation(AnimationState::WARRIOR_IDLE_E);
|
|
|
|
player.AddAnimation(AnimationState::WARRIOR_IDLE_S);
|
|
|
|
player.AddAnimation(AnimationState::WARRIOR_IDLE_W);
|
|
|
|
player.AddAnimation(AnimationState::WARRIOR_SWINGSWORD_E);
|
|
|
|
player.AddAnimation(AnimationState::WARRIOR_SWINGSWORD_S);
|
|
|
|
player.AddAnimation(AnimationState::WARRIOR_SWINGSWORD_N);
|
|
|
|
player.AddAnimation(AnimationState::WARRIOR_SWINGSWORD_W);
|
|
|
|
player.AddAnimation(AnimationState::WARRIOR_SWINGSONICSWORD_E);
|
|
|
|
player.AddAnimation(AnimationState::WARRIOR_SWINGSONICSWORD_S);
|
|
|
|
player.AddAnimation(AnimationState::WARRIOR_SWINGSONICSWORD_N);
|
|
|
|
player.AddAnimation(AnimationState::WARRIOR_SWINGSONICSWORD_W);
|
|
|
|
player.AddAnimation(AnimationState::RANGER_WALK_N);
|
|
|
|
player.AddAnimation(AnimationState::RANGER_WALK_E);
|
|
|
|
player.AddAnimation(AnimationState::RANGER_WALK_S);
|
|
|
|
player.AddAnimation(AnimationState::RANGER_WALK_W);
|
|
|
|
player.AddAnimation(AnimationState::RANGER_IDLE_N);
|
|
|
|
player.AddAnimation(AnimationState::RANGER_IDLE_E);
|
|
|
|
player.AddAnimation(AnimationState::RANGER_IDLE_S);
|
|
|
|
player.AddAnimation(AnimationState::RANGER_IDLE_W);
|
|
|
|
player.AddAnimation(AnimationState::WIZARD_WALK_N);
|
|
|
|
player.AddAnimation(AnimationState::WIZARD_WALK_E);
|
|
|
|
player.AddAnimation(AnimationState::WIZARD_WALK_S);
|
|
|
|
player.AddAnimation(AnimationState::WIZARD_WALK_W);
|
|
|
|
player.AddAnimation(AnimationState::WIZARD_IDLE_N);
|
|
|
|
player.AddAnimation(AnimationState::WIZARD_IDLE_E);
|
|
|
|
player.AddAnimation(AnimationState::WIZARD_IDLE_S);
|
|
|
|
player.AddAnimation(AnimationState::WIZARD_IDLE_W);
|
|
|
|
player.AddAnimation(AnimationState::WIZARD_IDLE_ATTACK_N);
|
|
|
|
player.AddAnimation(AnimationState::WIZARD_IDLE_ATTACK_E);
|
|
|
|
player.AddAnimation(AnimationState::WIZARD_IDLE_ATTACK_S);
|
|
|
|
player.AddAnimation(AnimationState::WIZARD_IDLE_ATTACK_W);
|
|
|
|
player.AddAnimation(AnimationState::WIZARD_ATTACK_N);
|
|
|
|
player.AddAnimation(AnimationState::WIZARD_ATTACK_E);
|
|
|
|
player.AddAnimation(AnimationState::WIZARD_ATTACK_S);
|
|
|
|
player.AddAnimation(AnimationState::WIZARD_ATTACK_W);
|
|
|
|
view=TileTransformedView{GetScreenSize(),{1,1}};
|
|
|
|
|
|
|
|
LoadLevel(CAMPAIGN_1_1);
|
|
|
|
|
|
|
|
player.SetClass(WARRIOR);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Crawler::OnUserUpdate(float fElapsedTime){
|
|
|
|
HandleUserInput(fElapsedTime);
|
|
|
|
UpdateEffects(fElapsedTime);
|
|
|
|
player.Update(fElapsedTime);
|
|
|
|
for(Monster&m:MONSTER_LIST){
|
|
|
|
m.Update(fElapsedTime);
|
|
|
|
}
|
|
|
|
UpdateBullets(fElapsedTime);
|
|
|
|
UpdateCamera(fElapsedTime);
|
|
|
|
RenderWorld(fElapsedTime);
|
|
|
|
RenderHud();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Crawler::InitializeAnimations(){
|
|
|
|
//Warrior animations.
|
|
|
|
Animate2D::FrameSequence pl_warrior_walk_s{0.2};
|
|
|
|
pl_warrior_walk_s.AddFrame({&GFX_Warrior_Sheet,{vi2d{0,0}*24,{24,24}}});
|
|
|
|
pl_warrior_walk_s.AddFrame({&GFX_Warrior_Sheet,{vi2d{1,0}*24,{24,24}}});
|
|
|
|
pl_warrior_walk_s.AddFrame({&GFX_Warrior_Sheet,{vi2d{0,0}*24,{24,24}}});
|
|
|
|
pl_warrior_walk_s.AddFrame({&GFX_Warrior_Sheet,{vi2d{2,0}*24,{24,24}}});
|
|
|
|
ANIMATION_DATA[AnimationState::WARRIOR_WALK_S]=pl_warrior_walk_s;
|
|
|
|
Animate2D::FrameSequence pl_warrior_walk_e{0.2};
|
|
|
|
pl_warrior_walk_e.AddFrame({&GFX_Warrior_Sheet,{vi2d{0,3}*24,{24,24}}});
|
|
|
|
pl_warrior_walk_e.AddFrame({&GFX_Warrior_Sheet,{vi2d{1,3}*24,{24,24}}});
|
|
|
|
pl_warrior_walk_e.AddFrame({&GFX_Warrior_Sheet,{vi2d{0,3}*24,{24,24}}});
|
|
|
|
pl_warrior_walk_e.AddFrame({&GFX_Warrior_Sheet,{vi2d{2,3}*24,{24,24}}});
|
|
|
|
ANIMATION_DATA[AnimationState::WARRIOR_WALK_E]=pl_warrior_walk_e;
|
|
|
|
Animate2D::FrameSequence pl_warrior_walk_w{0.2};
|
|
|
|
pl_warrior_walk_w.AddFrame({&GFX_Warrior_Sheet,{vi2d{0,2}*24,{24,24}}});
|
|
|
|
pl_warrior_walk_w.AddFrame({&GFX_Warrior_Sheet,{vi2d{1,2}*24,{24,24}}});
|
|
|
|
pl_warrior_walk_w.AddFrame({&GFX_Warrior_Sheet,{vi2d{0,2}*24,{24,24}}});
|
|
|
|
pl_warrior_walk_w.AddFrame({&GFX_Warrior_Sheet,{vi2d{2,2}*24,{24,24}}});
|
|
|
|
ANIMATION_DATA[AnimationState::WARRIOR_WALK_W]=pl_warrior_walk_w;
|
|
|
|
Animate2D::FrameSequence pl_warrior_walk_n{0.2};
|
|
|
|
pl_warrior_walk_n.AddFrame({&GFX_Warrior_Sheet,{vi2d{0,1}*24,{24,24}}});
|
|
|
|
pl_warrior_walk_n.AddFrame({&GFX_Warrior_Sheet,{vi2d{1,1}*24,{24,24}}});
|
|
|
|
pl_warrior_walk_n.AddFrame({&GFX_Warrior_Sheet,{vi2d{0,1}*24,{24,24}}});
|
|
|
|
pl_warrior_walk_n.AddFrame({&GFX_Warrior_Sheet,{vi2d{2,1}*24,{24,24}}});
|
|
|
|
ANIMATION_DATA[AnimationState::WARRIOR_WALK_N]=pl_warrior_walk_n;
|
|
|
|
Animate2D::FrameSequence pl_warrior_idle_s;
|
|
|
|
pl_warrior_idle_s.AddFrame({&GFX_Warrior_Sheet,{vi2d{0,0}*24,{24,24}}});
|
|
|
|
ANIMATION_DATA[AnimationState::WARRIOR_IDLE_S]=pl_warrior_idle_s;
|
|
|
|
Animate2D::FrameSequence pl_warrior_idle_e;
|
|
|
|
pl_warrior_idle_e.AddFrame({&GFX_Warrior_Sheet,{vi2d{0,3}*24,{24,24}}});
|
|
|
|
ANIMATION_DATA[AnimationState::WARRIOR_IDLE_E]=pl_warrior_idle_e;
|
|
|
|
Animate2D::FrameSequence pl_warrior_idle_w;
|
|
|
|
pl_warrior_idle_w.AddFrame({&GFX_Warrior_Sheet,{vi2d{0,2}*24,{24,24}}});
|
|
|
|
ANIMATION_DATA[AnimationState::WARRIOR_IDLE_W]=pl_warrior_idle_w;
|
|
|
|
Animate2D::FrameSequence pl_warrior_idle_n;
|
|
|
|
pl_warrior_idle_n.AddFrame({&GFX_Warrior_Sheet,{vi2d{0,1}*24,{24,24}}});
|
|
|
|
ANIMATION_DATA[AnimationState::WARRIOR_IDLE_N]=pl_warrior_idle_n;
|
|
|
|
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({&GFX_Warrior_Sheet,{vi2d{4+i,0}*24,{24,24}}});
|
|
|
|
pl_warrior_sonic_swing_s.AddFrame({&GFX_Warrior_Sheet,{vi2d{4+i,4}*24,{24,24}}});
|
|
|
|
}
|
|
|
|
for (int i=0;i<4;i++){
|
|
|
|
pl_warrior_swing_n.AddFrame({&GFX_Warrior_Sheet,{vi2d{4+i,1}*24,{24,24}}});
|
|
|
|
pl_warrior_sonic_swing_n.AddFrame({&GFX_Warrior_Sheet,{vi2d{4+i,5}*24,{24,24}}});
|
|
|
|
}
|
|
|
|
for (int i=0;i<4;i++){
|
|
|
|
pl_warrior_swing_w.AddFrame({&GFX_Warrior_Sheet,{vi2d{4+i,2}*24,{24,24}}});
|
|
|
|
pl_warrior_sonic_swing_w.AddFrame({&GFX_Warrior_Sheet,{vi2d{4+i,6}*24,{24,24}}});
|
|
|
|
}
|
|
|
|
for (int i=0;i<4;i++){
|
|
|
|
pl_warrior_swing_e.AddFrame({&GFX_Warrior_Sheet,{vi2d{4+i,3}*24,{24,24}}});
|
|
|
|
pl_warrior_sonic_swing_e.AddFrame({&GFX_Warrior_Sheet,{vi2d{4+i,7}*24,{24,24}}});
|
|
|
|
}
|
|
|
|
ANIMATION_DATA[AnimationState::WARRIOR_SWINGSWORD_N]=pl_warrior_swing_n;
|
|
|
|
ANIMATION_DATA[AnimationState::WARRIOR_SWINGSWORD_E]=pl_warrior_swing_e;
|
|
|
|
ANIMATION_DATA[AnimationState::WARRIOR_SWINGSWORD_S]=pl_warrior_swing_s;
|
|
|
|
ANIMATION_DATA[AnimationState::WARRIOR_SWINGSWORD_W]=pl_warrior_swing_w;
|
|
|
|
ANIMATION_DATA[AnimationState::WARRIOR_SWINGSONICSWORD_N]=pl_warrior_sonic_swing_n;
|
|
|
|
ANIMATION_DATA[AnimationState::WARRIOR_SWINGSONICSWORD_E]=pl_warrior_sonic_swing_e;
|
|
|
|
ANIMATION_DATA[AnimationState::WARRIOR_SWINGSONICSWORD_S]=pl_warrior_sonic_swing_s;
|
|
|
|
ANIMATION_DATA[AnimationState::WARRIOR_SWINGSONICSWORD_W]=pl_warrior_sonic_swing_w;
|
|
|
|
|
|
|
|
//Ranger animations
|
|
|
|
Animate2D::FrameSequence pl_ranger_walk_s{0.2};
|
|
|
|
pl_ranger_walk_s.AddFrame({&GFX_Ranger_Sheet,{vi2d{0,0}*24,{24,24}}});
|
|
|
|
pl_ranger_walk_s.AddFrame({&GFX_Ranger_Sheet,{vi2d{1,0}*24,{24,24}}});
|
|
|
|
pl_ranger_walk_s.AddFrame({&GFX_Ranger_Sheet,{vi2d{0,0}*24,{24,24}}});
|
|
|
|
pl_ranger_walk_s.AddFrame({&GFX_Ranger_Sheet,{vi2d{2,0}*24,{24,24}}});
|
|
|
|
ANIMATION_DATA[AnimationState::RANGER_WALK_S]=pl_ranger_walk_s;
|
|
|
|
Animate2D::FrameSequence pl_ranger_walk_e{0.2};
|
|
|
|
pl_ranger_walk_e.AddFrame({&GFX_Ranger_Sheet,{vi2d{0,3}*24,{24,24}}});
|
|
|
|
pl_ranger_walk_e.AddFrame({&GFX_Ranger_Sheet,{vi2d{1,3}*24,{24,24}}});
|
|
|
|
pl_ranger_walk_e.AddFrame({&GFX_Ranger_Sheet,{vi2d{0,3}*24,{24,24}}});
|
|
|
|
pl_ranger_walk_e.AddFrame({&GFX_Ranger_Sheet,{vi2d{2,3}*24,{24,24}}});
|
|
|
|
ANIMATION_DATA[AnimationState::RANGER_WALK_E]=pl_ranger_walk_e;
|
|
|
|
Animate2D::FrameSequence pl_ranger_walk_w{0.2};
|
|
|
|
pl_ranger_walk_w.AddFrame({&GFX_Ranger_Sheet,{vi2d{0,2}*24,{24,24}}});
|
|
|
|
pl_ranger_walk_w.AddFrame({&GFX_Ranger_Sheet,{vi2d{1,2}*24,{24,24}}});
|
|
|
|
pl_ranger_walk_w.AddFrame({&GFX_Ranger_Sheet,{vi2d{0,2}*24,{24,24}}});
|
|
|
|
pl_ranger_walk_w.AddFrame({&GFX_Ranger_Sheet,{vi2d{2,2}*24,{24,24}}});
|
|
|
|
ANIMATION_DATA[AnimationState::RANGER_WALK_W]=pl_ranger_walk_w;
|
|
|
|
Animate2D::FrameSequence pl_ranger_walk_n{0.2};
|
|
|
|
pl_ranger_walk_n.AddFrame({&GFX_Ranger_Sheet,{vi2d{0,1}*24,{24,24}}});
|
|
|
|
pl_ranger_walk_n.AddFrame({&GFX_Ranger_Sheet,{vi2d{1,1}*24,{24,24}}});
|
|
|
|
pl_ranger_walk_n.AddFrame({&GFX_Ranger_Sheet,{vi2d{0,1}*24,{24,24}}});
|
|
|
|
pl_ranger_walk_n.AddFrame({&GFX_Ranger_Sheet,{vi2d{2,1}*24,{24,24}}});
|
|
|
|
ANIMATION_DATA[AnimationState::RANGER_WALK_N]=pl_ranger_walk_n;
|
|
|
|
Animate2D::FrameSequence pl_ranger_idle_s;
|
|
|
|
pl_ranger_idle_s.AddFrame({&GFX_Ranger_Sheet,{vi2d{0,0}*24,{24,24}}});
|
|
|
|
ANIMATION_DATA[AnimationState::RANGER_IDLE_S]=pl_ranger_idle_s;
|
|
|
|
Animate2D::FrameSequence pl_ranger_idle_e;
|
|
|
|
pl_ranger_idle_e.AddFrame({&GFX_Ranger_Sheet,{vi2d{0,3}*24,{24,24}}});
|
|
|
|
ANIMATION_DATA[AnimationState::RANGER_IDLE_E]=pl_ranger_idle_e;
|
|
|
|
Animate2D::FrameSequence pl_ranger_idle_w;
|
|
|
|
pl_ranger_idle_w.AddFrame({&GFX_Ranger_Sheet,{vi2d{0,2}*24,{24,24}}});
|
|
|
|
ANIMATION_DATA[AnimationState::RANGER_IDLE_W]=pl_ranger_idle_w;
|
|
|
|
Animate2D::FrameSequence pl_ranger_idle_n;
|
|
|
|
pl_ranger_idle_n.AddFrame({&GFX_Ranger_Sheet,{vi2d{0,1}*24,{24,24}}});
|
|
|
|
ANIMATION_DATA[AnimationState::RANGER_IDLE_N]=pl_ranger_idle_n;
|
|
|
|
|
|
|
|
//Wizard animations
|
|
|
|
Animate2D::FrameSequence pl_wizard_walk_s{0.2};
|
|
|
|
pl_wizard_walk_s.AddFrame({&GFX_Wizard_Sheet,{vi2d{0,0}*24,{24,24}}});
|
|
|
|
pl_wizard_walk_s.AddFrame({&GFX_Wizard_Sheet,{vi2d{1,0}*24,{24,24}}});
|
|
|
|
pl_wizard_walk_s.AddFrame({&GFX_Wizard_Sheet,{vi2d{0,0}*24,{24,24}}});
|
|
|
|
pl_wizard_walk_s.AddFrame({&GFX_Wizard_Sheet,{vi2d{2,0}*24,{24,24}}});
|
|
|
|
ANIMATION_DATA[AnimationState::WIZARD_WALK_S]=pl_wizard_walk_s;
|
|
|
|
Animate2D::FrameSequence pl_wizard_walk_e{0.2};
|
|
|
|
pl_wizard_walk_e.AddFrame({&GFX_Wizard_Sheet,{vi2d{0,3}*24,{24,24}}});
|
|
|
|
pl_wizard_walk_e.AddFrame({&GFX_Wizard_Sheet,{vi2d{1,3}*24,{24,24}}});
|
|
|
|
pl_wizard_walk_e.AddFrame({&GFX_Wizard_Sheet,{vi2d{0,3}*24,{24,24}}});
|
|
|
|
pl_wizard_walk_e.AddFrame({&GFX_Wizard_Sheet,{vi2d{2,3}*24,{24,24}}});
|
|
|
|
ANIMATION_DATA[AnimationState::WIZARD_WALK_E]=pl_wizard_walk_e;
|
|
|
|
Animate2D::FrameSequence pl_wizard_walk_w{0.2};
|
|
|
|
pl_wizard_walk_w.AddFrame({&GFX_Wizard_Sheet,{vi2d{0,2}*24,{24,24}}});
|
|
|
|
pl_wizard_walk_w.AddFrame({&GFX_Wizard_Sheet,{vi2d{1,2}*24,{24,24}}});
|
|
|
|
pl_wizard_walk_w.AddFrame({&GFX_Wizard_Sheet,{vi2d{0,2}*24,{24,24}}});
|
|
|
|
pl_wizard_walk_w.AddFrame({&GFX_Wizard_Sheet,{vi2d{2,2}*24,{24,24}}});
|
|
|
|
ANIMATION_DATA[AnimationState::WIZARD_WALK_W]=pl_wizard_walk_w;
|
|
|
|
Animate2D::FrameSequence pl_wizard_walk_n{0.2};
|
|
|
|
pl_wizard_walk_n.AddFrame({&GFX_Wizard_Sheet,{vi2d{0,1}*24,{24,24}}});
|
|
|
|
pl_wizard_walk_n.AddFrame({&GFX_Wizard_Sheet,{vi2d{1,1}*24,{24,24}}});
|
|
|
|
pl_wizard_walk_n.AddFrame({&GFX_Wizard_Sheet,{vi2d{0,1}*24,{24,24}}});
|
|
|
|
pl_wizard_walk_n.AddFrame({&GFX_Wizard_Sheet,{vi2d{2,1}*24,{24,24}}});
|
|
|
|
ANIMATION_DATA[AnimationState::WIZARD_WALK_N]=pl_wizard_walk_n;
|
|
|
|
Animate2D::FrameSequence pl_wizard_idle_s;
|
|
|
|
pl_wizard_idle_s.AddFrame({&GFX_Wizard_Sheet,{vi2d{0,0}*24,{24,24}}});
|
|
|
|
ANIMATION_DATA[AnimationState::WIZARD_IDLE_S]=pl_wizard_idle_s;
|
|
|
|
Animate2D::FrameSequence pl_wizard_idle_e;
|
|
|
|
pl_wizard_idle_e.AddFrame({&GFX_Wizard_Sheet,{vi2d{0,3}*24,{24,24}}});
|
|
|
|
ANIMATION_DATA[AnimationState::WIZARD_IDLE_E]=pl_wizard_idle_e;
|
|
|
|
Animate2D::FrameSequence pl_wizard_idle_w;
|
|
|
|
pl_wizard_idle_w.AddFrame({&GFX_Wizard_Sheet,{vi2d{0,2}*24,{24,24}}});
|
|
|
|
ANIMATION_DATA[AnimationState::WIZARD_IDLE_W]=pl_wizard_idle_w;
|
|
|
|
Animate2D::FrameSequence pl_wizard_idle_n;
|
|
|
|
pl_wizard_idle_n.AddFrame({&GFX_Wizard_Sheet,{vi2d{0,1}*24,{24,24}}});
|
|
|
|
ANIMATION_DATA[AnimationState::WIZARD_IDLE_N]=pl_wizard_idle_n;
|
|
|
|
Animate2D::FrameSequence pl_wizard_idle_attack_s;
|
|
|
|
pl_wizard_idle_attack_s.AddFrame({&GFX_Wizard_Sheet,{vi2d{4,0}*24,{24,24}}});
|
|
|
|
ANIMATION_DATA[AnimationState::WIZARD_IDLE_ATTACK_S]=pl_wizard_idle_attack_s;
|
|
|
|
Animate2D::FrameSequence pl_wizard_idle_attack_e;
|
|
|
|
pl_wizard_idle_attack_e.AddFrame({&GFX_Wizard_Sheet,{vi2d{4,3}*24,{24,24}}});
|
|
|
|
ANIMATION_DATA[AnimationState::WIZARD_IDLE_ATTACK_E]=pl_wizard_idle_attack_e;
|
|
|
|
Animate2D::FrameSequence pl_wizard_idle_attack_w;
|
|
|
|
pl_wizard_idle_attack_w.AddFrame({&GFX_Wizard_Sheet,{vi2d{4,2}*24,{24,24}}});
|
|
|
|
ANIMATION_DATA[AnimationState::WIZARD_IDLE_ATTACK_W]=pl_wizard_idle_attack_w;
|
|
|
|
Animate2D::FrameSequence pl_wizard_idle_attack_n;
|
|
|
|
pl_wizard_idle_attack_n.AddFrame({&GFX_Wizard_Sheet,{vi2d{4,1}*24,{24,24}}});
|
|
|
|
ANIMATION_DATA[AnimationState::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({&GFX_Wizard_Sheet,{vi2d{4+i,0}*24,{24,24}}});
|
|
|
|
if(i==1){
|
|
|
|
pl_wizard_attack_s.AddFrame({&GFX_Wizard_Sheet,{vi2d{4,0}*24,{24,24}}});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ANIMATION_DATA[AnimationState::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({&GFX_Wizard_Sheet,{vi2d{4+i,3}*24,{24,24}}});
|
|
|
|
if(i==1){
|
|
|
|
pl_wizard_attack_e.AddFrame({&GFX_Wizard_Sheet,{vi2d{4,3}*24,{24,24}}});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ANIMATION_DATA[AnimationState::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({&GFX_Wizard_Sheet,{vi2d{4+i,2}*24,{24,24}}});
|
|
|
|
if(i==1){
|
|
|
|
pl_wizard_attack_w.AddFrame({&GFX_Wizard_Sheet,{vi2d{4,2}*24,{24,24}}});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ANIMATION_DATA[AnimationState::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({&GFX_Wizard_Sheet,{vi2d{4+i,1}*24,{24,24}}});
|
|
|
|
if(i==1){
|
|
|
|
pl_wizard_attack_n.AddFrame({&GFX_Wizard_Sheet,{vi2d{4,1}*24,{24,24}}});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ANIMATION_DATA[AnimationState::WIZARD_ATTACK_N]=pl_wizard_attack_n;
|
|
|
|
|
|
|
|
//Load slime animations.
|
|
|
|
for(int slime=0;slime<4;slime++){
|
|
|
|
for(int state=0;state<5;state++){
|
|
|
|
Animate2D::FrameSequence anim;
|
|
|
|
if(state==4){//These are death animations.
|
|
|
|
anim=Animate2D::FrameSequence(0.1f,Animate2D::Style::OneShot);
|
|
|
|
}
|
|
|
|
if(state==2){//These are death animations.
|
|
|
|
anim=Animate2D::FrameSequence(0.06f);
|
|
|
|
}
|
|
|
|
for (int frame=0;frame<10;frame++){
|
|
|
|
anim.AddFrame({&GFX_Slime_Sheet,{vi2d{frame,state+5*slime}*24,{24,24}}});
|
|
|
|
}
|
|
|
|
ANIMATION_DATA[AnimationState(AnimationState::GREEN_SLIME_IDLE+state+slime*5)]=anim;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Animate2D::FrameSequence effect_groundslam_back(0.02f,Animate2D::Style::OneShot),effect_groundslam_front(0.02f,Animate2D::Style::OneShot);
|
|
|
|
for(int i=0;i<5;i++){
|
|
|
|
effect_groundslam_back.AddFrame({&GFX_Effect_GroundSlam_Back,{{i*64,0},{64,64}}});
|
|
|
|
effect_groundslam_front.AddFrame({&GFX_Effect_GroundSlam_Front,{{i*64,0},{64,64}}});
|
|
|
|
}
|
|
|
|
ANIMATION_DATA[AnimationState::GROUND_SLAM_ATTACK_BACK]=effect_groundslam_back;
|
|
|
|
ANIMATION_DATA[AnimationState::GROUND_SLAM_ATTACK_FRONT]=effect_groundslam_front;
|
|
|
|
Animate2D::FrameSequence battlecry_effect(0.02f,Animate2D::Style::OneShot);
|
|
|
|
for(int i=0;i<5;i++){
|
|
|
|
battlecry_effect.AddFrame({&GFX_Battlecry_Effect,{{i*84,0},{84,84}}});
|
|
|
|
}
|
|
|
|
ANIMATION_DATA[AnimationState::BATTLECRY_EFFECT]=battlecry_effect;
|
|
|
|
Animate2D::FrameSequence sonicslash_effect(0.04f,Animate2D::Style::OneShot);
|
|
|
|
for(int i=0;i<4;i++){
|
|
|
|
sonicslash_effect.AddFrame({&GFX_SonicSlash,{{i*60,0},{60,60}}});
|
|
|
|
}
|
|
|
|
ANIMATION_DATA[AnimationState::SONICSLASH]=sonicslash_effect;
|
|
|
|
Animate2D::FrameSequence energy_bolt;
|
|
|
|
energy_bolt.AddFrame({&GFX_EnergyBolt,{{0,0},{24,24}}});
|
|
|
|
ANIMATION_DATA[AnimationState::ENERGY_BOLT]=energy_bolt;
|
|
|
|
|
|
|
|
Animate2D::FrameSequence energy_particle;
|
|
|
|
for(int i=0;i<3;i++){
|
|
|
|
energy_particle.AddFrame({&GFX_EnergyParticle,{{i*3,0},{3,3}}});
|
|
|
|
}
|
|
|
|
ANIMATION_DATA[AnimationState::ENERGY_PARTICLE]=energy_particle;
|
|
|
|
|
|
|
|
Animate2D::FrameSequence splash_animation(0.05);
|
|
|
|
for(int i=0;i<5;i++){
|
|
|
|
splash_animation.AddFrame({&GFX_Splash_Effect,{{i*24,0},{24,24}}});
|
|
|
|
}
|
|
|
|
ANIMATION_DATA[AnimationState::SPLASH_EFFECT]=splash_animation;
|
|
|
|
|
|
|
|
Animate2D::FrameSequence dot_particle;
|
|
|
|
dot_particle.AddFrame({&GFX_BulletCircle,{{0,0},{3,3}}});
|
|
|
|
ANIMATION_DATA[AnimationState::DOT_PARTICLE]=dot_particle;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Crawler::LeftHeld(){
|
|
|
|
return GetKey(LEFT).bHeld||GetKey(A).bHeld;
|
|
|
|
}
|
|
|
|
bool Crawler::RightHeld(){
|
|
|
|
return GetKey(RIGHT).bHeld||GetKey(D).bHeld;
|
|
|
|
}
|
|
|
|
bool Crawler::UpHeld(){
|
|
|
|
return GetKey(UP).bHeld||GetKey(W).bHeld;
|
|
|
|
}
|
|
|
|
bool Crawler::DownHeld(){
|
|
|
|
return GetKey(DOWN).bHeld||GetKey(S).bHeld;
|
|
|
|
}
|
|
|
|
bool Crawler::LeftReleased(){
|
|
|
|
return GetKey(LEFT).bReleased||GetKey(A).bReleased;
|
|
|
|
}
|
|
|
|
bool Crawler::RightReleased(){
|
|
|
|
return GetKey(RIGHT).bReleased||GetKey(D).bReleased;
|
|
|
|
}
|
|
|
|
bool Crawler::UpReleased(){
|
|
|
|
return GetKey(UP).bReleased||GetKey(W).bReleased;
|
|
|
|
}
|
|
|
|
bool Crawler::DownReleased(){
|
|
|
|
return GetKey(DOWN).bReleased||GetKey(S).bReleased;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Crawler::HandleUserInput(float fElapsedTime){
|
|
|
|
bool setIdleAnimation=true;
|
|
|
|
if(GetKey(F1).bPressed){
|
|
|
|
ConsoleShow(F1);
|
|
|
|
}
|
|
|
|
if(GetMouseWheel()>0){
|
|
|
|
switch(player.cl){
|
|
|
|
case WARRIOR:{
|
|
|
|
player.SetClass(RANGER);
|
|
|
|
}break;
|
|
|
|
case RANGER:{
|
|
|
|
player.SetClass(WIZARD);
|
|
|
|
}break;
|
|
|
|
case WIZARD:{
|
|
|
|
player.SetClass(WARRIOR);
|
|
|
|
}break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(GetMouseWheel()<0){
|
|
|
|
switch(player.cl){
|
|
|
|
case WARRIOR:{
|
|
|
|
player.SetClass(WIZARD);
|
|
|
|
}break;
|
|
|
|
case RANGER:{
|
|
|
|
player.SetClass(WARRIOR);
|
|
|
|
}break;
|
|
|
|
case WIZARD:{
|
|
|
|
player.SetClass(RANGER);
|
|
|
|
}break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(player.GetVelocity()==vf2d{0,0}){
|
|
|
|
if(RightHeld()){
|
|
|
|
player.SetX(player.GetX()+fElapsedTime*100*player.GetMoveSpdMult());
|
|
|
|
player.SetFacingDirection(RIGHT);
|
|
|
|
if(player.GetState()==State::NORMAL){
|
|
|
|
player.UpdateWalkingAnimation(RIGHT);
|
|
|
|
}
|
|
|
|
setIdleAnimation=false;
|
|
|
|
}
|
|
|
|
if(LeftHeld()){
|
|
|
|
player.SetX(player.GetX()-fElapsedTime*100*player.GetMoveSpdMult());
|
|
|
|
if(setIdleAnimation){
|
|
|
|
player.SetFacingDirection(LEFT);
|
|
|
|
if(player.GetState()==State::NORMAL){
|
|
|
|
player.UpdateWalkingAnimation(LEFT);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
setIdleAnimation=false;
|
|
|
|
}
|
|
|
|
if(UpHeld()){
|
|
|
|
player.SetY(player.GetY()-fElapsedTime*100*player.GetMoveSpdMult());
|
|
|
|
if(setIdleAnimation){
|
|
|
|
player.SetFacingDirection(UP);
|
|
|
|
if(player.GetState()==State::NORMAL){
|
|
|
|
player.UpdateWalkingAnimation(UP);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
setIdleAnimation=false;
|
|
|
|
}
|
|
|
|
if(DownHeld()){
|
|
|
|
player.SetY(player.GetY()+fElapsedTime*100*player.GetMoveSpdMult());
|
|
|
|
if(setIdleAnimation){
|
|
|
|
player.SetFacingDirection(DOWN);
|
|
|
|
if(player.GetState()==State::NORMAL){
|
|
|
|
player.UpdateWalkingAnimation(DOWN);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
setIdleAnimation=false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(UpReleased()){
|
|
|
|
player.SetLastReleasedMovementKey(UP);
|
|
|
|
if(player.GetState()==State::NORMAL){
|
|
|
|
if(RightHeld()){
|
|
|
|
player.UpdateWalkingAnimation(RIGHT);
|
|
|
|
} else
|
|
|
|
if(DownHeld()){
|
|
|
|
player.UpdateWalkingAnimation(DOWN);
|
|
|
|
} else
|
|
|
|
if(LeftHeld()){
|
|
|
|
player.UpdateWalkingAnimation(LEFT);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(RightReleased()){
|
|
|
|
player.SetLastReleasedMovementKey(RIGHT);
|
|
|
|
if(player.GetState()==State::NORMAL){
|
|
|
|
if(UpHeld()){
|
|
|
|
player.UpdateWalkingAnimation(UP);
|
|
|
|
} else
|
|
|
|
if(DownHeld()){
|
|
|
|
player.UpdateWalkingAnimation(DOWN);
|
|
|
|
} else
|
|
|
|
if(LeftHeld()){
|
|
|
|
player.UpdateWalkingAnimation(LEFT);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(LeftReleased()){
|
|
|
|
player.SetLastReleasedMovementKey(LEFT);
|
|
|
|
if(player.GetState()==State::NORMAL){
|
|
|
|
if(RightHeld()){
|
|
|
|
player.UpdateWalkingAnimation(RIGHT);
|
|
|
|
} else
|
|
|
|
if(DownHeld()){
|
|
|
|
player.UpdateWalkingAnimation(DOWN);
|
|
|
|
} else
|
|
|
|
if(UpHeld()){
|
|
|
|
player.UpdateWalkingAnimation(UP);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(DownReleased()){
|
|
|
|
player.SetLastReleasedMovementKey(DOWN);
|
|
|
|
if(player.GetState()==State::NORMAL){
|
|
|
|
if(RightHeld()){
|
|
|
|
player.UpdateWalkingAnimation(RIGHT);
|
|
|
|
} else
|
|
|
|
if(UpHeld()){
|
|
|
|
player.UpdateWalkingAnimation(UP);
|
|
|
|
} else
|
|
|
|
if(LeftHeld()){
|
|
|
|
player.UpdateWalkingAnimation(LEFT);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(player.GetState()==State::SWING_SWORD){
|
|
|
|
setIdleAnimation=false;
|
|
|
|
switch(player.GetFacingDirection()){
|
|
|
|
case UP:{
|
|
|
|
player.UpdateAnimation(AnimationState::WARRIOR_SWINGSWORD_N);
|
|
|
|
}break;
|
|
|
|
case DOWN:{
|
|
|
|
player.UpdateAnimation(AnimationState::WARRIOR_SWINGSWORD_S);
|
|
|
|
}break;
|
|
|
|
case LEFT:{
|
|
|
|
player.UpdateAnimation(AnimationState::WARRIOR_SWINGSWORD_W);
|
|
|
|
}break;
|
|
|
|
case RIGHT:{
|
|
|
|
player.UpdateAnimation(AnimationState::WARRIOR_SWINGSWORD_E);
|
|
|
|
}break;
|
|
|
|
}
|
|
|
|
player.SetSwordSwingTimer(player.GetSwordSwingTimer()-fElapsedTime);
|
|
|
|
if(player.GetSwordSwingTimer()<=0){
|
|
|
|
player.SetSwordSwingTimer(0);
|
|
|
|
player.SetState(State::NORMAL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(player.GetState()!=State::NORMAL){
|
|
|
|
setIdleAnimation=false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(setIdleAnimation){
|
|
|
|
switch(player.GetLastReleasedMovementKey()){
|
|
|
|
case UP:{
|
|
|
|
player.UpdateIdleAnimation(UP);
|
|
|
|
}break;
|
|
|
|
case DOWN:{
|
|
|
|
player.UpdateIdleAnimation(DOWN);
|
|
|
|
}break;
|
|
|
|
case LEFT:{
|
|
|
|
player.UpdateIdleAnimation(LEFT);
|
|
|
|
}break;
|
|
|
|
case RIGHT:{
|
|
|
|
player.UpdateIdleAnimation(RIGHT);
|
|
|
|
}break;
|
|
|
|
default:{
|
|
|
|
player.UpdateIdleAnimation(DOWN);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
//We have moved.
|
|
|
|
player.Moved();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Crawler::UpdateCamera(float fElapsedTime){
|
|
|
|
lastWorldShakeAdjust=std::max(0.f,lastWorldShakeAdjust-fElapsedTime);
|
|
|
|
if(worldShakeTime-fElapsedTime>0){
|
|
|
|
if(lastWorldShakeAdjust==0){
|
|
|
|
lastWorldShakeAdjust=util::random(0.2)+0.05;
|
|
|
|
worldShakeVel={util::random(300)-150,util::random(300)-150};
|
|
|
|
}
|
|
|
|
worldShake+=worldShakeVel*fElapsedTime;
|
|
|
|
} else {
|
|
|
|
camera.SetTarget(player.GetPos());
|
|
|
|
}
|
|
|
|
worldShakeTime=std::max(0.f,worldShakeTime-fElapsedTime);
|
|
|
|
camera.Update(fElapsedTime);
|
|
|
|
view.SetWorldOffset(camera.GetViewPosition());
|
|
|
|
}
|
|
|
|
|
|
|
|
void Crawler::UpdateEffects(float fElapsedTime){
|
|
|
|
for(std::vector<Effect>::iterator it=backgroundEffects.begin();it!=backgroundEffects.end();++it){
|
|
|
|
Effect&e=*it;
|
|
|
|
if(!e.Update(fElapsedTime)){
|
|
|
|
it=backgroundEffects.erase(it);
|
|
|
|
if(it==backgroundEffects.end()){
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for(std::vector<Effect>::iterator it=foregroundEffects.begin();it!=foregroundEffects.end();++it){
|
|
|
|
Effect&e=*it;
|
|
|
|
if(!e.Update(fElapsedTime)){
|
|
|
|
it=foregroundEffects.erase(it);
|
|
|
|
if(it==foregroundEffects.end()){
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void Crawler::UpdateBullets(float fElapsedTime){
|
|
|
|
for(auto it=BULLET_LIST.begin();it!=BULLET_LIST.end();++it){
|
|
|
|
Bullet*b=(*it).get();
|
|
|
|
b->UpdateFadeTime(fElapsedTime);
|
|
|
|
b->Update(fElapsedTime);
|
|
|
|
b->pos+=b->vel*fElapsedTime;
|
|
|
|
if(!b->deactivated&&geom2d::overlaps(geom2d::circle(player.GetPos(),12*player.GetSizeMult()/2),geom2d::circle(b->pos,b->radius))){
|
|
|
|
if(player.Hurt(b->damage)){
|
|
|
|
if(b->PlayerHit(player)){
|
|
|
|
it=BULLET_LIST.erase(it);
|
|
|
|
if(it==BULLET_LIST.end()){
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(b->pos.x+b->radius<view.GetWorldTL().x||b->pos.x-b->radius>view.GetWorldBR().x||b->pos.y+b->radius<view.GetWorldTL().y||b->pos.y-b->radius>view.GetWorldBR().y){
|
|
|
|
it=BULLET_LIST.erase(it);
|
|
|
|
if(it==BULLET_LIST.end()){
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
b->lifetime-=fElapsedTime;
|
|
|
|
if(b->lifetime<=0){
|
|
|
|
it=BULLET_LIST.erase(it);
|
|
|
|
if(it==BULLET_LIST.end()){
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
b->animation.UpdateState(b->internal_animState,fElapsedTime);
|
|
|
|
}
|
|
|
|
for(std::vector<std::unique_ptr<Bullet>>::iterator it=PLAYER_BULLET_LIST.begin();it!=PLAYER_BULLET_LIST.end();++it){
|
|
|
|
std::unique_ptr<Bullet>&b=*it;
|
|
|
|
b->UpdateFadeTime(fElapsedTime);
|
|
|
|
b->Update(fElapsedTime);
|
|
|
|
b->pos+=b->vel*fElapsedTime;
|
|
|
|
if(!b->deactivated){
|
|
|
|
for(Monster&m:MONSTER_LIST){
|
|
|
|
if(geom2d::overlaps(geom2d::circle(m.GetPos(),12*m.GetSizeMult()),geom2d::circle(b->pos,b->radius))){
|
|
|
|
if(b->hitList.find(&m)==b->hitList.end()&&m.Hurt(b->damage)){
|
|
|
|
if(!b->hitsMultiple){
|
|
|
|
if(b->MonsterHit(m)){
|
|
|
|
it=PLAYER_BULLET_LIST.erase(it);
|
|
|
|
if(it==PLAYER_BULLET_LIST.end()){
|
|
|
|
goto outsidePlayerBulletLoop;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
goto continuePlayerBulletLoop;
|
|
|
|
}
|
|
|
|
b->hitList[&m]=true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(b->pos.x<view.GetWorldTL().x||b->pos.x>view.GetWorldBR().x||b->pos.y<view.GetWorldTL().y||b->pos.y>view.GetWorldBR().y){
|
|
|
|
it=PLAYER_BULLET_LIST.erase(it);
|
|
|
|
if(it==PLAYER_BULLET_LIST.end()){
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
b->lifetime-=fElapsedTime;
|
|
|
|
if(b->lifetime<=0){
|
|
|
|
it=PLAYER_BULLET_LIST.erase(it);
|
|
|
|
if(it==PLAYER_BULLET_LIST.end()){
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
b->animation.UpdateState(b->internal_animState,fElapsedTime);
|
|
|
|
continuePlayerBulletLoop:
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
outsidePlayerBulletLoop:
|
|
|
|
int a;
|
|
|
|
}
|
|
|
|
void Crawler::HurtEnemies(vf2d pos,float radius,int damage){
|
|
|
|
for(Monster&m:MONSTER_LIST){
|
|
|
|
if(geom2d::overlaps(geom2d::circle(pos,radius),geom2d::circle(m.GetPos(),12*m.GetSizeMult()))){
|
|
|
|
m.Hurt(damage);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Crawler::RenderWorld(float fElapsedTime){
|
|
|
|
Clear({100,180,100});
|
|
|
|
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){
|
|
|
|
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)){
|
|
|
|
view.DrawPartialDecal(vi2d{x,y}*24,{24,24},tileSheet.tileset.tileset->Decal(),vi2d{tileSheetX,tileSheetY}*24,{24,24});
|
|
|
|
}
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//DrawDecal({0,0},MAP_TILESETS["assets/maps/"+MAP_DATA[LEVEL1].TilesetData[1].data["source"]]->Decal());
|
|
|
|
std::vector<Monster>monstersBefore,monstersAfter;
|
|
|
|
Player&pl=player;
|
|
|
|
std::copy_if(MONSTER_LIST.begin(),MONSTER_LIST.end(),std::back_inserter(monstersBefore),[&pl](Monster&m){return m.GetPos().y<pl.GetPos().y;});
|
|
|
|
std::copy_if(MONSTER_LIST.begin(),MONSTER_LIST.end(),std::back_inserter(monstersAfter),[&pl](Monster&m){return m.GetPos().y>=pl.GetPos().y;});
|
|
|
|
std::sort(monstersBefore.begin(),monstersBefore.end(),[](Monster&m1,Monster&m2){return m1.GetPos().y<m2.GetPos().y;});
|
|
|
|
std::sort(monstersAfter.begin(),monstersAfter.end(),[](Monster&m1,Monster&m2){return m1.GetPos().y<m2.GetPos().y;});
|
|
|
|
if(player.GetZ()>0){
|
|
|
|
vf2d shadowScale=vf2d{8/3.f,1}/std::max(1.f,player.GetZ()/4);
|
|
|
|
view.DrawDecal(player.GetPos()-vf2d{3,3}*shadowScale/2+vf2d{0,6},GFX_Circle.Decal(),shadowScale);
|
|
|
|
}
|
|
|
|
for(Effect&e:backgroundEffects){
|
|
|
|
e.Draw();
|
|
|
|
}
|
|
|
|
for(Monster&m:monstersBefore){
|
|
|
|
m.Draw();
|
|
|
|
}
|
|
|
|
vf2d playerScale=vf2d(player.GetSizeMult(),player.GetSizeMult());
|
|
|
|
vf2d playerPosition=player.GetPos();
|
|
|
|
#define RENDER_PLAYER 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);
|
|
|
|
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);
|
|
|
|
RENDER_PLAYER
|
|
|
|
} else {
|
|
|
|
RENDER_PLAYER
|
|
|
|
}
|
|
|
|
if(player.GetState()==State::BLOCK){
|
|
|
|
view.DrawDecal(player.GetPos()-vf2d{12,12},GFX_BLOCK_BUBBLE.Decal());
|
|
|
|
}
|
|
|
|
for(Monster&m:monstersAfter){
|
|
|
|
m.Draw();
|
|
|
|
}
|
|
|
|
for(Effect&e:foregroundEffects){
|
|
|
|
e.Draw();
|
|
|
|
}
|
|
|
|
for(std::unique_ptr<Bullet>&b:BULLET_LIST){
|
|
|
|
b->Draw();
|
|
|
|
}
|
|
|
|
for(std::unique_ptr<Bullet>&b:PLAYER_BULLET_LIST){
|
|
|
|
b->Draw();
|
|
|
|
}
|
|
|
|
for(TileGroup&group:foregroundTileGroups){
|
|
|
|
if(geom2d::overlaps(group.GetRange(),player.pos)){
|
|
|
|
group.playerBehind=true;
|
|
|
|
} else {
|
|
|
|
group.playerBehind=false;
|
|
|
|
}
|
|
|
|
if(view.IsRectVisible(group.GetRange().pos,group.GetRange().size)){
|
|
|
|
for(TileRenderData&tile:group.GetTiles()){
|
|
|
|
view.DrawPartialDecal(tile.pos,{24,24},tile.tileset,tile.tileSheetPos,{24,24},{255,255,255,uint8_t(group.playerBehind?128:255)});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for(std::vector<DamageNumber>::iterator it=DAMAGENUMBER_LIST.begin();it!=DAMAGENUMBER_LIST.end();++it){
|
|
|
|
DamageNumber&dn=*it;
|
|
|
|
dn.lifeTime+=fElapsedTime;
|
|
|
|
if(dn.lifeTime>1){
|
|
|
|
it=DAMAGENUMBER_LIST.erase(it);
|
|
|
|
if(it==DAMAGENUMBER_LIST.end()){
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Player&Crawler::GetPlayer(){
|
|
|
|
return player;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Crawler::RenderHud(){
|
|
|
|
const std::function<std::string(std::string)>capitalize=[](std::string name)->std::string{
|
|
|
|
std::string newName="";
|
|
|
|
for(int i=0;i<name.length();i++){
|
|
|
|
newName.append(1,name[i]>='a'?name[i]-32:name[i]);
|
|
|
|
newName.append(1,' ');
|
|
|
|
}
|
|
|
|
return newName;
|
|
|
|
};
|
|
|
|
std::vector<Ability>cooldowns{
|
|
|
|
player.rightClickAbility,
|
|
|
|
player.ability1,
|
|
|
|
player.ability2,
|
|
|
|
player.ability3
|
|
|
|
};
|
|
|
|
std::vector<Ability>activeCooldowns;
|
|
|
|
std::copy_if(cooldowns.begin(),cooldowns.end(),std::back_inserter(activeCooldowns),[](Ability a){
|
|
|
|
return a.cooldown>0;
|
|
|
|
});
|
|
|
|
std::sort(activeCooldowns.begin(),activeCooldowns.end(),[](Ability&a1,Ability&a2){
|
|
|
|
return a1.cooldown<a2.cooldown;
|
|
|
|
});
|
|
|
|
int offset=6*activeCooldowns.size();
|
|
|
|
for(Ability&a:activeCooldowns){
|
|
|
|
if(a.cooldown>0){
|
|
|
|
FillRectDecal(vf2d{10,ScreenHeight()-22.f}-vf2d{0,float(offset)},{64,6},BLACK);
|
|
|
|
FillRectDecal(vf2d{11,ScreenHeight()-21.f}-vf2d{0,float(offset)},{62,4},DARK_GREY);
|
|
|
|
GradientFillRectDecal(vf2d{10,ScreenHeight()-22.f}-vf2d{0,float(offset)},{(a.cooldown/a.COOLDOWN_TIME)*64,6},a.barColor1,a.barColor1,a.barColor2,a.barColor2);
|
|
|
|
DrawRotatedShadowStringPropDecal(vf2d{8,ScreenHeight()-20.f}+vf2d{1,1}-vf2d{0,float(offset)},capitalize(a.name),-PI/64,{0,0},WHITE,BLACK,{0.4,0.4},0.5);
|
|
|
|
std::stringstream cooldownTimeDisplay;
|
|
|
|
cooldownTimeDisplay<<std::fixed<<std::setprecision(1)<<a.cooldown;
|
|
|
|
DrawShadowStringPropDecal(vf2d{74,ScreenHeight()-22.f+1}-vf2d{float(GetTextSizeProp(cooldownTimeDisplay.str()).x*0.5),float(offset)},cooldownTimeDisplay.str(),WHITE,BLACK,{0.5,0.5});
|
|
|
|
}
|
|
|
|
offset-=6;
|
|
|
|
}
|
|
|
|
DrawDecal({2,2},GFX_Heart.Decal());
|
|
|
|
DrawDecal({2,20},GFX_Mana.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});
|
|
|
|
DrawShadowStringPropDecal({24,23},text_mana,{192,192,255},BLACK,{1.5,1.5});
|
|
|
|
if(player.notEnoughManaDisplay.second>0){
|
|
|
|
std::string displayText="Not enough mana for "+player.notEnoughManaDisplay.first+"!";
|
|
|
|
DrawShadowStringPropDecal(vf2d{float(ScreenWidth()/2),float(ScreenHeight()/4)}-GetTextSizeProp(displayText)/2,displayText,DARK_RED,VERY_DARK_RED);
|
|
|
|
}
|
|
|
|
if(player.notificationDisplay.second>0){
|
|
|
|
std::string displayText=player.notificationDisplay.first;
|
|
|
|
DrawShadowStringPropDecal(vf2d{float(ScreenWidth()/2),float(ScreenHeight()/4)-24}-GetTextSizeProp(displayText)/2,displayText,BLUE,VERY_DARK_BLUE);
|
|
|
|
}
|
|
|
|
std::string versionStr("v" + std::to_string(VERSION_MAJOR) + "." + std::to_string(VERSION_MINOR) + "." + std::to_string(VERSION_PATCH) + "." + std::to_string(VERSION_BUILD));
|
|
|
|
DrawShadowStringDecal(vf2d{ GetScreenSize() } - vf2d{ GetTextSize(versionStr) }*0.4,versionStr,WHITE,BLACK,{0.4,0.4},0.4);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Crawler::AddEffect(Effect foreground,Effect background){
|
|
|
|
foregroundEffects.push_back(foreground);
|
|
|
|
backgroundEffects.push_back(background);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Crawler::AddEffect(Effect foreground,bool back){
|
|
|
|
if(back){
|
|
|
|
backgroundEffects.push_back(foreground);
|
|
|
|
} else {
|
|
|
|
foregroundEffects.push_back(foreground);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
vf2d Crawler::GetWorldMousePos(){
|
|
|
|
return GetMousePos()+view.GetWorldOffset();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Crawler::SetupWorldShake(float duration){
|
|
|
|
worldShakeTime=duration;
|
|
|
|
worldShake=player.GetPos();
|
|
|
|
camera.SetTarget(worldShake);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Crawler::InitializeLevel(std::string mapFile,MapName map){
|
|
|
|
TMXParser level(mapFile);
|
|
|
|
size_t slashMarker = mapFile.find_last_of('/');
|
|
|
|
std::string baseDir=mapFile.substr(0,slashMarker+1);
|
|
|
|
MAP_DATA[map]=level.GetData();
|
|
|
|
for(XMLTag&tag:MAP_DATA[map].TilesetData){
|
|
|
|
size_t slashMarkerSourceDir = tag.data["source"].find_last_of('/');
|
|
|
|
std::string baseSourceDir=tag.data["source"].substr(slashMarkerSourceDir+1);
|
|
|
|
if(MAP_TILESETS.find("assets/maps/"+baseSourceDir)==MAP_TILESETS.end()){
|
|
|
|
TSXParser tileset(baseDir+tag.data["source"]);
|
|
|
|
Renderable*r=new Renderable();
|
|
|
|
MAP_TILESETS["assets/maps/"+baseSourceDir].tileset=r;
|
|
|
|
MAP_TILESETS["assets/maps/"+baseSourceDir].foregroundTiles=tileset.GetData().ForegroundTileData;
|
|
|
|
MAP_TILESETS["assets/maps/"+baseSourceDir].collision=tileset.GetData().CollisionData;
|
|
|
|
r->Load("assets/maps/"+tileset.GetData().ImageData.data["source"]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Crawler::LoadLevel(MapName map){
|
|
|
|
SPAWNER_LIST.clear();
|
|
|
|
foregroundTileGroups.clear();
|
|
|
|
currentLevel=map;
|
|
|
|
WORLD_SIZE={MAP_DATA[map].MapData.width,MAP_DATA[map].MapData.height};
|
|
|
|
for(SpawnerTag&spawner:MAP_DATA[map].SpawnerData){
|
|
|
|
std::vector<std::pair<MonsterName,vf2d>>monster_list;
|
|
|
|
vf2d spawnerRadius=vf2d{spawner.ObjectData.GetFloat("width"),spawner.ObjectData.GetFloat("height")}/2;
|
|
|
|
for(XMLTag&property:spawner.properties){
|
|
|
|
int monsterTypeID=property.GetInteger("value")-1;
|
|
|
|
if(monsterTypeID>=0&&monsterTypeID<MonsterName::END){
|
|
|
|
monster_list.push_back({MonsterName(monsterTypeID),{rand()%int(spawnerRadius.x)-spawnerRadius.x/2,rand()%int(spawnerRadius.y)-spawnerRadius.y/2}});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
SPAWNER_LIST.push_back(MonsterSpawner{{spawner.ObjectData.GetFloat("x")+spawnerRadius.x,spawner.ObjectData.GetFloat("y")+spawnerRadius.y},spawnerRadius,monster_list});
|
|
|
|
}
|
|
|
|
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;
|
|
|
|
if(IsForegroundTile(tileSheet,tileSheetIndex)){
|
|
|
|
TileRenderData tile={tileSheet.tileset.tileset->Decal(),vi2d{x,y}*24,vi2d{tileSheetX,tileSheetY}*24};
|
|
|
|
bool foundGroup=false;
|
|
|
|
for(TileGroup&group:foregroundTileGroups){
|
|
|
|
if(geom2d::overlaps(geom2d::rect<int>{vi2d{x,y}*24-vi2d{1,1},{26,26}},group.GetRange())){
|
|
|
|
group.InsertTile(tile);
|
|
|
|
foundGroup=true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(!foundGroup){
|
|
|
|
TileGroup group;
|
|
|
|
group.InsertTile(tile);
|
|
|
|
foregroundTileGroups.push_back(group);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
player.SetPos(MAP_DATA[map].MapData.playerSpawnLocation);
|
|
|
|
player.path.Initialize();
|
|
|
|
}
|
|
|
|
|
|
|
|
vi2d Crawler::GetWorldSize(){
|
|
|
|
return WORLD_SIZE;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Crawler::IsForegroundTile(TilesheetData sheet,int tileID){
|
|
|
|
return sheet.tileset.foregroundTiles.find(tileID)!=sheet.tileset.foregroundTiles.end();
|
|
|
|
}
|
|
|
|
|
|
|
|
TilesheetData Crawler::GetTileSheet(MapName map,int tileID){
|
|
|
|
std::vector<XMLTag>&tileData=MAP_DATA[map].TilesetData;
|
|
|
|
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};
|
|
|
|
} else {
|
|
|
|
for (int i=1;i<tileData.size();i++){
|
|
|
|
if(tileID<stoi(tileData[i].data["firstgid"])){
|
|
|
|
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"])};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
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"])};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Crawler::HasTileCollision(MapName map,vf2d pos){
|
|
|
|
geom2d::rect<int>collisionRect=GetTileCollision(map,pos);
|
|
|
|
vi2d collisionRectSnapPos=vi2d{pos/24}*24;
|
|
|
|
collisionRect.pos+=collisionRectSnapPos;
|
|
|
|
return geom2d::overlaps(collisionRect,pos);
|
|
|
|
}
|
|
|
|
|
|
|
|
geom2d::rect<int>Crawler::GetTileCollision(MapName map,vf2d pos){
|
|
|
|
for(LayerTag&layer:MAP_DATA[map].LayerData){
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NO_COLLISION;
|
|
|
|
}
|
|
|
|
|
|
|
|
MapName Crawler::GetCurrentLevel(){
|
|
|
|
return currentLevel;
|
|
|
|
}
|
|
|
|
|
|
|
|
int main()
|
|
|
|
{
|
|
|
|
Crawler demo;
|
|
|
|
if (demo.Construct(WINDOW_SIZE.x, WINDOW_SIZE.y, 4, 4))
|
|
|
|
demo.Start();
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|