2023-06-11 22:57:43 -05:00
# include "olcPGEX_TransformedView.h"
# include "Crawler.h"
# include "olcUTIL_Camera2D.h"
2023-06-12 00:37:55 -05:00
# include "DamageNumber.h"
2023-06-16 01:41:38 -05:00
# include "Bullet.h"
2023-06-17 21:19:08 -05:00
# include "Ability.h"
2023-06-17 22:03:20 -05:00
# include "Class.h"
2023-06-18 02:05:50 -07:00
# include "Version.h"
2023-06-21 00:34:09 -07:00
# include "TMXParser.h"
2023-06-22 01:30:26 -07:00
# include "TSXParser.h"
2023-06-23 20:42:55 -07:00
# include "Map.h"
2023-06-15 04:53:57 -05:00
# include "DEFINES.h"
2023-07-06 18:03:35 +00:00
# include "utils.h"
2023-07-10 18:48:57 -05:00
# include <set>
# include <queue>
2023-07-12 00:23:36 -05:00
# include "Emitter.h"
2023-07-26 21:08:17 +00:00
# include "config.h"
2023-08-06 19:00:09 -05:00
# include "safemap.h"
2023-06-11 22:57:43 -05:00
2023-07-12 00:23:36 -05:00
INCLUDE_EMITTER_LIST
2023-07-02 08:42:18 -07:00
2023-06-11 22:57:43 -05:00
//192x192
2023-07-26 18:08:06 +00:00
vi2d WINDOW_SIZE = { 24 * 15 , 24 * 10 } ;
2023-08-06 19:00:09 -05:00
safemap < std : : string , Animate2D : : FrameSequence > ANIMATION_DATA ;
2023-06-11 22:57:43 -05:00
std : : vector < Monster > MONSTER_LIST ;
std : : vector < MonsterSpawner > SPAWNER_LIST ;
2023-07-25 19:48:24 -05:00
std : : vector < std : : shared_ptr < DamageNumber > > DAMAGENUMBER_LIST ;
2023-06-30 15:44:41 -07:00
std : : vector < std : : unique_ptr < Bullet > > BULLET_LIST ;
2023-07-26 18:08:06 +00:00
utils : : datafile DATA ;
2023-06-11 22:57:43 -05:00
Crawler * game ;
2023-07-21 18:47:45 +00:00
Key Crawler : : KEY_ABILITY1 = Q ;
Key Crawler : : KEY_ABILITY2 = E ;
Key Crawler : : KEY_ABILITY3 = R ;
Key Crawler : : KEY_ABILITY4 = F ;
2023-06-11 22:57:43 -05:00
Crawler : : Crawler ( )
{
sAppName = " Crawler Concept " ;
game = this ;
2023-07-05 21:14:36 +00:00
2023-07-26 01:58:00 -05:00
utils : : datafile : : Read ( DATA , " assets/config/configuration.txt " ) ;
2023-07-26 19:53:34 +00:00
std : : string CONFIG_PATH = " config_path " _S ;
2023-07-26 01:58:00 -05:00
2023-07-26 19:53:34 +00:00
std : : string GFX_CONFIG = CONFIG_PATH + " gfx_config " _S ;
2023-07-26 01:58:00 -05:00
utils : : datafile : : Read ( DATA , GFX_CONFIG ) ;
2023-07-26 19:53:34 +00:00
WINDOW_SIZE = { " WINDOW_SIZE " _i [ 0 ] , " WINDOW_SIZE " _i [ 1 ] } ;
2023-07-26 20:37:52 +00:00
std : : string MAP_CONFIG = CONFIG_PATH + " map_config " _S ;
utils : : datafile : : Read ( DATA , MAP_CONFIG ) ;
2023-07-26 21:08:17 +00:00
2023-08-06 15:20:54 -05:00
std : : string PLAYER_CONFIG = CONFIG_PATH + " player_config " _S ;
utils : : datafile : : Read ( DATA , PLAYER_CONFIG ) ;
2023-08-06 19:00:09 -05:00
std : : string MONSTERS_CONFIG = CONFIG_PATH + " monsters_config " _S ;
utils : : datafile : : Read ( DATA , MONSTERS_CONFIG ) ;
std : : string MONSTERSTRATEGIES_CONFIG = CONFIG_PATH + " monsterstrategies_config " _S ;
utils : : datafile : : Read ( DATA , MONSTERSTRATEGIES_CONFIG ) ;
2023-07-26 21:08:17 +00:00
for ( std : : string & cl : DATA . GetProperty ( " class_list " ) . GetValues ( ) ) {
std : : cout < < cl < < std : : endl ;
utils : : datafile : : Read ( DATA , CONFIG_PATH + " class_directory " _S + cl + " .txt " ) ;
}
2023-07-28 04:41:18 -05:00
utils : : datafile : : DEBUG_ACCESS_OPTIONS = " debug_access_options " _I ;
2023-07-26 18:08:06 +00:00
}
2023-07-26 01:58:00 -05:00
2023-07-26 18:08:06 +00:00
bool Crawler : : OnUserCreate ( ) {
2023-07-26 20:37:52 +00:00
# define INITLEVEL(map) InitializeLevel("map_path"_S + "Levels."#map ## _S,map);
INITLEVEL ( WORLD_MAP ) ;
INITLEVEL ( CAMPAIGN_1_1 ) ;
INITLEVEL ( BOSS_1 ) ;
INITLEVEL ( CAMPAIGN_1_2 ) ;
2023-07-07 19:48:45 +00:00
2023-07-14 15:44:17 +00:00
player = std : : make_unique < Warrior > ( ) ;
2023-07-02 08:42:18 -07:00
2023-06-11 22:57:43 -05:00
//Initialize Camera.
camera = Camera2D { WINDOW_SIZE } ;
camera . SetMode ( olc : : utils : : Camera2D : : Mode : : LazyFollow ) ;
2023-07-13 20:24:47 +00:00
camera . SetTarget ( player - > GetPos ( ) ) ;
2023-06-11 22:57:43 -05:00
camera . SetWorldBoundary ( { 0 , 0 } , WORLD_SIZE * 24 ) ;
2023-06-16 01:10:40 -05:00
camera . EnableWorldBoundary ( false ) ;
2023-06-11 22:57:43 -05:00
2023-07-26 01:58:00 -05:00
# undef LoadImage //Dumb Windows.
auto LoadImage = [ & ] ( Renderable & r , std : : string key ) {
r . Load ( GetString ( " GFX_Prefix " ) + GetString ( key ) ) ;
} ;
# define LOADIMG(name) LoadImage(name,"Images."#name);
2023-06-11 22:57:43 -05:00
//Graphics
2023-07-26 01:58:00 -05:00
LOADIMG ( GFX_Warrior_Sheet )
LOADIMG ( GFX_Circle )
LOADIMG ( GFX_Effect_GroundSlam_Back )
LOADIMG ( GFX_Effect_GroundSlam_Front )
LOADIMG ( GFX_Heart )
LOADIMG ( GFX_BLOCK_BUBBLE )
LOADIMG ( GFX_Ranger_Sheet )
LOADIMG ( GFX_Wizard_Sheet )
LOADIMG ( GFX_Battlecry_Effect )
LOADIMG ( GFX_Mana )
LOADIMG ( GFX_SonicSlash )
LOADIMG ( GFX_BulletCircle )
LOADIMG ( GFX_BulletCircleOutline )
LOADIMG ( GFX_EnergyBolt )
LOADIMG ( GFX_EnergyParticle )
LOADIMG ( GFX_Splash_Effect )
LOADIMG ( GFX_LightningBolt )
LOADIMG ( GFX_LightningBoltParticle1 )
LOADIMG ( GFX_LightningBoltParticle2 )
LOADIMG ( GFX_LightningBoltParticle3 )
LOADIMG ( GFX_LightningBoltParticle4 )
LOADIMG ( GFX_ChainLightning )
LOADIMG ( GFX_LightningSplash )
LOADIMG ( GFX_Meteor )
LOADIMG ( GFX_Arrow )
LOADIMG ( GFX_Laser )
LOADIMG ( GFX_ChargedArrow )
2023-06-11 22:57:43 -05:00
2023-08-06 19:00:09 -05:00
Monster : : InitializeStrategies ( ) ;
2023-06-11 22:57:43 -05:00
//Animations
2023-07-12 00:23:36 -05:00
sig : : Animation : : InitializeAnimations ( ) ;
2023-08-06 19:00:09 -05:00
MonsterData : : InitializeMonsterData ( ) ;
2023-06-11 22:57:43 -05:00
2023-07-12 00:23:36 -05:00
sig : : Animation : : SetupPlayerAnimations ( ) ;
2023-06-11 22:57:43 -05:00
view = TileTransformedView { GetScreenSize ( ) , { 1 , 1 } } ;
2023-06-22 22:09:11 -07:00
LoadLevel ( CAMPAIGN_1_1 ) ;
2023-07-26 21:08:17 +00:00
InitializeClasses ( ) ;
2023-07-14 19:14:04 +00:00
ChangePlayerClass ( WARRIOR ) ;
2023-07-25 17:34:53 -05:00
Warrior : : ability4 = Ranger : : ability1 ; //Class ability swapping demonstration.
2023-07-05 04:31:31 -05:00
2023-06-11 22:57:43 -05:00
return true ;
}
bool Crawler : : OnUserUpdate ( float fElapsedTime ) {
2023-07-23 12:33:20 -05:00
fElapsedTime = std : : clamp ( fElapsedTime , 0.f , 1 / 60.f ) ;
2023-06-11 22:57:43 -05:00
HandleUserInput ( fElapsedTime ) ;
2023-06-15 00:11:39 -05:00
UpdateEffects ( fElapsedTime ) ;
2023-07-13 20:24:47 +00:00
player - > Update ( fElapsedTime ) ;
2023-06-11 22:57:43 -05:00
for ( Monster & m : MONSTER_LIST ) {
m . Update ( fElapsedTime ) ;
}
2023-06-16 01:41:38 -05:00
UpdateBullets ( fElapsedTime ) ;
2023-06-11 22:57:43 -05:00
UpdateCamera ( fElapsedTime ) ;
2023-06-12 00:37:55 -05:00
RenderWorld ( fElapsedTime ) ;
2023-06-15 00:47:11 -05:00
RenderHud ( ) ;
2023-06-11 22:57:43 -05:00
return true ;
}
2023-06-15 05:06:50 -05:00
bool Crawler : : LeftHeld ( ) {
2023-06-24 01:18:21 -07:00
return GetKey ( LEFT ) . bHeld | | GetKey ( A ) . bHeld ;
2023-06-15 05:06:50 -05:00
}
bool Crawler : : RightHeld ( ) {
2023-06-24 01:18:21 -07:00
return GetKey ( RIGHT ) . bHeld | | GetKey ( D ) . bHeld ;
2023-06-15 05:06:50 -05:00
}
bool Crawler : : UpHeld ( ) {
2023-06-24 01:18:21 -07:00
return GetKey ( UP ) . bHeld | | GetKey ( W ) . bHeld ;
2023-06-15 05:06:50 -05:00
}
bool Crawler : : DownHeld ( ) {
2023-06-24 01:18:21 -07:00
return GetKey ( DOWN ) . bHeld | | GetKey ( S ) . bHeld ;
2023-06-15 05:06:50 -05:00
}
bool Crawler : : LeftReleased ( ) {
2023-06-24 01:18:21 -07:00
return GetKey ( LEFT ) . bReleased | | GetKey ( A ) . bReleased ;
2023-06-15 05:06:50 -05:00
}
bool Crawler : : RightReleased ( ) {
2023-06-24 01:18:21 -07:00
return GetKey ( RIGHT ) . bReleased | | GetKey ( D ) . bReleased ;
2023-06-15 05:06:50 -05:00
}
bool Crawler : : UpReleased ( ) {
2023-06-24 01:18:21 -07:00
return GetKey ( UP ) . bReleased | | GetKey ( W ) . bReleased ;
2023-06-15 05:06:50 -05:00
}
bool Crawler : : DownReleased ( ) {
2023-06-24 01:18:21 -07:00
return GetKey ( DOWN ) . bReleased | | GetKey ( S ) . bReleased ;
2023-06-15 05:06:50 -05:00
}
2023-06-11 22:57:43 -05:00
void Crawler : : HandleUserInput ( float fElapsedTime ) {
bool setIdleAnimation = true ;
2023-07-05 21:14:36 +00:00
if ( GetKey ( F1 ) . bPressed ) {
ConsoleShow ( F1 ) ;
}
2023-06-17 23:07:26 -05:00
if ( GetMouseWheel ( ) > 0 ) {
2023-07-13 20:24:47 +00:00
switch ( player - > GetClass ( ) ) {
2023-06-17 23:07:26 -05:00
case WARRIOR : {
2023-07-14 15:44:17 +00:00
ChangePlayerClass ( RANGER ) ;
2023-06-17 23:07:26 -05:00
} break ;
case RANGER : {
2023-07-14 15:44:17 +00:00
ChangePlayerClass ( WIZARD ) ;
2023-06-17 23:07:26 -05:00
} break ;
case WIZARD : {
2023-07-14 15:44:17 +00:00
ChangePlayerClass ( WARRIOR ) ;
2023-06-17 23:07:26 -05:00
} break ;
}
}
if ( GetMouseWheel ( ) < 0 ) {
2023-07-13 20:24:47 +00:00
switch ( player - > GetClass ( ) ) {
2023-06-17 23:07:26 -05:00
case WARRIOR : {
2023-07-14 15:44:17 +00:00
ChangePlayerClass ( WIZARD ) ;
2023-06-17 23:07:26 -05:00
} break ;
case RANGER : {
2023-07-14 15:44:17 +00:00
ChangePlayerClass ( WARRIOR ) ;
2023-06-17 23:07:26 -05:00
} break ;
case WIZARD : {
2023-07-14 15:44:17 +00:00
ChangePlayerClass ( RANGER ) ;
2023-06-17 23:07:26 -05:00
} break ;
}
}
2023-07-13 20:24:47 +00:00
if ( player - > GetVelocity ( ) = = vf2d { 0 , 0 } & & player - > CanMove ( ) ) {
2023-07-06 15:07:44 -05:00
auto GetPlayerStaircaseDirection = [ & ] ( ) {
for ( LayerTag & layer : MAP_DATA [ GetCurrentLevel ( ) ] . LayerData ) {
2023-07-13 20:24:47 +00:00
int truncatedPlayerX = int ( player - > GetX ( ) ) / 24 ;
int truncatedPlayerY = int ( player - > GetY ( ) ) / 24 ;
2023-07-06 15:07:44 -05:00
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 ( ) ;
2023-06-15 23:44:34 -05:00
if ( RightHeld ( ) ) {
2023-08-06 15:20:54 -05:00
player - > SetX ( player - > GetX ( ) + fElapsedTime * " Player.MoveSpd " _F * player - > GetMoveSpdMult ( ) ) ;
player - > movementVelocity . x = " Player.MoveSpd " _F ;
2023-07-06 15:07:44 -05:00
if ( staircaseDirection = = " RIGHT " ) {
2023-08-06 15:20:54 -05:00
player - > SetY ( player - > GetY ( ) - " Player.StaircaseClimbSpd " _F * fElapsedTime * player - > GetMoveSpdMult ( ) ) ;
player - > movementVelocity . y = - " Player.StaircaseClimbSpd " _F ;
2023-07-06 15:07:44 -05:00
} else
2023-08-06 15:20:54 -05:00
if ( staircaseDirection = = " LEFT " ) {
player - > SetY ( player - > GetY ( ) + " Player.StaircaseClimbSpd " _F * fElapsedTime * player - > GetMoveSpdMult ( ) ) ;
player - > movementVelocity . y = " Player.StaircaseClimbSpd " _F ;
}
2023-07-13 20:24:47 +00:00
player - > SetFacingDirection ( RIGHT ) ;
2023-07-19 20:36:01 +00:00
if ( player - > GetState ( ) = = State : : NORMAL | | player - > GetState ( ) = = State : : PREP_CAST ) {
2023-07-13 20:24:47 +00:00
player - > UpdateWalkingAnimation ( RIGHT ) ;
2023-06-17 19:34:16 -05:00
}
2023-06-15 23:44:34 -05:00
setIdleAnimation = false ;
2023-06-11 22:57:43 -05:00
}
2023-06-15 23:44:34 -05:00
if ( LeftHeld ( ) ) {
2023-08-06 15:20:54 -05:00
player - > SetX ( player - > GetX ( ) - fElapsedTime * " Player.MoveSpd " _F * player - > GetMoveSpdMult ( ) ) ;
player - > movementVelocity . x = - " Player.MoveSpd " _F ;
2023-07-06 15:07:44 -05:00
if ( staircaseDirection = = " RIGHT " ) {
2023-08-06 15:20:54 -05:00
player - > SetY ( player - > GetY ( ) + " Player.StaircaseClimbSpd " _F * fElapsedTime * player - > GetMoveSpdMult ( ) ) ;
player - > movementVelocity . y = " Player.StaircaseClimbSpd " _F ;
2023-07-06 15:07:44 -05:00
} else
2023-08-06 15:20:54 -05:00
if ( staircaseDirection = = " LEFT " ) {
player - > SetY ( player - > GetY ( ) - " Player.StaircaseClimbSpd " _F * fElapsedTime * player - > GetMoveSpdMult ( ) ) ;
player - > movementVelocity . y = - " Player.StaircaseClimbSpd " _F ;
2023-07-06 15:07:44 -05:00
}
2023-06-15 23:44:34 -05:00
if ( setIdleAnimation ) {
2023-07-13 20:24:47 +00:00
player - > SetFacingDirection ( LEFT ) ;
2023-07-19 20:36:01 +00:00
if ( player - > GetState ( ) = = State : : NORMAL | | player - > GetState ( ) = = State : : PREP_CAST ) {
2023-07-13 20:24:47 +00:00
player - > UpdateWalkingAnimation ( LEFT ) ;
2023-06-17 19:34:16 -05:00
}
2023-06-15 23:44:34 -05:00
}
setIdleAnimation = false ;
2023-06-11 22:57:43 -05:00
}
2023-06-15 23:44:34 -05:00
if ( UpHeld ( ) ) {
2023-08-06 15:20:54 -05:00
player - > SetY ( player - > GetY ( ) - fElapsedTime * " Player.MoveSpd " _F * player - > GetMoveSpdMult ( ) ) ;
player - > movementVelocity . y = - " Player.MoveSpd " _F * fElapsedTime ;
2023-06-15 23:44:34 -05:00
if ( setIdleAnimation ) {
2023-07-13 20:24:47 +00:00
player - > SetFacingDirection ( UP ) ;
2023-07-19 20:36:01 +00:00
if ( player - > GetState ( ) = = State : : NORMAL | | player - > GetState ( ) = = State : : PREP_CAST ) {
2023-07-13 20:24:47 +00:00
player - > UpdateWalkingAnimation ( UP ) ;
2023-06-17 19:34:16 -05:00
}
2023-06-15 23:44:34 -05:00
}
setIdleAnimation = false ;
2023-06-11 22:57:43 -05:00
}
2023-06-15 23:44:34 -05:00
if ( DownHeld ( ) ) {
2023-08-06 15:20:54 -05:00
player - > SetY ( player - > GetY ( ) + fElapsedTime * " Player.MoveSpd " _F * player - > GetMoveSpdMult ( ) ) ;
player - > movementVelocity . y = " Player.MoveSpd " _F * fElapsedTime ;
2023-06-15 23:44:34 -05:00
if ( setIdleAnimation ) {
2023-07-13 20:24:47 +00:00
player - > SetFacingDirection ( DOWN ) ;
2023-07-19 20:36:01 +00:00
if ( player - > GetState ( ) = = State : : NORMAL | | player - > GetState ( ) = = State : : PREP_CAST ) {
2023-07-13 20:24:47 +00:00
player - > UpdateWalkingAnimation ( DOWN ) ;
2023-06-17 19:34:16 -05:00
}
2023-06-15 23:44:34 -05:00
}
setIdleAnimation = false ;
2023-06-11 22:57:43 -05:00
}
}
2023-06-15 05:06:50 -05:00
if ( UpReleased ( ) ) {
2023-07-13 20:24:47 +00:00
player - > SetLastReleasedMovementKey ( UP ) ;
2023-07-23 08:13:40 -05:00
player - > movementVelocity . y = 0 ;
2023-07-19 20:36:01 +00:00
if ( player - > GetState ( ) = = State : : NORMAL | | player - > GetState ( ) = = State : : PREP_CAST ) {
2023-06-17 19:34:16 -05:00
if ( RightHeld ( ) ) {
2023-07-13 20:24:47 +00:00
player - > UpdateWalkingAnimation ( RIGHT ) ;
2023-06-17 19:34:16 -05:00
} else
if ( DownHeld ( ) ) {
2023-07-13 20:24:47 +00:00
player - > UpdateWalkingAnimation ( DOWN ) ;
2023-06-17 19:34:16 -05:00
} else
if ( LeftHeld ( ) ) {
2023-07-13 20:24:47 +00:00
player - > UpdateWalkingAnimation ( LEFT ) ;
2023-06-17 19:34:16 -05:00
}
2023-06-15 05:06:50 -05:00
}
2023-06-11 22:57:43 -05:00
}
2023-06-15 05:06:50 -05:00
if ( RightReleased ( ) ) {
2023-07-13 20:24:47 +00:00
player - > SetLastReleasedMovementKey ( RIGHT ) ;
2023-07-23 08:13:40 -05:00
player - > movementVelocity . x = 0 ;
2023-07-19 20:36:01 +00:00
if ( player - > GetState ( ) = = State : : NORMAL | | player - > GetState ( ) = = State : : PREP_CAST ) {
2023-06-17 19:34:16 -05:00
if ( UpHeld ( ) ) {
2023-07-13 20:24:47 +00:00
player - > UpdateWalkingAnimation ( UP ) ;
2023-06-17 19:34:16 -05:00
} else
if ( DownHeld ( ) ) {
2023-07-13 20:24:47 +00:00
player - > UpdateWalkingAnimation ( DOWN ) ;
2023-06-17 19:34:16 -05:00
} else
if ( LeftHeld ( ) ) {
2023-07-13 20:24:47 +00:00
player - > UpdateWalkingAnimation ( LEFT ) ;
2023-06-17 19:34:16 -05:00
}
2023-06-15 00:11:39 -05:00
}
2023-06-11 22:57:43 -05:00
}
2023-06-15 05:06:50 -05:00
if ( LeftReleased ( ) ) {
2023-07-13 20:24:47 +00:00
player - > SetLastReleasedMovementKey ( LEFT ) ;
2023-07-23 08:13:40 -05:00
player - > movementVelocity . x = 0 ;
2023-07-19 20:36:01 +00:00
if ( player - > GetState ( ) = = State : : NORMAL | | player - > GetState ( ) = = State : : PREP_CAST ) {
2023-06-17 19:34:16 -05:00
if ( RightHeld ( ) ) {
2023-07-13 20:24:47 +00:00
player - > UpdateWalkingAnimation ( RIGHT ) ;
2023-06-17 19:34:16 -05:00
} else
if ( DownHeld ( ) ) {
2023-07-13 20:24:47 +00:00
player - > UpdateWalkingAnimation ( DOWN ) ;
2023-06-17 19:34:16 -05:00
} else
if ( UpHeld ( ) ) {
2023-07-13 20:24:47 +00:00
player - > UpdateWalkingAnimation ( UP ) ;
2023-06-17 19:34:16 -05:00
}
2023-06-15 00:11:39 -05:00
}
2023-06-11 22:57:43 -05:00
}
2023-06-15 05:06:50 -05:00
if ( DownReleased ( ) ) {
2023-07-13 20:24:47 +00:00
player - > SetLastReleasedMovementKey ( DOWN ) ;
2023-07-23 08:13:40 -05:00
player - > movementVelocity . y = 0 ;
2023-07-19 20:36:01 +00:00
if ( player - > GetState ( ) = = State : : NORMAL | | player - > GetState ( ) = = State : : PREP_CAST ) {
2023-06-17 19:34:16 -05:00
if ( RightHeld ( ) ) {
2023-07-13 20:24:47 +00:00
player - > UpdateWalkingAnimation ( RIGHT ) ;
2023-06-17 19:34:16 -05:00
} else
if ( UpHeld ( ) ) {
2023-07-13 20:24:47 +00:00
player - > UpdateWalkingAnimation ( UP ) ;
2023-06-17 19:34:16 -05:00
} else
if ( LeftHeld ( ) ) {
2023-07-13 20:24:47 +00:00
player - > UpdateWalkingAnimation ( LEFT ) ;
2023-06-17 19:34:16 -05:00
}
}
}
2023-07-22 03:19:52 -05:00
if ( player - > GetState ( ) ! = State : : NORMAL & & player - > GetState ( ) ! = State : : PREP_CAST ) {
2023-06-17 21:19:08 -05:00
setIdleAnimation = false ;
}
2023-06-11 22:57:43 -05:00
if ( setIdleAnimation ) {
2023-07-13 20:24:47 +00:00
switch ( player - > GetLastReleasedMovementKey ( ) ) {
2023-06-15 00:11:39 -05:00
case UP : {
2023-07-13 20:24:47 +00:00
player - > UpdateIdleAnimation ( UP ) ;
2023-06-15 00:11:39 -05:00
} break ;
case DOWN : {
2023-07-13 20:24:47 +00:00
player - > UpdateIdleAnimation ( DOWN ) ;
2023-06-15 00:11:39 -05:00
} break ;
case LEFT : {
2023-07-13 20:24:47 +00:00
player - > UpdateIdleAnimation ( LEFT ) ;
2023-06-15 00:11:39 -05:00
} break ;
case RIGHT : {
2023-07-13 20:24:47 +00:00
player - > UpdateIdleAnimation ( RIGHT ) ;
2023-06-15 00:11:39 -05:00
} break ;
default : {
2023-07-13 20:24:47 +00:00
player - > UpdateIdleAnimation ( DOWN ) ;
2023-06-15 00:11:39 -05:00
}
2023-06-11 22:57:43 -05:00
}
}
}
void Crawler : : UpdateCamera ( float fElapsedTime ) {
2023-06-20 19:13:45 -07:00
lastWorldShakeAdjust = std : : max ( 0.f , lastWorldShakeAdjust - fElapsedTime ) ;
if ( worldShakeTime - fElapsedTime > 0 ) {
2023-07-22 03:19:52 -05:00
worldShakeVel = { 1000 , - 1000 } ;
2023-06-20 19:13:45 -07:00
if ( lastWorldShakeAdjust = = 0 ) {
2023-07-22 03:19:52 -05:00
lastWorldShakeAdjust = 0.04 ;
2023-07-21 18:47:45 +00:00
worldShakeVel . x * = - 1 ;
worldShakeVel . y * = - 1 ;
2023-06-20 19:13:45 -07:00
}
2023-07-21 18:47:45 +00:00
worldShake = player - > GetPos ( ) + worldShakeVel * fElapsedTime ;
2023-06-20 19:13:45 -07:00
} else {
2023-07-13 20:24:47 +00:00
camera . SetTarget ( player - > GetPos ( ) ) ;
2023-06-20 19:13:45 -07:00
}
worldShakeTime = std : : max ( 0.f , worldShakeTime - fElapsedTime ) ;
2023-06-11 22:57:43 -05:00
camera . Update ( fElapsedTime ) ;
2023-07-06 02:38:43 -05:00
view . SetWorldOffset ( camera . GetViewPosition ( ) ) ;
2023-06-11 22:57:43 -05:00
}
2023-06-15 00:11:39 -05:00
void Crawler : : UpdateEffects ( float fElapsedTime ) {
2023-07-12 00:23:36 -05:00
for ( auto it = EMITTER_LIST . begin ( ) ; it ! = EMITTER_LIST . end ( ) ; + + it ) {
auto ptr = ( * it ) . get ( ) ;
if ( ! ptr - > Update ( fElapsedTime ) ) {
it = EMITTER_LIST . erase ( it ) ;
if ( it = = EMITTER_LIST . end ( ) ) {
break ;
}
}
}
2023-07-13 01:35:51 -05:00
for ( std : : vector < std : : unique_ptr < Effect > > : : iterator it = backgroundEffects . begin ( ) ; it ! = backgroundEffects . end ( ) ; + + it ) {
Effect * e = ( * it ) . get ( ) ;
if ( ! e - > Update ( fElapsedTime ) ) {
2023-06-15 00:11:39 -05:00
it = backgroundEffects . erase ( it ) ;
2023-07-21 15:20:56 -05:00
if ( it = = backgroundEffects . end ( ) ) { //In case we added effects to the vector and the vector has shifted in memory, we prematurely end.
2023-06-15 00:11:39 -05:00
break ;
}
}
}
2023-07-13 01:35:51 -05:00
for ( std : : vector < std : : unique_ptr < Effect > > : : iterator it = foregroundEffects . begin ( ) ; it ! = foregroundEffects . end ( ) ; + + it ) {
Effect * e = ( * it ) . get ( ) ;
if ( ! e - > Update ( fElapsedTime ) ) {
2023-06-15 00:11:39 -05:00
it = foregroundEffects . erase ( it ) ;
2023-07-21 15:20:56 -05:00
if ( it = = foregroundEffects . end ( ) ) { //In case we added effects to the vector and the vector has shifted in memory, we prematurely end.
2023-06-15 00:11:39 -05:00
break ;
}
}
}
2023-07-21 15:20:56 -05:00
for ( auto it = foregroundEffectsToBeInserted . begin ( ) ; it ! = foregroundEffectsToBeInserted . end ( ) ; + + it ) {
foregroundEffects . push_back ( std : : move ( * it ) ) ;
}
for ( auto it = backgroundEffectsToBeInserted . begin ( ) ; it ! = backgroundEffectsToBeInserted . end ( ) ; + + it ) {
backgroundEffects . push_back ( std : : move ( * it ) ) ;
}
foregroundEffectsToBeInserted . clear ( ) ;
backgroundEffectsToBeInserted . clear ( ) ;
2023-06-15 00:11:39 -05:00
}
2023-06-16 01:41:38 -05:00
void Crawler : : UpdateBullets ( float fElapsedTime ) {
2023-06-30 15:44:41 -07:00
for ( auto it = BULLET_LIST . begin ( ) ; it ! = BULLET_LIST . end ( ) ; + + it ) {
2023-07-05 02:31:34 -05:00
Bullet * b = ( * it ) . get ( ) ;
2023-07-05 05:34:21 -05:00
b - > UpdateFadeTime ( fElapsedTime ) ;
2023-06-30 15:44:41 -07:00
b - > Update ( fElapsedTime ) ;
2023-07-12 00:23:36 -05:00
b - > animation . UpdateState ( b - > internal_animState , fElapsedTime ) ;
2023-07-07 06:42:49 -05:00
if ( ! b - > deactivated ) {
2023-08-06 15:07:53 -05:00
vf2d moveStep = b - > vel * fElapsedTime ;
int stepCount = 1 ;
if ( ( b - > vel * fElapsedTime ) . mag ( ) > 1 ) {
moveStep = ( b - > vel * fElapsedTime ) . norm ( ) ;
stepCount = b - > vel . x * fElapsedTime / moveStep . x ;
}
for ( ; stepCount > 0 ; stepCount - - ) {
b - > pos + = moveStep ;
if ( b - > friendly ) {
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 , b - > OnUpperLevel ( ) ) ) {
if ( ! b - > hitsMultiple ) {
if ( b - > MonsterHit ( m ) ) {
it = BULLET_LIST . erase ( it ) ;
if ( it = = BULLET_LIST . end ( ) ) {
goto outsideBulletLoop ;
}
2023-07-07 06:42:49 -05:00
}
2023-08-06 15:07:53 -05:00
goto continueBulletLoop ;
2023-07-07 06:42:49 -05:00
}
2023-08-06 15:07:53 -05:00
b - > hitList [ & m ] = true ;
2023-07-07 06:42:49 -05:00
}
}
}
2023-08-06 15:07:53 -05:00
} else {
if ( geom2d : : overlaps ( geom2d : : circle ( player - > GetPos ( ) , 12 * player - > GetSizeMult ( ) / 2 ) , geom2d : : circle ( b - > pos , b - > radius ) ) ) {
if ( player - > Hurt ( b - > damage , b - > OnUpperLevel ( ) ) ) {
if ( b - > PlayerHit ( GetPlayer ( ) ) ) {
it = BULLET_LIST . erase ( it ) ;
if ( it = = BULLET_LIST . end ( ) ) {
goto outsideBulletLoop ;
}
2023-07-07 06:42:49 -05:00
}
2023-08-06 15:07:53 -05:00
goto continueBulletLoop ;
2023-07-07 06:42:49 -05:00
}
2023-07-05 05:34:21 -05:00
}
2023-06-17 19:51:56 -05:00
}
2023-06-16 01:41:38 -05:00
}
2023-08-06 15:07:53 -05:00
} else {
b - > pos + = b - > vel * fElapsedTime ;
2023-06-16 01:41:38 -05:00
}
2023-07-05 05:34:21 -05:00
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 ) {
2023-06-16 01:41:38 -05:00
it = BULLET_LIST . erase ( it ) ;
if ( it = = BULLET_LIST . end ( ) ) {
break ;
}
2023-07-05 02:31:34 -05:00
continue ;
2023-06-16 01:41:38 -05:00
}
2023-06-30 15:44:41 -07:00
b - > lifetime - = fElapsedTime ;
if ( b - > lifetime < = 0 ) {
2023-06-20 19:13:45 -07:00
it = BULLET_LIST . erase ( it ) ;
if ( it = = BULLET_LIST . end ( ) ) {
break ;
}
2023-07-05 02:31:34 -05:00
continue ;
2023-06-20 19:13:45 -07:00
}
2023-08-06 15:07:53 -05:00
continueBulletLoop :
2023-07-05 02:31:34 -05:00
continue ;
2023-06-16 01:41:38 -05:00
}
2023-08-06 15:07:53 -05:00
outsideBulletLoop :
2023-06-24 02:14:11 -07:00
int a ;
2023-06-16 01:41:38 -05:00
}
2023-07-07 19:48:45 +00:00
void Crawler : : HurtEnemies ( vf2d pos , float radius , int damage , bool upperLevel ) {
2023-06-15 00:47:11 -05:00
for ( Monster & m : MONSTER_LIST ) {
2023-07-22 03:19:52 -05:00
if ( geom2d : : overlaps ( geom2d : : circle ( pos , radius ) , geom2d : : circle ( m . GetPos ( ) , 12 * m . GetSizeMult ( ) ) ) ) {
m . Hurt ( damage , upperLevel ) ;
2023-06-15 00:47:11 -05:00
}
}
}
2023-06-15 00:11:39 -05:00
2023-07-07 06:42:49 -05:00
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 ) {
2023-07-13 20:24:47 +00:00
Player * pl = GetPlayer ( ) ;
2023-07-07 06:42:49 -05:00
for ( auto it = MONSTER_LIST . begin ( ) ; it ! = MONSTER_LIST . end ( ) ; + + it ) {
Monster & m = * it ;
2023-07-13 20:24:47 +00:00
if ( m . GetPos ( ) . y < pl - > GetPos ( ) . y ) { //This monster renders before the player does (behind the player)
2023-07-07 06:42:49 -05:00
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 ) {
2023-07-13 01:35:51 -05:00
Effect * e = ( * it ) . get ( ) ;
if ( e - > OnUpperLevel ( ) ) {
foregroundEffectsUpper . push_back ( e ) ;
2023-07-07 06:42:49 -05:00
} else {
2023-07-13 01:35:51 -05:00
foregroundEffectsLower . push_back ( e ) ;
2023-07-07 06:42:49 -05:00
}
}
for ( auto it = backgroundEffects . begin ( ) ; it ! = backgroundEffects . end ( ) ; + + it ) {
2023-07-13 01:35:51 -05:00
Effect * e = ( * it ) . get ( ) ;
if ( e - > OnUpperLevel ( ) ) {
backgroundEffectsUpper . push_back ( e ) ;
2023-07-07 06:42:49 -05:00
} else {
2023-07-13 01:35:51 -05:00
backgroundEffectsLower . push_back ( e ) ;
2023-07-07 06:42:49 -05:00
}
}
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 ; } ) ;
}
2023-06-12 00:37:55 -05:00
void Crawler : : RenderWorld ( float fElapsedTime ) {
2023-06-11 22:57:43 -05:00
Clear ( { 100 , 180 , 100 } ) ;
2023-07-06 14:24:43 -05:00
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 ;
2023-07-13 20:24:47 +00:00
if ( ! bridgeLayerFade & & ! player - > upperLevel ) {
2023-07-06 14:24:43 -05:00
int tileID = layer . tiles [ y ] [ x ] - 1 ;
if ( tileID ! = - 1 ) {
2023-07-13 20:24:47 +00:00
int playerXTruncated = int ( player - > GetPos ( ) . x ) / 24 ;
int playerYTruncated = int ( player - > GetPos ( ) . y ) / 24 ;
2023-07-06 14:24:43 -05:00
if ( playerXTruncated = = x & & playerYTruncated = = y ) {
bridgeLayerFade = true ;
}
}
}
continue ;
2023-06-22 22:09:11 -07:00
}
2023-07-06 14:24:43 -05:00
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 } ) ;
}
2023-07-29 10:21:53 -05:00
if ( " debug_collision_boxes " _I ) {
2023-07-10 19:07:59 -05:00
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 ) ;
}
2023-07-29 10:21:53 -05:00
}
2023-06-23 20:42:55 -07:00
}
2023-06-22 04:34:23 -07:00
}
}
2023-06-16 01:10:40 -05:00
}
2023-06-11 22:57:43 -05:00
}
2023-07-11 17:24:50 +00:00
if ( bridgeLayerFade ) {
bridgeFadeFactor = std : : min ( bridgeFadeFactor + fElapsedTime , TileGroup : : FADE_TIME ) ;
} else {
bridgeFadeFactor = std : : max ( bridgeFadeFactor - fElapsedTime , 0.f ) ;
}
2023-07-06 14:24:43 -05:00
# pragma endregion
2023-06-22 02:46:38 -07:00
//DrawDecal({0,0},MAP_TILESETS["assets/maps/"+MAP_DATA[LEVEL1].TilesetData[1].data["source"]]->Decal());
2023-07-07 06:42:49 -05:00
std : : vector < Monster * > monstersBeforeLower , monstersAfterLower , monstersBeforeUpper , monstersAfterUpper ;
std : : vector < Bullet * > bulletsLower , bulletsUpper ;
std : : vector < Effect * > backgroundEffectsLower , backgroundEffectsUpper , foregroundEffectsLower , foregroundEffectsUpper ;
2023-07-13 20:24:47 +00:00
Player * pl = GetPlayer ( ) ;
2023-07-07 06:42:49 -05:00
PopulateRenderLists ( monstersBeforeLower , monstersBeforeUpper , monstersAfterLower , monstersAfterUpper , bulletsLower , bulletsUpper , backgroundEffectsLower , backgroundEffectsUpper , foregroundEffectsLower , foregroundEffectsUpper ) ;
2023-07-13 20:24:47 +00:00
if ( player - > GetZ ( ) > 0 ) {
vf2d shadowScale = vf2d { 8 / 3.f , 1 } / std : : max ( 1.f , player - > GetZ ( ) / 4 ) ;
2023-07-14 15:44:17 +00:00
view . DrawDecal ( player - > GetPos ( ) - vf2d { 3 , 3 } * shadowScale / 2 + vf2d { 0 , 6 } , GFX_Circle . Decal ( ) , shadowScale , BLACK ) ;
2023-06-12 20:22:40 +00:00
}
2023-07-07 06:42:49 -05:00
for ( Effect * e : backgroundEffectsLower ) {
e - > Draw ( ) ;
2023-06-15 00:11:39 -05:00
}
2023-07-07 06:42:49 -05:00
for ( Monster * m : monstersBeforeLower ) {
m - > Draw ( ) ;
2023-06-12 00:37:55 -05:00
}
2023-07-13 20:24:47 +00:00
vf2d playerScale = vf2d ( player - > GetSizeMult ( ) , player - > GetSizeMult ( ) ) ;
vf2d playerPosition = player - > GetPos ( ) ;
2023-07-24 20:58:29 +00:00
auto RenderPlayer = [ & ] ( ) {
2023-07-24 23:20:28 -05:00
int count = 0 ;
for ( vf2d & pos : player - > ghostPositions ) {
view . DrawPartialRotatedDecal ( pos , player - > GetFrame ( ) . GetSourceImage ( ) - > Decal ( ) , player - > GetSpinAngle ( ) , { 12 , 12 } , player - > GetFrame ( ) . GetSourceRect ( ) . pos , player - > GetFrame ( ) . GetSourceRect ( ) . size , playerScale , { 0 , 0 , 0 , uint8_t ( float ( count ) / player - > RETREAT_GHOST_FRAMES * 255 ) } ) ;
count + + ;
}
2023-07-24 20:58:29 +00:00
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 ) ;
}
2023-07-24 23:20:28 -05:00
} ;
2023-07-07 04:49:26 -05:00
//define end
2023-07-13 20:24:47 +00:00
if ( ! player - > upperLevel ) {
2023-07-24 20:58:29 +00:00
RenderPlayer ( ) ;
2023-07-05 19:40:05 +00:00
}
2023-07-13 20:24:47 +00:00
if ( player - > GetState ( ) = = State : : BLOCK ) {
view . DrawDecal ( player - > GetPos ( ) - vf2d { 12 , 12 } , GFX_BLOCK_BUBBLE . Decal ( ) ) ;
2023-06-17 21:19:08 -05:00
}
2023-07-07 06:42:49 -05:00
for ( Monster * m : monstersAfterLower ) {
m - > Draw ( ) ;
2023-06-11 22:57:43 -05:00
}
2023-07-07 06:42:49 -05:00
for ( Effect * e : foregroundEffectsLower ) {
e - > Draw ( ) ;
2023-06-15 00:11:39 -05:00
}
2023-07-07 06:42:49 -05:00
for ( Bullet * b : bulletsLower ) {
2023-06-30 15:44:41 -07:00
b - > Draw ( ) ;
2023-06-16 01:41:38 -05:00
}
2023-07-22 03:19:52 -05:00
auto RenderPrecastTargetingIndicator = [ & ] ( ) {
if ( player - > GetState ( ) = = State : : PREP_CAST ) {
float precastSize = GetPlayer ( ) - > castPrepAbility - > precastInfo . size ;
float precastRange = GetPlayer ( ) - > castPrepAbility - > precastInfo . range ;
vf2d scale = vf2d { precastSize , precastSize } * 2 / 3.f ;
vf2d centerPoint = GetWorldMousePos ( ) - vf2d { game - > GFX_Circle . Sprite ( ) - > width * scale . x / 2 , game - > GFX_Circle . Sprite ( ) - > height * scale . y / 2 } ;
float distance = sqrt ( pow ( player - > GetX ( ) - GetWorldMousePos ( ) . x , 2 ) + pow ( player - > GetY ( ) - GetWorldMousePos ( ) . y , 2 ) ) ;
if ( distance > precastRange ) { //Clamp the distance.
vf2d pointToCursor = { GetWorldMousePos ( ) . x - player - > GetX ( ) , GetWorldMousePos ( ) . y - player - > GetY ( ) } ;
pointToCursor = pointToCursor . norm ( ) * precastRange ;
vf2d centerPoint = player - > GetPos ( ) + pointToCursor - vf2d { game - > GFX_Circle . Sprite ( ) - > width * scale . x / 2 , game - > GFX_Circle . Sprite ( ) - > height * scale . y / 2 } ;
view . DrawDecal ( centerPoint , GFX_Circle . Decal ( ) , scale , { 255 , 0 , 0 , 96 } ) ;
} else {
view . DrawDecal ( centerPoint , GFX_Circle . Decal ( ) , scale , { 255 , 0 , 0 , 96 } ) ;
}
}
} ;
if ( ! player - > OnUpperLevel ( ) ) {
RenderPrecastTargetingIndicator ( ) ;
2023-07-19 20:36:01 +00:00
}
2023-07-06 14:24:43 -05:00
# pragma region Foreground Rendering
for ( TileGroup & group : foregroundTileGroups ) {
if ( view . IsRectVisible ( group . GetRange ( ) . pos , group . GetRange ( ) . size ) ) {
2023-07-13 20:24:47 +00:00
if ( geom2d : : overlaps ( group . GetFadeRange ( ) , player - > pos ) ) {
2023-07-11 15:33:50 +00:00
group . playerBehind = true ;
group . fadeFactor = std : : min ( group . fadeFactor + fElapsedTime , TileGroup : : FADE_TIME ) ;
} else {
group . playerBehind = false ;
group . fadeFactor = std : : max ( group . fadeFactor - fElapsedTime , 0.f ) ;
}
2023-07-06 14:24:43 -05:00
for ( TileRenderData & tile : group . GetTiles ( ) ) {
2023-07-11 15:33:50 +00:00
view . DrawPartialDecal ( tile . pos , { 24 , 24 } , tile . tileset , tile . tileSheetPos , { 24 , 24 } , { 255 , 255 , 255 , uint8_t ( 255 - group . fadeFactor / TileGroup : : FADE_TIME * TileGroup : : FADE_AMT ) } ) ;
2023-07-06 14:24:43 -05:00
}
}
}
# 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 ;
2023-07-11 17:24:50 +00:00
view . DrawPartialDecal ( vi2d { x , y } * 24 , { 24 , 24 } , tileSheet . tileset . tileset - > Decal ( ) , vi2d { tileSheetX , tileSheetY } * 24 , { 24 , 24 } , { 255 , 255 , 255 , uint8_t ( 255 - bridgeFadeFactor / TileGroup : : FADE_TIME * TileGroup : : FADE_AMT ) } ) ;
2023-07-10 19:07:59 -05:00
# ifdef DEBUG_COLLISIONS
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 ) ;
}
# endif
2023-07-06 14:24:43 -05:00
}
}
}
}
2023-06-22 23:28:16 -07:00
}
2023-07-06 14:24:43 -05:00
# pragma endregion
2023-07-07 06:42:49 -05:00
for ( Effect * e : backgroundEffectsUpper ) {
e - > Draw ( ) ;
}
for ( Monster * m : monstersBeforeUpper ) {
m - > Draw ( ) ;
2023-07-07 04:49:26 -05:00
}
2023-07-13 20:24:47 +00:00
if ( player - > upperLevel ) {
2023-07-24 20:58:29 +00:00
RenderPlayer ( ) ;
2023-07-07 04:49:26 -05:00
}
2023-07-07 06:42:49 -05:00
for ( Monster * m : monstersAfterUpper ) {
m - > Draw ( ) ;
}
for ( Effect * e : foregroundEffectsUpper ) {
e - > Draw ( ) ;
}
for ( Bullet * b : bulletsUpper ) {
b - > Draw ( ) ;
2023-07-07 04:49:26 -05:00
}
2023-07-22 03:19:52 -05:00
if ( player - > OnUpperLevel ( ) ) {
RenderPrecastTargetingIndicator ( ) ;
}
2023-07-06 14:24:43 -05:00
# pragma region Upper Foreground Rendering
for ( TileGroup & group : upperForegroundTileGroups ) {
2023-07-13 20:24:47 +00:00
if ( geom2d : : overlaps ( group . GetFadeRange ( ) , player - > pos ) ) {
2023-07-11 17:24:50 +00:00
group . playerBehind = true ;
group . fadeFactor = std : : min ( group . fadeFactor + fElapsedTime , TileGroup : : FADE_TIME ) ;
} else {
group . playerBehind = false ;
group . fadeFactor = std : : max ( group . fadeFactor - fElapsedTime , 0.f ) ;
}
2023-07-06 14:24:43 -05:00
for ( TileRenderData & tile : group . GetTiles ( ) ) {
2023-07-11 17:24:50 +00:00
view . DrawPartialDecal ( tile . pos , { 24 , 24 } , tile . tileset , tile . tileSheetPos , { 24 , 24 } , { 255 , 255 , 255 , uint8_t ( 255 - group . fadeFactor / TileGroup : : FADE_TIME * TileGroup : : FADE_AMT ) } ) ;
2023-07-06 14:24:43 -05:00
}
2023-06-22 23:28:16 -07:00
}
2023-07-06 14:24:43 -05:00
# pragma endregion
2023-07-25 19:48:24 -05:00
for ( std : : vector < std : : shared_ptr < DamageNumber > > : : iterator it = DAMAGENUMBER_LIST . begin ( ) ; it ! = DAMAGENUMBER_LIST . end ( ) ; + + it ) {
DamageNumber * dn = ( * it ) . get ( ) ;
if ( dn - > pauseTime > 0 ) {
dn - > pauseTime - = fElapsedTime ;
} else {
dn - > lifeTime + = fElapsedTime ;
if ( dn - > lifeTime > 1 ) {
it = DAMAGENUMBER_LIST . erase ( it ) ;
if ( it = = DAMAGENUMBER_LIST . end ( ) ) {
break ;
}
} else {
if ( dn - > lifeTime < DamageNumber : : MOVE_UP_TIME ) {
dn - > pos . y - = 20 * fElapsedTime ;
}
2023-06-15 04:53:57 -05:00
}
2023-06-12 00:37:55 -05:00
}
2023-07-25 19:48:24 -05:00
std : : string text = std : : to_string ( dn - > damage ) ;
view . DrawStringPropDecal ( dn - > pos - GetTextSizeProp ( text ) / 2 , text , DARK_RED ) ;
2023-06-12 00:37:55 -05:00
}
2023-06-11 22:57:43 -05:00
}
2023-07-13 20:24:47 +00:00
Player * Crawler : : GetPlayer ( ) {
return player . get ( ) ;
2023-06-15 23:44:34 -05:00
}
2023-06-15 00:47:11 -05:00
void Crawler : : RenderHud ( ) {
2023-06-17 21:19:08 -05:00
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 {
2023-07-14 15:44:17 +00:00
player - > GetRightClickAbility ( ) ,
player - > GetAbility1 ( ) ,
player - > GetAbility2 ( ) ,
player - > GetAbility3 ( ) ,
player - > GetAbility4 ( ) ,
2023-06-17 21:19:08 -05:00
} ;
2023-07-23 12:33:20 -05:00
std : : vector < Ability > activeCooldowns { } ;
std : : copy_if ( cooldowns . begin ( ) , cooldowns . end ( ) , std : : back_inserter ( activeCooldowns ) , [ ] ( Ability & a ) {
2023-06-17 21:19:08 -05:00
return a . cooldown > 0 ;
} ) ;
2023-07-23 12:33:20 -05:00
std : : sort ( activeCooldowns . begin ( ) , activeCooldowns . end ( ) , [ & ] ( Ability & a1 , Ability & a2 ) {
2023-06-17 21:19:08 -05:00
return a1 . cooldown < a2 . cooldown ;
} ) ;
int offset = 6 * activeCooldowns . size ( ) ;
for ( Ability & a : activeCooldowns ) {
2023-07-23 12:33:20 -05:00
if ( a . cooldown > 0.1 ) {
2023-06-17 21:19:08 -05:00
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 ) ;
2023-06-24 00:00:14 -07:00
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 ) ;
2023-07-06 18:03:35 +00:00
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 } ) ;
2023-06-17 21:19:08 -05:00
}
offset - = 6 ;
2023-06-15 00:47:11 -05:00
}
2023-07-18 19:43:51 +00:00
if ( GetPlayer ( ) - > GetCastInfo ( ) . castTimer > 0 ) {
FillRectDecal ( vf2d { ScreenWidth ( ) / 2 - 92.f , ScreenHeight ( ) - 90.f } , { 184 , 20 } , BLACK ) ;
FillRectDecal ( vf2d { ScreenWidth ( ) / 2 - 90.f , ScreenHeight ( ) - 88.f } , { 180 , 16 } , DARK_GREY ) ;
float timer = GetPlayer ( ) - > GetCastInfo ( ) . castTimer ;
float totalTime = GetPlayer ( ) - > GetCastInfo ( ) . castTotalTime ;
std : : string castText = GetPlayer ( ) - > GetCastInfo ( ) . name ;
GradientFillRectDecal ( vf2d { ScreenWidth ( ) / 2 - 90.f , ScreenHeight ( ) - 88.f } , { ( timer / totalTime ) * 180 , 16 } , { 247 , 125 , 37 } , { 247 , 125 , 37 } , { 247 , 184 , 37 } , { 247 , 184 , 37 } ) ;
std : : stringstream castTimeDisplay ;
castTimeDisplay < < std : : fixed < < std : : setprecision ( 1 ) < < timer ;
2023-07-18 21:05:50 +00:00
DrawShadowStringPropDecal ( vf2d { ScreenWidth ( ) / 2 + 90.f , ScreenHeight ( ) - 80.f } - vf2d { float ( GetTextSizeProp ( castTimeDisplay . str ( ) ) . x ) , 0 } , castTimeDisplay . str ( ) , WHITE , BLACK ) ;
2023-07-18 19:43:51 +00:00
DrawShadowStringPropDecal ( vf2d { ScreenWidth ( ) / 2.f - GetTextSizeProp ( castText ) . x * 2 / 2 , ScreenHeight ( ) - 64.f } , castText , WHITE , BLACK , { 2 , 3 } , 2.f ) ;
}
2023-06-16 01:59:46 -05:00
DrawDecal ( { 2 , 2 } , GFX_Heart . Decal ( ) ) ;
2023-06-19 04:03:04 -05:00
DrawDecal ( { 2 , 20 } , GFX_Mana . Decal ( ) ) ;
2023-07-13 20:24:47 +00:00
std : : string text = player - > GetHealth ( ) > 0 ? std : : to_string ( player - > GetHealth ( ) ) : " X " ;
std : : string text_mana = std : : to_string ( player - > GetMana ( ) ) ;
2023-06-24 00:00:14 -07:00
DrawShadowStringPropDecal ( { 20 , 3 } , text , WHITE , BLACK , { 2 , 2 } ) ;
DrawShadowStringPropDecal ( { 24 , 23 } , text_mana , { 192 , 192 , 255 } , BLACK , { 1.5 , 1.5 } ) ;
2023-07-13 20:24:47 +00:00
if ( player - > notEnoughManaDisplay . second > 0 ) {
std : : string displayText = " Not enough mana for " + player - > notEnoughManaDisplay . first + " ! " ;
2023-06-24 00:00:14 -07:00
DrawShadowStringPropDecal ( vf2d { float ( ScreenWidth ( ) / 2 ) , float ( ScreenHeight ( ) / 4 ) } - GetTextSizeProp ( displayText ) / 2 , displayText , DARK_RED , VERY_DARK_RED ) ;
2023-06-19 04:03:04 -05:00
}
2023-07-13 20:24:47 +00:00
if ( player - > notificationDisplay . second > 0 ) {
std : : string displayText = player - > notificationDisplay . first ;
2023-07-06 03:31:47 -05:00
DrawShadowStringPropDecal ( vf2d { float ( ScreenWidth ( ) / 2 ) , float ( ScreenHeight ( ) / 4 ) - 24 } - GetTextSizeProp ( displayText ) / 2 , displayText , BLUE , VERY_DARK_BLUE ) ;
2023-07-06 02:38:43 -05:00
}
2023-06-18 02:05:50 -07:00
std : : string versionStr ( " v " + std : : to_string ( VERSION_MAJOR ) + " . " + std : : to_string ( VERSION_MINOR ) + " . " + std : : to_string ( VERSION_PATCH ) + " . " + std : : to_string ( VERSION_BUILD ) ) ;
2023-06-24 00:00:14 -07:00
DrawShadowStringDecal ( vf2d { GetScreenSize ( ) } - vf2d { GetTextSize ( versionStr ) } * 0.4 , versionStr , WHITE , BLACK , { 0.4 , 0.4 } , 0.4 ) ;
2023-07-29 10:21:53 -05:00
if ( " debug_player_info " _I ) {
2023-07-13 20:24:47 +00:00
DrawShadowStringDecal ( { 0 , 128 } , player - > GetPos ( ) . str ( ) ) ;
2023-07-29 10:21:53 -05:00
DrawShadowStringDecal ( { 0 , 136 } , " Spd: " + std : : to_string ( player - > GetMoveSpdMult ( ) ) ) ;
}
2023-06-15 00:47:11 -05:00
}
2023-07-13 01:35:51 -05:00
void Crawler : : AddEffect ( std : : unique_ptr < Effect > foreground , std : : unique_ptr < Effect > background ) {
2023-07-21 15:20:56 -05:00
AddEffect ( std : : move ( background ) , true ) ;
AddEffect ( std : : move ( foreground ) ) ;
2023-06-15 00:11:39 -05:00
}
2023-07-13 01:35:51 -05:00
void Crawler : : AddEffect ( std : : unique_ptr < Effect > foreground , bool back ) {
2023-06-19 03:25:01 -05:00
if ( back ) {
2023-07-21 15:20:56 -05:00
backgroundEffectsToBeInserted . push_back ( std : : move ( foreground ) ) ;
2023-06-19 03:25:01 -05:00
} else {
2023-07-21 15:20:56 -05:00
foregroundEffectsToBeInserted . push_back ( std : : move ( foreground ) ) ;
2023-06-19 03:25:01 -05:00
}
}
2023-06-15 04:53:57 -05:00
vf2d Crawler : : GetWorldMousePos ( ) {
return GetMousePos ( ) + view . GetWorldOffset ( ) ;
}
2023-06-20 19:13:45 -07:00
void Crawler : : SetupWorldShake ( float duration ) {
2023-07-21 18:47:45 +00:00
worldShakeVel = { 750 , - 750 } ;
2023-06-20 19:13:45 -07:00
worldShakeTime = duration ;
2023-07-13 20:24:47 +00:00
worldShake = player - > GetPos ( ) ;
2023-06-20 19:13:45 -07:00
camera . SetTarget ( worldShake ) ;
}
2023-06-21 22:59:06 -07:00
void Crawler : : InitializeLevel ( std : : string mapFile , MapName map ) {
TMXParser level ( mapFile ) ;
2023-07-14 19:14:04 +00:00
2023-06-21 22:59:06 -07:00
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 ) {
2023-06-22 05:38:44 -07:00
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 ( ) ;
2023-06-22 22:09:11 -07:00
MAP_TILESETS [ " assets/maps/ " + baseSourceDir ] . tileset = r ;
MAP_TILESETS [ " assets/maps/ " + baseSourceDir ] . foregroundTiles = tileset . GetData ( ) . ForegroundTileData ;
2023-07-06 14:24:43 -05:00
MAP_TILESETS [ " assets/maps/ " + baseSourceDir ] . upperForegroundTiles = tileset . GetData ( ) . UpperForegroundTileData ;
2023-06-23 20:42:55 -07:00
MAP_TILESETS [ " assets/maps/ " + baseSourceDir ] . collision = tileset . GetData ( ) . CollisionData ;
2023-07-06 15:07:44 -05:00
MAP_TILESETS [ " assets/maps/ " + baseSourceDir ] . staircaseTiles = tileset . GetData ( ) . StaircaseData ;
2023-06-22 05:38:44 -07:00
r - > Load ( " assets/maps/ " + tileset . GetData ( ) . ImageData . data [ " source " ] ) ;
}
2023-06-21 22:59:06 -07:00
}
}
2023-06-22 02:46:38 -07:00
void Crawler : : LoadLevel ( MapName map ) {
2023-06-22 17:44:51 -07:00
SPAWNER_LIST . clear ( ) ;
2023-06-22 23:28:16 -07:00
foregroundTileGroups . clear ( ) ;
2023-06-22 02:46:38 -07:00
currentLevel = map ;
WORLD_SIZE = { MAP_DATA [ map ] . MapData . width , MAP_DATA [ map ] . MapData . height } ;
2023-07-14 19:14:04 +00:00
2023-07-07 21:35:44 -05:00
for ( auto key : MAP_DATA [ map ] . SpawnerData ) {
SpawnerTag & spawnData = MAP_DATA [ map ] . SpawnerData [ key . first ] ;
2023-08-13 02:12:19 -05:00
std : : vector < std : : pair < int , vf2d > > monster_list ;
2023-07-07 21:35:44 -05:00
vf2d spawnerRadius = vf2d { spawnData . ObjectData . GetFloat ( " width " ) , spawnData . ObjectData . GetFloat ( " height " ) } / 2 ;
for ( XMLTag & monster : spawnData . monsters ) {
int monsterTypeID = monster . GetInteger ( " value " ) - 1 ;
2023-08-13 02:12:19 -05:00
monster_list . push_back ( { monsterTypeID , { monster . GetInteger ( " x " ) - spawnData . ObjectData . GetFloat ( " x " ) , monster . GetInteger ( " y " ) - spawnData . ObjectData . GetFloat ( " y " ) } } ) ;
2023-06-22 17:44:51 -07:00
}
2023-07-10 19:22:33 -05:00
SPAWNER_LIST . push_back ( MonsterSpawner { { spawnData . ObjectData . GetFloat ( " x " ) , spawnData . ObjectData . GetFloat ( " y " ) } , spawnerRadius * 2 , monster_list , spawnData . upperLevel } ) ;
2023-06-22 17:44:51 -07:00
}
2023-07-14 19:14:04 +00:00
2023-07-10 18:48:57 -05:00
std : : set < vi2d > foregroundTilesAdded , upperForegroundTilesAdded ;
2023-06-22 23:28:16 -07:00
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 ;
2023-07-06 14:24:43 -05:00
# pragma region TileGroupShenanigans
2023-07-10 18:48:57 -05:00
TileRenderData tile = { tileSheet . tileset . tileset - > Decal ( ) , vi2d { x , y } * 24 , vi2d { tileSheetX , tileSheetY } * 24 } ;
if ( IsForegroundTile ( tileSheet , tileSheetIndex ) & & foregroundTilesAdded . find ( { x , y } ) = = foregroundTilesAdded . end ( ) ) {
std : : queue < vi2d > tileGroupChecks ;
TileGroup group ;
foregroundTilesAdded . insert ( { x , y } ) ;
group . InsertTile ( tile ) ;
if ( x > 0 ) tileGroupChecks . push ( { x - 1 , y } ) ;
if ( x < WORLD_SIZE . x - 1 ) tileGroupChecks . push ( { x + 1 , y } ) ;
if ( y > 0 ) tileGroupChecks . push ( { x , y - 1 } ) ;
if ( y < WORLD_SIZE . y - 1 ) tileGroupChecks . push ( { x , y + 1 } ) ;
while ( ! tileGroupChecks . empty ( ) ) {
vi2d & pos = tileGroupChecks . front ( ) ;
tileGroupChecks . pop ( ) ;
int tileID = layer . tiles [ pos . y ] [ pos . x ] - 1 ;
TilesheetData tileSheet = GetTileSheet ( currentLevel , tileID ) ;
int tileSheetWidth = tileSheet . tileset . tileset - > Sprite ( ) - > width / 24 ;
int tileSheetHeight = tileSheet . tileset . tileset - > Sprite ( ) - > height / 24 ;
int tileSheetIndex = tileID - ( tileSheet . firstgid - 1 ) ;
int tileSheetX = tileSheetIndex % tileSheetWidth ;
int tileSheetY = tileSheetIndex / tileSheetWidth ;
TileRenderData tile = { tileSheet . tileset . tileset - > Decal ( ) , pos * 24 , vi2d { tileSheetX , tileSheetY } * 24 } ;
if ( IsForegroundTile ( tileSheet , tileSheetIndex ) & & foregroundTilesAdded . find ( pos ) = = foregroundTilesAdded . end ( ) ) {
foregroundTilesAdded . insert ( pos ) ;
2023-07-06 14:24:43 -05:00
group . InsertTile ( tile ) ;
2023-07-10 18:48:57 -05:00
if ( pos . x > 0 ) tileGroupChecks . push ( pos + vi2d { - 1 , 0 } ) ;
if ( pos . x < WORLD_SIZE . x - 1 ) tileGroupChecks . push ( pos + vi2d { 1 , 0 } ) ;
if ( pos . y > 0 ) tileGroupChecks . push ( pos + vi2d { 0 , - 1 } ) ;
if ( pos . y < WORLD_SIZE . y - 1 ) tileGroupChecks . push ( pos + vi2d { 0 , 1 } ) ;
2023-07-06 14:24:43 -05:00
}
}
2023-07-10 18:48:57 -05:00
foregroundTileGroups . push_back ( group ) ;
2023-07-06 14:24:43 -05:00
} else
2023-07-10 18:48:57 -05:00
if ( IsUpperForegroundTile ( tileSheet , tileSheetIndex ) & & upperForegroundTilesAdded . find ( { x , y } ) = = upperForegroundTilesAdded . end ( ) ) {
std : : queue < vi2d > tileGroupChecks ;
TileGroup group ;
upperForegroundTilesAdded . insert ( { x , y } ) ;
group . InsertTile ( tile ) ;
if ( x > 0 ) tileGroupChecks . push ( { x - 1 , y } ) ;
if ( x < WORLD_SIZE . x - 1 ) tileGroupChecks . push ( { x + 1 , y } ) ;
if ( y > 0 ) tileGroupChecks . push ( { x , y - 1 } ) ;
if ( y < WORLD_SIZE . y - 1 ) tileGroupChecks . push ( { x , y + 1 } ) ;
while ( ! tileGroupChecks . empty ( ) ) {
vi2d & pos = tileGroupChecks . front ( ) ;
tileGroupChecks . pop ( ) ;
int tileID = layer . tiles [ pos . y ] [ pos . x ] - 1 ;
TilesheetData tileSheet = GetTileSheet ( currentLevel , tileID ) ;
int tileSheetWidth = tileSheet . tileset . tileset - > Sprite ( ) - > width / 24 ;
int tileSheetHeight = tileSheet . tileset . tileset - > Sprite ( ) - > height / 24 ;
int tileSheetIndex = tileID - ( tileSheet . firstgid - 1 ) ;
int tileSheetX = tileSheetIndex % tileSheetWidth ;
int tileSheetY = tileSheetIndex / tileSheetWidth ;
TileRenderData tile = { tileSheet . tileset . tileset - > Decal ( ) , pos * 24 , vi2d { tileSheetX , tileSheetY } * 24 } ;
if ( IsUpperForegroundTile ( tileSheet , tileSheetIndex ) & & upperForegroundTilesAdded . find ( pos ) = = upperForegroundTilesAdded . end ( ) ) {
upperForegroundTilesAdded . insert ( pos ) ;
group . InsertTile ( tile ) ;
if ( pos . x > 0 ) tileGroupChecks . push ( pos + vi2d { - 1 , 0 } ) ;
if ( pos . x < WORLD_SIZE . x - 1 ) tileGroupChecks . push ( pos + vi2d { 1 , 0 } ) ;
if ( pos . y > 0 ) tileGroupChecks . push ( pos + vi2d { 0 , - 1 } ) ;
if ( pos . y < WORLD_SIZE . y - 1 ) tileGroupChecks . push ( pos + vi2d { 0 , 1 } ) ;
2023-07-10 20:31:13 +00:00
}
}
2023-07-10 18:48:57 -05:00
upperForegroundTileGroups . push_back ( group ) ;
2023-07-10 20:31:13 +00:00
}
2023-07-06 14:24:43 -05:00
# pragma endregion
2023-06-22 23:28:16 -07:00
}
}
}
}
2023-07-14 19:14:04 +00:00
2023-07-07 06:42:49 -05:00
int counter = 0 ;
bridgeLayerIndex = - 1 ;
for ( LayerTag & layer : MAP_DATA [ map ] . LayerData ) {
if ( IsBridgeLayer ( layer ) ) {
bridgeLayerIndex = counter ;
}
counter + + ;
}
2023-07-14 19:14:04 +00:00
2023-07-13 20:24:47 +00:00
player - > upperLevel = false ; //Assume player starts on lower level.
player - > SetPos ( MAP_DATA [ map ] . MapData . playerSpawnLocation ) ;
2023-07-14 19:14:04 +00:00
2023-07-10 18:40:51 +00:00
pathfinder . Initialize ( ) ;
2023-06-22 02:46:38 -07:00
}
vi2d Crawler : : GetWorldSize ( ) {
return WORLD_SIZE ;
}
2023-07-06 14:24:43 -05:00
bool Crawler : : IsUpperForegroundTile ( TilesheetData sheet , int tileID ) {
return sheet . tileset . upperForegroundTiles . find ( tileID ) ! = sheet . tileset . upperForegroundTiles . end ( ) ;
}
2023-06-22 22:09:11 -07:00
bool Crawler : : IsForegroundTile ( TilesheetData sheet , int tileID ) {
return sheet . tileset . foregroundTiles . find ( tileID ) ! = sheet . tileset . foregroundTiles . end ( ) ;
}
2023-06-22 04:34:23 -07:00
TilesheetData Crawler : : GetTileSheet ( MapName map , int tileID ) {
std : : vector < XMLTag > & tileData = MAP_DATA [ map ] . TilesetData ;
if ( tileData . size ( ) = = 1 ) {
2023-06-22 05:38:44 -07:00
size_t slashMarkerSourceDir = tileData [ 0 ] . data [ " source " ] . find_last_of ( ' / ' ) ;
std : : string baseSourceDir = tileData [ 0 ] . data [ " source " ] . substr ( slashMarkerSourceDir + 1 ) ;
2023-06-22 22:09:11 -07:00
return { MAP_TILESETS [ " assets/maps/ " + baseSourceDir ] , 1 } ;
2023-06-22 04:34:23 -07:00
} else {
for ( int i = 1 ; i < tileData . size ( ) ; i + + ) {
2023-06-22 04:42:55 -07:00
if ( tileID < stoi ( tileData [ i ] . data [ " firstgid " ] ) ) {
2023-06-22 05:38:44 -07:00
size_t slashMarkerSourceDir = tileData [ i - 1 ] . data [ " source " ] . find_last_of ( ' / ' ) ;
std : : string baseSourceDir = tileData [ i - 1 ] . data [ " source " ] . substr ( slashMarkerSourceDir + 1 ) ;
2023-06-22 22:09:11 -07:00
return { MAP_TILESETS [ " assets/maps/ " + baseSourceDir ] , stoi ( tileData [ i - 1 ] . data [ " firstgid " ] ) } ;
2023-06-22 04:34:23 -07:00
}
}
2023-06-22 05:38:44 -07:00
size_t slashMarkerSourceDir = tileData [ tileData . size ( ) - 1 ] . data [ " source " ] . find_last_of ( ' / ' ) ;
std : : string baseSourceDir = tileData [ tileData . size ( ) - 1 ] . data [ " source " ] . substr ( slashMarkerSourceDir + 1 ) ;
2023-06-22 22:09:11 -07:00
return { MAP_TILESETS [ " assets/maps/ " + baseSourceDir ] , stoi ( tileData [ tileData . size ( ) - 1 ] . data [ " firstgid " ] ) } ;
2023-06-22 04:34:23 -07:00
}
}
2023-07-06 14:59:21 -05:00
bool Crawler : : HasTileCollision ( MapName map , vf2d pos , bool upperLevel ) {
geom2d : : rect < int > collisionRect = GetTileCollision ( map , pos , upperLevel ) ;
2023-07-05 18:29:04 +00:00
vi2d collisionRectSnapPos = vi2d { pos / 24 } * 24 ;
collisionRect . pos + = collisionRectSnapPos ;
return geom2d : : overlaps ( collisionRect , pos ) ;
2023-07-05 04:31:31 -05:00
}
2023-07-06 14:24:43 -05:00
bool Crawler : : IsBridgeLayer ( LayerTag & layer ) {
return layer . tag . data . find ( " class " ) ! = layer . tag . data . end ( ) & & layer . tag . data [ " class " ] = = " Bridge " ;
}
2023-07-06 14:59:21 -05:00
geom2d : : rect < int > Crawler : : GetTileCollision ( MapName map , vf2d pos , bool upperLevel ) {
2023-07-06 14:24:43 -05:00
if ( pos . x < 0 | | pos . y < 0 | | pos . x > = WORLD_SIZE . x * 24 | | pos . y > = WORLD_SIZE . y * 24 ) return NO_COLLISION ;
2023-07-07 17:44:06 -05:00
# 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
2023-07-07 06:42:49 -05:00
//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 ;
2023-06-24 00:00:14 -07:00
for ( LayerTag & layer : MAP_DATA [ map ] . LayerData ) {
2023-07-07 06:42:49 -05:00
auto HasNoClass = [ & ] ( ) { return layer . tag . data . find ( " class " ) = = layer . tag . data . end ( ) ; } ;
if ( HasNoClass ( ) & & counter ! = bridgeLayerIndex ) {
2023-07-06 14:59:21 -05:00
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 ;
}
2023-06-24 00:00:14 -07:00
}
2023-07-07 06:42:49 -05:00
counter + + ;
2023-06-24 00:00:14 -07:00
}
2023-07-05 18:29:04 +00:00
return NO_COLLISION ;
2023-06-24 00:00:14 -07:00
}
MapName Crawler : : GetCurrentLevel ( ) {
return currentLevel ;
}
2023-07-07 04:31:36 -05:00
std : : map < std : : string , std : : vector < geom2d : : rect < int > > > & Crawler : : GetZoneData ( MapName map ) {
return MAP_DATA [ map ] . ZoneData ;
}
2023-07-13 20:24:47 +00:00
void Crawler : : ChangePlayerClass ( Class cl ) {
switch ( cl ) {
case WARRIOR : {
2023-07-14 19:14:04 +00:00
player . reset ( new Warrior ( player . get ( ) ) ) ;
2023-07-13 20:24:47 +00:00
} break ;
case THIEF : {
2023-07-14 19:14:04 +00:00
player . reset ( new Thief ( player . get ( ) ) ) ;
2023-07-13 20:24:47 +00:00
} break ;
case TRAPPER : {
2023-07-14 19:14:04 +00:00
player . reset ( new Trapper ( player . get ( ) ) ) ;
2023-07-13 20:24:47 +00:00
} break ;
case RANGER : {
2023-07-14 19:14:04 +00:00
player . reset ( new Ranger ( player . get ( ) ) ) ;
2023-07-13 20:24:47 +00:00
} break ;
case WIZARD : {
2023-07-14 19:14:04 +00:00
player . reset ( new Wizard ( player . get ( ) ) ) ;
2023-07-13 20:24:47 +00:00
} break ;
case WITCH : {
2023-07-14 19:14:04 +00:00
player . reset ( new Witch ( player . get ( ) ) ) ;
2023-07-13 20:24:47 +00:00
} break ;
}
2023-07-14 19:14:04 +00:00
sig : : Animation : : SetupPlayerAnimations ( ) ;
2023-07-13 20:24:47 +00:00
GetPlayer ( ) - > UpdateIdleAnimation ( DOWN ) ;
}
2023-07-26 21:08:17 +00:00
void Crawler : : InitializeClasses ( ) {
Warrior : : Initialize ( ) ;
Thief : : Initialize ( ) ;
Ranger : : Initialize ( ) ;
Trapper : : Initialize ( ) ;
Wizard : : Initialize ( ) ;
Witch : : Initialize ( ) ;
2023-07-22 04:21:10 -05:00
Warrior : : InitializeClassAbilities ( ) ;
Thief : : InitializeClassAbilities ( ) ;
Ranger : : InitializeClassAbilities ( ) ;
Trapper : : InitializeClassAbilities ( ) ;
Wizard : : InitializeClassAbilities ( ) ;
Witch : : InitializeClassAbilities ( ) ;
}
2023-07-26 01:58:00 -05:00
std : : string Crawler : : GetString ( std : : string key ) {
return DATA . GetProperty ( key ) . GetString ( ) ;
}
2023-07-26 18:08:06 +00:00
datafilestringdata Crawler : : GetStringList ( std : : string key ) {
return { DATA , key } ;
}
2023-07-26 01:58:00 -05:00
int Crawler : : GetInt ( std : : string key ) {
return DATA . GetProperty ( key ) . GetInt ( ) ;
}
2023-07-26 18:08:06 +00:00
datafileintdata Crawler : : GetIntList ( std : : string key ) {
return { DATA , key } ;
}
2023-07-26 01:58:00 -05:00
float Crawler : : GetFloat ( std : : string key ) {
return DATA . GetProperty ( key ) . GetReal ( ) ;
}
2023-07-26 18:08:06 +00:00
datafilefloatdata Crawler : : GetFloatList ( std : : string key ) {
return { DATA , key } ;
}
2023-07-26 01:58:00 -05:00
double Crawler : : GetDouble ( std : : string key ) {
return DATA . GetProperty ( key ) . GetReal ( ) ;
}
2023-07-26 18:08:06 +00:00
datafiledoubledata Crawler : : GetDoubleList ( std : : string key ) {
return { DATA , key } ;
}
2023-06-11 22:57:43 -05:00
int main ( )
{
2023-08-06 15:07:53 -05:00
char * testArr = new char [ 5000 ] ;
delete [ ] testArr ;
2023-06-11 22:57:43 -05:00
Crawler demo ;
if ( demo . Construct ( WINDOW_SIZE . x , WINDOW_SIZE . y , 4 , 4 ) )
demo . Start ( ) ;
return 0 ;
2023-07-26 18:08:06 +00:00
}
2023-07-26 19:53:34 +00:00
datafilestringdata operator " " _s ( const char * key , std : : size_t len ) {
2023-07-28 04:41:18 -05:00
if ( utils : : datafile : : DEBUG_ACCESS_OPTIONS ) {
std : : cout < < " Reading " < < std : : string ( key , len ) < < std : : endl ;
}
2023-07-26 18:08:06 +00:00
return { DATA , std : : string ( key , len ) } ;
}
2023-07-26 19:53:34 +00:00
datafileintdata operator " " _i ( const char * key , std : : size_t len ) {
2023-07-28 04:41:18 -05:00
if ( utils : : datafile : : DEBUG_ACCESS_OPTIONS ) {
std : : cout < < " Reading " < < std : : string ( key , len ) < < std : : endl ;
}
2023-07-26 18:08:06 +00:00
return { DATA , std : : string ( key , len ) } ;
}
2023-07-26 19:53:34 +00:00
datafilefloatdata operator " " _f ( const char * key , std : : size_t len ) {
2023-07-28 04:41:18 -05:00
if ( utils : : datafile : : DEBUG_ACCESS_OPTIONS ) {
std : : cout < < " Reading " < < std : : string ( key , len ) < < std : : endl ;
}
2023-07-26 18:08:06 +00:00
return { DATA , std : : string ( key , len ) } ;
}
2023-07-26 19:53:34 +00:00
datafiledoubledata operator " " _d ( const char * key , std : : size_t len ) {
2023-07-28 04:41:18 -05:00
if ( utils : : datafile : : DEBUG_ACCESS_OPTIONS ) {
std : : cout < < " Reading " < < std : : string ( key , len ) < < std : : endl ;
}
2023-07-26 18:08:06 +00:00
return { DATA , std : : string ( key , len ) } ;
}
2023-07-28 04:41:18 -05:00
Pixel operator " " _Pixel ( const char * key , std : : size_t len ) {
if ( utils : : datafile : : DEBUG_ACCESS_OPTIONS ) {
std : : cout < < " Reading " < < std : : string ( key , len ) < < std : : endl ;
}
return { uint8_t ( DATA . GetProperty ( std : : string ( key , len ) ) . GetInt ( 0 ) ) , uint8_t ( DATA . GetProperty ( std : : string ( key , len ) ) . GetInt ( 1 ) ) , uint8_t ( DATA . GetProperty ( std : : string ( key , len ) ) . GetInt ( 2 ) ) , uint8_t ( DATA . GetProperty ( std : : string ( key , len ) ) . GetInt ( 3 ) ) } ;
}
2023-07-26 19:53:34 +00:00
std : : string operator " " _S ( const char * key , std : : size_t len ) {
2023-07-28 04:41:18 -05:00
if ( utils : : datafile : : DEBUG_ACCESS_OPTIONS ) {
std : : cout < < " Reading " < < std : : string ( key , len ) < < std : : endl ;
}
2023-07-26 18:08:06 +00:00
return DATA . GetProperty ( std : : string ( key , len ) ) . GetString ( ) ;
}
2023-07-26 19:53:34 +00:00
int operator " " _I ( const char * key , std : : size_t len ) {
2023-07-28 04:41:18 -05:00
if ( utils : : datafile : : DEBUG_ACCESS_OPTIONS ) {
std : : cout < < " Reading " < < std : : string ( key , len ) < < std : : endl ;
}
2023-07-26 18:08:06 +00:00
return DATA . GetProperty ( std : : string ( key , len ) ) . GetInt ( ) ;
}
2023-07-26 19:53:34 +00:00
float operator " " _F ( const char * key , std : : size_t len ) {
2023-07-28 04:41:18 -05:00
if ( utils : : datafile : : DEBUG_ACCESS_OPTIONS ) {
std : : cout < < " Reading " < < std : : string ( key , len ) < < std : : endl ;
}
2023-07-26 18:08:06 +00:00
return DATA . GetProperty ( std : : string ( key , len ) ) . GetReal ( ) ;
}
2023-07-28 20:17:09 +00:00
float operator " " _FRange ( const char * key , std : : size_t len ) {
if ( utils : : datafile : : DEBUG_ACCESS_OPTIONS ) {
std : : cout < < " Reading " < < std : : string ( key , len ) < < std : : endl ;
}
return util : : random ( DATA . GetProperty ( std : : string ( key , len ) ) . GetReal ( 1 ) - DATA . GetProperty ( std : : string ( key , len ) ) . GetReal ( 0 ) ) + DATA . GetProperty ( std : : string ( key , len ) ) . GetReal ( 0 ) ;
}
2023-07-26 19:53:34 +00:00
double operator " " _D ( const char * key , std : : size_t len ) {
2023-07-28 04:41:18 -05:00
if ( utils : : datafile : : DEBUG_ACCESS_OPTIONS ) {
std : : cout < < std : : string ( key , len ) < < std : : endl ;
}
2023-07-26 18:08:06 +00:00
return DATA . GetProperty ( std : : string ( key , len ) ) . GetReal ( ) ;
2023-06-11 22:57:43 -05:00
}