@ -21,7 +21,6 @@ std::vector<Monster>MONSTER_LIST;
std : : vector < MonsterSpawner > SPAWNER_LIST ;
std : : vector < DamageNumber > DAMAGENUMBER_LIST ;
std : : vector < std : : unique_ptr < Bullet > > BULLET_LIST ;
std : : vector < std : : unique_ptr < Bullet > > PLAYER_BULLET_LIST ;
Crawler * game ;
Crawler : : Crawler ( )
@ -642,15 +641,36 @@ void Crawler::UpdateBullets(float fElapsedTime){
b - > UpdateFadeTime ( fElapsedTime ) ;
b - > Update ( fElapsedTime ) ;
b - > pos + = b - > vel * fElapsedTime ;
if ( ! b - > deactivated & & geom2d : : overlaps ( geom2d : : circle ( player . GetPos ( ) , 12 * player . GetSizeMult ( ) / 2 ) , geom2d : : circle ( b - > pos , b - > radius ) ) ) {
if ( player . Hurt ( b - > damage ) ) {
if ( b - > PlayerHit ( player ) ) {
it = BULLET_LIST . erase ( it ) ;
if ( it = = BULLET_LIST . end ( ) ) {
break ;
if ( ! b - > deactivated ) {
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 ) ) {
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 ( 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 ;
}
}
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 ) {
@ -669,46 +689,6 @@ void Crawler::UpdateBullets(float fElapsedTime){
continue ;
}
b - > animation . UpdateState ( b - > internal_animState , fElapsedTime ) ;
}
for ( std : : vector < std : : unique_ptr < Bullet > > : : iterator it = PLAYER_BULLET_LIST . begin ( ) ; it ! = PLAYER_BULLET_LIST . end ( ) ; + + it ) {
std : : unique_ptr < Bullet > & b = * it ;
b - > UpdateFadeTime ( fElapsedTime ) ;
b - > Update ( fElapsedTime ) ;
b - > pos + = b - > vel * fElapsedTime ;
if ( ! b - > deactivated ) {
for ( Monster & m : MONSTER_LIST ) {
if ( geom2d : : overlaps ( geom2d : : circle ( m . GetPos ( ) , 12 * m . GetSizeMult ( ) ) , geom2d : : circle ( b - > pos , b - > radius ) ) ) {
if ( b - > hitList . find ( & m ) = = b - > hitList . end ( ) & & m . Hurt ( b - > damage ) ) {
if ( ! b - > hitsMultiple ) {
if ( b - > MonsterHit ( m ) ) {
it = PLAYER_BULLET_LIST . erase ( it ) ;
if ( it = = PLAYER_BULLET_LIST . end ( ) ) {
goto outsidePlayerBulletLoop ;
}
}
goto continuePlayerBulletLoop ;
}
b - > hitList [ & m ] = true ;
}
}
}
}
if ( b - > pos . x < view . GetWorldTL ( ) . x | | b - > pos . x > view . GetWorldBR ( ) . x | | b - > pos . y < view . GetWorldTL ( ) . y | | b - > pos . y > view . GetWorldBR ( ) . y ) {
it = PLAYER_BULLET_LIST . erase ( it ) ;
if ( it = = PLAYER_BULLET_LIST . end ( ) ) {
break ;
}
continue ;
}
b - > lifetime - = fElapsedTime ;
if ( b - > lifetime < = 0 ) {
it = PLAYER_BULLET_LIST . erase ( it ) ;
if ( it = = PLAYER_BULLET_LIST . end ( ) ) {
break ;
}
continue ;
}
b - > animation . UpdateState ( b - > internal_animState , fElapsedTime ) ;
continuePlayerBulletLoop :
continue ;
}
@ -723,6 +703,54 @@ void Crawler::HurtEnemies(vf2d pos,float radius,int 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 ;
@ -769,23 +797,22 @@ void Crawler::RenderWorld(float fElapsedTime){
}
# pragma endregion
//DrawDecal({0,0},MAP_TILESETS["assets/maps/"+MAP_DATA[LEVEL1].TilesetData[1].data["source"]]->Decal());
std : : vector < Monster > monstersBefore , monstersAfter ;
std : : vector < Monster * > monstersBeforeLower , monstersAfterLower , monstersBeforeUpper , monstersAfterUpper ;
std : : vector < Bullet * > bulletsLower , bulletsUpper ;
std : : vector < Effect * > backgroundEffectsLower , backgroundEffectsUpper , foregroundEffectsLower , foregroundEffectsUpper ;
Player & pl = player ;
std : : copy_if ( MONSTER_LIST . begin ( ) , MONSTER_LIST . end ( ) , std : : back_inserter ( monstersBefore ) , [ & pl ] ( Monster & m ) { return m . GetPos ( ) . y < pl . GetPos ( ) . y ; } ) ;
std : : copy_if ( MONSTER_LIST . begin ( ) , MONSTER_LIST . end ( ) , std : : back_inserter ( monstersAfter ) , [ & pl ] ( Monster & m ) { return m . GetPos ( ) . y > = pl . GetPos ( ) . y ; } ) ;
std : : sort ( monstersBefore . begin ( ) , monstersBefore . end ( ) , [ ] ( Monster & m1 , Monster & m2 ) { return m1 . GetPos ( ) . y < m2 . GetPos ( ) . y ; } ) ;
std : : sort ( monstersAfter . begin ( ) , monstersAfter . end ( ) , [ ] ( Monster & m1 , Monster & m2 ) { return m1 . GetPos ( ) . y < m2 . GetPos ( ) . y ; } ) ;
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 : backgroundEffects ) {
e . Draw ( ) ;
for ( Effect * e : backgroundEffectsLower ) {
e - > Draw ( ) ;
}
for ( Monster & m : monstersBefore ) {
if ( ! m . OnUpperLevel ( ) ) {
m . Draw ( ) ;
}
for ( Monster * m : monstersBeforeLower ) {
m - > Draw ( ) ;
}
vf2d playerScale = vf2d ( player . GetSizeMult ( ) , player . GetSizeMult ( ) ) ;
vf2d playerPosition = player . GetPos ( ) ;
@ -802,18 +829,13 @@ void Crawler::RenderWorld(float fElapsedTime){
if ( player . GetState ( ) = = State : : BLOCK ) {
view . DrawDecal ( player . GetPos ( ) - vf2d { 12 , 12 } , GFX_BLOCK_BUBBLE . Decal ( ) ) ;
}
for ( Monster & m : monstersAfter ) {
if ( ! m . OnUpperLevel ( ) ) {
m . Draw ( ) ;
}
for ( Monster * m : monstersAfterLower ) {
m - > Draw ( ) ;
}
for ( Effect & e : foregroundEffects ) {
e . Draw ( ) ;
for ( Effect * e : foregroundEffectsLower ) {
e - > Draw ( ) ;
}
for ( std : : unique_ptr < Bullet > & b : BULLET_LIST ) {
b - > Draw ( ) ;
}
for ( std : : unique_ptr < Bullet > & b : PLAYER_BULLET_LIST ) {
for ( Bullet * b : bulletsLower ) {
b - > Draw ( ) ;
}
# pragma region Foreground Rendering
@ -855,18 +877,23 @@ void Crawler::RenderWorld(float fElapsedTime){
}
}
# pragma endregion
for ( Monster & m : monstersBefore ) {
if ( m . OnUpperLevel ( ) ) {
m . Draw ( ) ;
}
for ( Effect * e : backgroundEffectsUpper ) {
e - > Draw ( ) ;
}
for ( Monster * m : monstersBeforeUpper ) {
m - > Draw ( ) ;
}
if ( player . upperLevel ) {
RENDER_PLAYER
}
for ( Monster & m : monstersAfter ) {
if ( m . OnUpperLevel ( ) ) {
m . Draw ( ) ;
}
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 ) {
@ -1057,6 +1084,15 @@ void Crawler::LoadLevel(MapName map){
}
}
}
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 ( ) ;
}
@ -1106,15 +1142,26 @@ bool Crawler::IsBridgeLayer(LayerTag&layer){
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 ;
//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 ( ) & & ! upperLevel ; } ;
auto BridgeCollisionIsActivated = [ & ] ( ) { return ( IsBridgeLayer ( layer ) & & upperLevel ) ; } ;
if ( HasNoClass ( ) | | BridgeCollisionIsActivated ( ) ) {
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 ;
}