# 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 ;
Crawler * game ;
Crawler : : Crawler ( )
{
sAppName = " Crawler Concept " ;
game = this ;
}
bool Crawler : : OnUserCreate ( ) {
InitializeLevel ( " assets/Campaigns/1_1.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 ) {
fElapsedTime = std : : min ( 1 / 60.f , 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 } ) {
auto GetPlayerStaircaseDirection = [ & ] ( ) {
for ( LayerTag & layer : MAP_DATA [ GetCurrentLevel ( ) ] . LayerData ) {
int truncatedPlayerX = int ( player . GetX ( ) ) / 24 ;
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 " ] ;
}
}
return std : : string ( " NONE " ) ;
} ;
std : : string staircaseDirection = GetPlayerStaircaseDirection ( ) ;
if ( RightHeld ( ) ) {
player . SetX ( player . GetX ( ) + fElapsedTime * 100 * player . GetMoveSpdMult ( ) ) ;
if ( staircaseDirection = = " RIGHT " ) {
player . SetY ( player . GetY ( ) - 60 * fElapsedTime * player . GetMoveSpdMult ( ) ) ;
} else
if ( staircaseDirection = = " LEFT " ) {
player . SetY ( player . GetY ( ) + 60 * fElapsedTime * 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 ( staircaseDirection = = " RIGHT " ) {
player . SetY ( player . GetY ( ) + 60 * fElapsedTime * player . GetMoveSpdMult ( ) ) ;
} else
if ( staircaseDirection = = " LEFT " ) {
player . SetY ( player . GetY ( ) - 60 * fElapsedTime * 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 ) ;
}
}
}
}
void Crawler : : UpdateCamera ( float fElapsedTime ) {
lastWorldShakeAdjust = std : : max ( 0.f , lastWorldShakeAdjust - fElapsedTime ) ;
if ( worldShakeTime - fElapsedTime > 0 ) {
if ( lastWorldShakeAdjust = = 0 ) {
lastWorldShakeAdjust = util : : random ( 0.04 ) + 0.01 ;
worldShakeVel = { util : : random ( 200 ) + 100 , util : : random ( 200 ) + 100 } ;
if ( rand ( ) % 2 = = 0 ) {
worldShakeVel . x * = - 1 ;
}
if ( rand ( ) % 2 = = 0 ) {
worldShakeVel . y * = - 1 ;
}
}
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 ) {
if ( b - > friendly ) {
for ( Monster & m : MONSTER_LIST ) {
if ( b - > OnUpperLevel ( ) = = m . OnUpperLevel ( ) & & 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 = BULLET_LIST . erase ( it ) ;
if ( it = = BULLET_LIST . end ( ) ) {
goto outsidePlayerBulletLoop ;
}
}
goto continuePlayerBulletLoop ;
}
b - > hitList [ & m ] = true ;
}
}
}
} else {
if ( b - > OnUpperLevel ( ) = = player . OnUpperLevel ( ) & & 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 ) ;
continuePlayerBulletLoop :
continue ;
}
outsidePlayerBulletLoop :
int a ;
}
void Crawler : : HurtEnemies ( vf2d pos , float radius , int damage , bool upperLevel ) {
for ( Monster & m : MONSTER_LIST ) {
if ( m . OnUpperLevel ( ) = = upperLevel & & geom2d : : overlaps ( geom2d : : circle ( pos , radius ) , geom2d : : circle ( m . GetPos ( ) , 12 * m . GetSizeMult ( ) ) ) ) {
m . Hurt ( damage ) ;
}
}
}
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 ) {
Player & pl = player ;
for ( auto it = MONSTER_LIST . begin ( ) ; it ! = MONSTER_LIST . end ( ) ; + + it ) {
Monster & m = * it ;
if ( m . GetPos ( ) . y < pl . GetPos ( ) . y ) { //This monster renders before the player does (behind the player)
if ( m . OnUpperLevel ( ) ) {
monstersBeforeUpper . push_back ( & m ) ;
} else {
monstersBeforeLower . push_back ( & m ) ;
}
} else { //This monster renders after the player does (in front of the player)
if ( m . OnUpperLevel ( ) ) {
monstersAfterUpper . push_back ( & m ) ;
} else {
monstersAfterLower . push_back ( & m ) ;
}
}
}
for ( auto it = BULLET_LIST . begin ( ) ; it ! = BULLET_LIST . end ( ) ; + + it ) {
Bullet * b = ( * it ) . get ( ) ;
if ( b - > OnUpperLevel ( ) ) {
bulletsUpper . push_back ( b ) ;
} else {
bulletsLower . push_back ( b ) ;
}
}
for ( auto it = foregroundEffects . begin ( ) ; it ! = foregroundEffects . end ( ) ; + + it ) {
Effect & e = * it ;
if ( e . OnUpperLevel ( ) ) {
foregroundEffectsUpper . push_back ( & e ) ;
} else {
foregroundEffectsLower . push_back ( & e ) ;
}
}
for ( auto it = backgroundEffects . begin ( ) ; it ! = backgroundEffects . end ( ) ; + + it ) {
Effect & e = * it ;
if ( e . OnUpperLevel ( ) ) {
backgroundEffectsUpper . push_back ( & e ) ;
} else {
backgroundEffectsLower . push_back ( & e ) ;
}
}
std : : sort ( monstersBeforeUpper . begin ( ) , monstersBeforeUpper . end ( ) , [ ] ( Monster * m1 , Monster * m2 ) { return m1 - > GetPos ( ) . y < m2 - > GetPos ( ) . y ; } ) ;
std : : sort ( monstersBeforeLower . begin ( ) , monstersBeforeLower . end ( ) , [ ] ( Monster * m1 , Monster * m2 ) { return m1 - > GetPos ( ) . y < m2 - > GetPos ( ) . y ; } ) ;
std : : sort ( monstersAfterUpper . begin ( ) , monstersAfterUpper . end ( ) , [ ] ( Monster * m1 , Monster * m2 ) { return m1 - > GetPos ( ) . y < m2 - > GetPos ( ) . y ; } ) ;
std : : sort ( monstersAfterLower . begin ( ) , monstersAfterLower . end ( ) , [ ] ( Monster * m1 , Monster * m2 ) { return m1 - > GetPos ( ) . y < m2 - > GetPos ( ) . y ; } ) ;
}
void Crawler : : RenderWorld ( float fElapsedTime ) {
Clear ( { 100 , 180 , 100 } ) ;
LayerTag * bridgeLayer = nullptr ;
bool bridgeLayerFade = false ;
# pragma region Basic Tile Layer Rendering
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 ) {
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 ) {
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 ( 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 ) ;
}
}
}
}
}
}
# 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 = player ;
PopulateRenderLists ( monstersBeforeLower , monstersBeforeUpper , monstersAfterLower , monstersAfterUpper , bulletsLower , bulletsUpper , backgroundEffectsLower , backgroundEffectsUpper , foregroundEffectsLower , foregroundEffectsUpper ) ;
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 : backgroundEffectsLower ) {
e - > Draw ( ) ;
}
for ( Monster * m : monstersBeforeLower ) {
m - > Draw ( ) ;
}
vf2d playerScale = vf2d ( player . GetSizeMult ( ) , player . GetSizeMult ( ) ) ;
vf2d playerPosition = player . GetPos ( ) ;
# define RENDER_PLAYER \
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 ) {
RENDER_PLAYER
}
if ( player . GetState ( ) = = State : : BLOCK ) {
view . DrawDecal ( player . GetPos ( ) - vf2d { 12 , 12 } , GFX_BLOCK_BUBBLE . Decal ( ) ) ;
}
for ( Monster * m : monstersAfterLower ) {
m - > Draw ( ) ;
}
for ( Effect * e : foregroundEffectsLower ) {
e - > Draw ( ) ;
}
for ( Bullet * b : bulletsLower ) {
b - > Draw ( ) ;
}
# pragma region Foreground Rendering
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 ) } ) ;
}
}
}
# pragma endregion
# pragma region Bridge Layer Rendering
if ( bridgeLayer ! = nullptr ) {
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 ) {
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 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 ( bridgeLayerFade ? 128 : 255 ) } ) ;
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 ) ;
}
}
}
}
}
}
# pragma endregion
for ( Effect * e : backgroundEffectsUpper ) {
e - > Draw ( ) ;
}
for ( Monster * m : monstersBeforeUpper ) {
m - > Draw ( ) ;
}
if ( player . upperLevel ) {
RENDER_PLAYER
}
for ( Monster * m : monstersAfterUpper ) {
m - > Draw ( ) ;
}
for ( Effect * e : foregroundEffectsUpper ) {
e - > Draw ( ) ;
}
for ( Bullet * b : bulletsUpper ) {
b - > Draw ( ) ;
}
# pragma region Upper Foreground Rendering
for ( TileGroup & group : upperForegroundTileGroups ) {
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 ) } ) ;
}
}
}
# pragma endregion
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 ] . upperForegroundTiles = tileset . GetData ( ) . UpperForegroundTileData ;
MAP_TILESETS [ " assets/maps/ " + baseSourceDir ] . collision = tileset . GetData ( ) . CollisionData ;
MAP_TILESETS [ " assets/maps/ " + baseSourceDir ] . staircaseTiles = tileset . GetData ( ) . StaircaseData ;
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 ( auto key : MAP_DATA [ map ] . SpawnerData ) {
SpawnerTag & spawnData = MAP_DATA [ map ] . SpawnerData [ key . first ] ;
std : : vector < std : : pair < MonsterName , 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 ;
if ( monsterTypeID > = 0 & & monsterTypeID < MonsterName : : END ) {
monster_list . push_back ( { MonsterName ( 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 } ) ;
}
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 GroupForegroundTilesTogether = [ & ] ( std : : vector < TileGroup > & vec ) {
TileRenderData tile = { tileSheet . tileset . tileset - > Decal ( ) , vi2d { x , y } * 24 , vi2d { tileSheetX , tileSheetY } * 24 } ;
bool foundGroup = false ;
for ( TileGroup & group : vec ) {
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 ) ;
vec . push_back ( group ) ;
}
} ;
if ( IsForegroundTile ( tileSheet , tileSheetIndex ) ) {
GroupForegroundTilesTogether ( foregroundTileGroups ) ;
} else
if ( IsUpperForegroundTile ( tileSheet , tileSheetIndex ) ) {
GroupForegroundTilesTogether ( upperForegroundTileGroups ) ;
}
# pragma endregion
}
}
}
}
int counter = 0 ;
bridgeLayerIndex = - 1 ;
for ( LayerTag & layer : MAP_DATA [ map ] . LayerData ) {
if ( IsBridgeLayer ( layer ) ) {
bridgeLayerIndex = counter ;
}
counter + + ;
}
player . upperLevel = false ; //Assume player starts on lower level.
player . SetPos ( MAP_DATA [ map ] . MapData . playerSpawnLocation ) ;
player . path . Initialize ( ) ;
}
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 : : 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 , bool upperLevel ) {
geom2d : : rect < int > collisionRect = GetTileCollision ( map , pos , upperLevel ) ;
vi2d collisionRectSnapPos = vi2d { pos / 24 } * 24 ;
collisionRect . pos + = collisionRectSnapPos ;
return geom2d : : overlaps ( collisionRect , pos ) ;
}
bool Crawler : : IsBridgeLayer ( LayerTag & layer ) {
return layer . tag . data . find ( " class " ) ! = layer . tag . data . end ( ) & & layer . tag . data [ " class " ] = = " Bridge " ;
}
geom2d : : rect < int > Crawler : : GetTileCollision ( MapName map , vf2d pos , bool upperLevel ) {
if ( pos . x < 0 | | pos . y < 0 | | pos . x > = WORLD_SIZE . x * 24 | | pos . y > = WORLD_SIZE . y * 24 ) return NO_COLLISION ;
# pragma region Lower Bridge Collision Check
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 } } ;
}
}
}
# pragma endregion
//The logic here is, if there's a tile on the bridge, we respect that tile instead if we're on the upper level. So we don't check other layers when we are on the upper level and there is a tile below us.
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 ;
}
return NO_COLLISION ;
}
}
int counter = 0 ;
for ( LayerTag & layer : MAP_DATA [ map ] . LayerData ) {
auto HasNoClass = [ & ] ( ) { return layer . tag . data . find ( " class " ) = = layer . tag . data . end ( ) ; } ;
if ( HasNoClass ( ) & & 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 ;
}
}
counter + + ;
}
return NO_COLLISION ;
}
MapName Crawler : : GetCurrentLevel ( ) {
return currentLevel ;
}
std : : map < std : : string , std : : vector < geom2d : : rect < int > > > & Crawler : : GetZoneData ( MapName map ) {
return MAP_DATA [ map ] . ZoneData ;
}
int main ( )
{
Crawler demo ;
if ( demo . Construct ( WINDOW_SIZE . x , WINDOW_SIZE . y , 4 , 4 ) )
demo . Start ( ) ;
return 0 ;
}