2010-11-20 10:37:14 +00:00
/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
/* If you are missing that file, acquire a complete release at teeworlds.com. */
2008-08-14 17:19:13 +00:00
# include <base/system.h>
2010-05-29 07:25:38 +00:00
# include <base/math.h>
# include <base/vmath.h>
2008-08-14 17:19:13 +00:00
2007-08-22 07:52:33 +00:00
# include <math.h>
2010-05-29 07:25:38 +00:00
# include <engine/map.h>
# include <engine/kernel.h>
2008-01-13 11:15:32 +00:00
2010-05-29 07:25:38 +00:00
# include <game/mapitems.h>
# include <game/layers.h>
# include <game/collision.h>
2008-01-13 11:15:32 +00:00
2011-03-16 15:36:54 +00:00
# include <engine/shared/config.h>
2008-01-13 11:15:32 +00:00
2010-05-29 07:25:38 +00:00
CCollision : : CCollision ( )
{
m_pTiles = 0 ;
m_Width = 0 ;
m_Height = 0 ;
m_pLayers = 0 ;
2010-10-06 21:44:10 +00:00
2010-10-27 10:14:26 +00:00
m_pTele = 0 ;
m_pSpeedup = 0 ;
m_pFront = 0 ;
m_pSwitch = 0 ;
2010-10-06 21:44:10 +00:00
m_pDoor = 0 ;
2010-11-13 13:22:19 +00:00
m_pSwitchers = 0 ;
2014-03-12 22:12:50 +00:00
m_pTune = 0 ;
2010-05-29 07:25:38 +00:00
}
2008-01-13 11:15:32 +00:00
2010-05-29 07:25:38 +00:00
void CCollision : : Init ( class CLayers * pLayers )
2008-01-13 11:15:32 +00:00
{
2010-11-04 20:06:12 +00:00
if ( m_pLayers ) m_pLayers - > Dest ( ) ;
Dest ( ) ;
2010-11-22 20:43:22 +00:00
m_NumSwitchers = 0 ;
2010-05-29 07:25:38 +00:00
m_pLayers = pLayers ;
m_Width = m_pLayers - > GameLayer ( ) - > m_Width ;
m_Height = m_pLayers - > GameLayer ( ) - > m_Height ;
m_pTiles = static_cast < CTile * > ( m_pLayers - > Map ( ) - > GetData ( m_pLayers - > GameLayer ( ) - > m_Data ) ) ;
2011-01-06 03:46:10 +00:00
2010-08-10 04:28:17 +00:00
if ( m_pLayers - > TeleLayer ( ) )
2014-01-10 23:46:32 +00:00
{
2014-01-10 23:54:52 +00:00
unsigned int Size = m_pLayers - > Map ( ) - > GetUncompressedDataSize ( m_pLayers - > TeleLayer ( ) - > m_Tele ) ;
2014-01-10 23:46:32 +00:00
if ( Size > = m_Width * m_Height * sizeof ( CTeleTile ) )
m_pTele = static_cast < CTeleTile * > ( m_pLayers - > Map ( ) - > GetData ( m_pLayers - > TeleLayer ( ) - > m_Tele ) ) ;
}
2011-04-09 06:41:31 +00:00
2010-08-10 04:28:17 +00:00
if ( m_pLayers - > SpeedupLayer ( ) )
2014-01-10 23:46:32 +00:00
{
2014-01-10 23:54:52 +00:00
unsigned int Size = m_pLayers - > Map ( ) - > GetUncompressedDataSize ( m_pLayers - > SpeedupLayer ( ) - > m_Speedup ) ;
2014-01-10 23:46:32 +00:00
if ( Size > = m_Width * m_Height * sizeof ( CSpeedupTile ) )
m_pSpeedup = static_cast < CSpeedupTile * > ( m_pLayers - > Map ( ) - > GetData ( m_pLayers - > SpeedupLayer ( ) - > m_Speedup ) ) ;
}
2011-04-09 06:41:31 +00:00
2010-08-27 23:30:50 +00:00
if ( m_pLayers - > SwitchLayer ( ) )
2010-09-25 16:39:52 +00:00
{
2014-01-10 23:54:52 +00:00
unsigned int Size = m_pLayers - > Map ( ) - > GetUncompressedDataSize ( m_pLayers - > SwitchLayer ( ) - > m_Switch ) ;
2014-01-10 23:46:32 +00:00
if ( Size > = m_Width * m_Height * sizeof ( CSwitchTile ) )
m_pSwitch = static_cast < CSwitchTile * > ( m_pLayers - > Map ( ) - > GetData ( m_pLayers - > SwitchLayer ( ) - > m_Switch ) ) ;
2010-09-25 16:39:52 +00:00
m_pDoor = new CDoorTile [ m_Width * m_Height ] ;
2011-01-29 23:58:47 +00:00
mem_zero ( m_pDoor , m_Width * m_Height * sizeof ( CDoorTile ) ) ;
2010-09-25 16:39:52 +00:00
}
2010-09-27 03:15:56 +00:00
else
2010-11-13 13:22:19 +00:00
{
2010-09-27 03:15:56 +00:00
m_pDoor = 0 ;
2010-11-13 13:22:19 +00:00
m_pSwitchers = 0 ;
}
2011-04-09 06:41:31 +00:00
2014-03-12 22:12:50 +00:00
if ( m_pLayers - > TuneLayer ( ) )
{
unsigned int Size = m_pLayers - > Map ( ) - > GetUncompressedDataSize ( m_pLayers - > TuneLayer ( ) - > m_Tune ) ;
if ( Size > = m_Width * m_Height * sizeof ( CTuneTile ) )
m_pTune = static_cast < CTuneTile * > ( m_pLayers - > Map ( ) - > GetData ( m_pLayers - > TuneLayer ( ) - > m_Tune ) ) ;
}
2010-08-10 04:28:17 +00:00
if ( m_pLayers - > FrontLayer ( ) )
2014-01-10 23:46:32 +00:00
{
2014-01-10 23:54:52 +00:00
unsigned int Size = m_pLayers - > Map ( ) - > GetUncompressedDataSize ( m_pLayers - > FrontLayer ( ) - > m_Front ) ;
if ( Size > = m_Width * m_Height * sizeof ( CTile ) )
2014-01-10 23:46:32 +00:00
m_pFront = static_cast < CTile * > ( m_pLayers - > Map ( ) - > GetData ( m_pLayers - > FrontLayer ( ) - > m_Front ) ) ;
}
2010-08-15 14:42:40 +00:00
2010-05-29 07:25:38 +00:00
for ( int i = 0 ; i < m_Width * m_Height ; i + + )
2008-09-23 14:38:13 +00:00
{
2010-11-13 13:22:19 +00:00
int Index ;
if ( m_pSwitch )
2010-05-29 07:25:38 +00:00
{
2010-11-22 20:43:22 +00:00
if ( m_pSwitch [ i ] . m_Number > m_NumSwitchers )
m_NumSwitchers = m_pSwitch [ i ] . m_Number ;
2011-04-09 06:41:31 +00:00
2010-11-13 13:22:19 +00:00
if ( m_pSwitch [ i ] . m_Number )
m_pDoor [ i ] . m_Number = m_pSwitch [ i ] . m_Number ;
else
m_pDoor [ i ] . m_Number = 0 ;
2010-11-14 17:33:12 +00:00
Index = m_pSwitch [ i ] . m_Type ;
2011-04-09 06:41:31 +00:00
2013-08-14 02:24:29 +00:00
if ( Index < = TILE_NPH_START )
2010-11-15 09:33:21 +00:00
{
2014-02-09 22:31:29 +00:00
if ( Index > = TILE_JUMP & & Index < = TILE_PENALTY )
2010-11-15 09:33:21 +00:00
m_pSwitch [ i ] . m_Type = Index ;
else
m_pSwitch [ i ] . m_Type = 0 ;
}
2010-11-13 13:22:19 +00:00
}
if ( m_pFront )
{
Index = m_pFront [ i ] . m_Index ;
2011-04-09 06:41:31 +00:00
2013-08-14 02:24:29 +00:00
if ( Index < = TILE_NPH_START )
2010-11-13 13:22:19 +00:00
{
2010-11-15 09:33:21 +00:00
switch ( Index )
{
case TILE_DEATH :
m_pFront [ i ] . m_Index = COLFLAG_DEATH ;
break ;
case TILE_SOLID :
m_pFront [ i ] . m_Index = 0 ;
break ;
case TILE_NOHOOK :
m_pFront [ i ] . m_Index = 0 ;
break ;
case TILE_NOLASER :
m_pFront [ i ] . m_Index = COLFLAG_NOLASER ;
break ;
default :
m_pFront [ i ] . m_Index = 0 ;
}
2010-11-13 13:22:19 +00:00
2010-11-15 09:33:21 +00:00
// DDRace tiles
2014-06-21 16:14:22 +00:00
if ( Index = = TILE_THROUGH | | Index = = TILE_WALLJUMP | | ( Index > = TILE_FREEZE & & Index < = TILE_UNFREEZE ) | | ( Index > = TILE_SWITCHOPEN & & Index < = TILE_TELECHECKIN ) | | ( Index > = TILE_BEGIN & & Index < = TILE_STOPA ) | | Index = = TILE_CP | | Index = = TILE_CP_F | | ( Index > = TILE_OLDLASER & & Index < = TILE_NPH_START ) | | ( Index > = TILE_EHOOK_START & & Index < = TILE_SOLO_END ) | | ( Index > = TILE_DFREEZE & & Index < = TILE_DUNFREEZE ) )
2010-11-15 09:33:21 +00:00
m_pFront [ i ] . m_Index = Index ;
}
2010-05-29 07:25:38 +00:00
}
2010-11-13 13:22:19 +00:00
Index = m_pTiles [ i ] . m_Index ;
2013-08-14 02:24:29 +00:00
if ( Index < = TILE_NPH_START )
2010-11-13 13:22:19 +00:00
{
switch ( Index )
{
case TILE_DEATH :
m_pTiles [ i ] . m_Index = COLFLAG_DEATH ;
break ;
case TILE_SOLID :
m_pTiles [ i ] . m_Index = COLFLAG_SOLID ;
break ;
case TILE_NOHOOK :
m_pTiles [ i ] . m_Index = COLFLAG_SOLID | COLFLAG_NOHOOK ;
break ;
case TILE_NOLASER :
m_pTiles [ i ] . m_Index = COLFLAG_NOLASER ;
break ;
default :
m_pTiles [ i ] . m_Index = 0 ;
}
2010-08-15 14:42:40 +00:00
2010-11-13 13:22:19 +00:00
// DDRace tiles
2014-06-21 16:14:22 +00:00
if ( Index = = TILE_THROUGH | | Index = = TILE_WALLJUMP | | ( Index > = TILE_FREEZE & & Index < = TILE_UNFREEZE ) | | ( Index > = TILE_SWITCHOPEN & & Index < = TILE_TELECHECKIN ) | | ( Index > = TILE_BEGIN & & Index < = TILE_STOPA ) | | Index = = TILE_CP | | Index = = TILE_CP_F | | ( Index > = TILE_OLDLASER & & Index < = TILE_NPH_START ) | | ( Index > = TILE_EHOOK_START & & Index < = TILE_SOLO_END ) | | ( Index > = TILE_DFREEZE & & Index < = TILE_DUNFREEZE ) )
2010-11-13 13:22:19 +00:00
m_pTiles [ i ] . m_Index = Index ;
}
}
2010-11-22 20:43:22 +00:00
if ( m_NumSwitchers )
2010-11-13 13:22:19 +00:00
{
2010-11-22 20:43:22 +00:00
m_pSwitchers = new SSwitchers [ m_NumSwitchers + 1 ] ;
2011-04-09 06:41:31 +00:00
2010-11-22 20:43:22 +00:00
for ( int i = 0 ; i < m_NumSwitchers + 1 ; + + i )
2010-11-13 13:22:19 +00:00
{
2014-01-01 21:34:10 +00:00
for ( int j = 0 ; j < MAX_CLIENTS ; + + j )
2010-11-13 13:22:19 +00:00
{
m_pSwitchers [ i ] . m_Status [ j ] = true ;
2010-11-22 20:43:22 +00:00
m_pSwitchers [ i ] . m_EndTick [ j ] = 0 ;
m_pSwitchers [ i ] . m_Type [ j ] = 0 ;
2010-11-13 13:22:19 +00:00
}
}
2008-09-23 14:38:13 +00:00
}
2008-01-13 11:15:32 +00:00
}
2011-02-13 06:47:51 +00:00
int CCollision : : GetTile ( int x , int y )
2010-09-22 15:07:45 +00:00
{
2011-02-13 06:47:51 +00:00
int Nx = clamp ( x / 32 , 0 , m_Width - 1 ) ;
int Ny = clamp ( y / 32 , 0 , m_Height - 1 ) ;
2011-02-13 05:35:13 +00:00
if ( ! m_pTiles | | Ny < 0 | | Nx < 0 )
2011-01-06 03:46:10 +00:00
return 0 ;
2011-04-13 18:37:12 +00:00
2011-02-13 05:35:13 +00:00
if ( m_pTiles [ Ny * m_Width + Nx ] . m_Index = = COLFLAG_SOLID
| | m_pTiles [ Ny * m_Width + Nx ] . m_Index = = ( COLFLAG_SOLID | COLFLAG_NOHOOK )
| | m_pTiles [ Ny * m_Width + Nx ] . m_Index = = COLFLAG_DEATH
| | m_pTiles [ Ny * m_Width + Nx ] . m_Index = = COLFLAG_NOLASER )
return m_pTiles [ Ny * m_Width + Nx ] . m_Index ;
2011-04-09 06:41:31 +00:00
return 0 ;
2010-09-22 15:07:45 +00:00
}
2011-01-07 23:26:17 +00:00
/*
bool CCollision : : IsTileSolid ( int x , int y )
2010-09-26 02:25:05 +00:00
{
2011-02-13 06:47:51 +00:00
return GetTile ( x , y ) & COLFLAG_SOLID ;
2011-01-07 23:26:17 +00:00
}
*/
2008-01-13 11:15:32 +00:00
// TODO: rewrite this smarter!
2011-01-06 03:46:10 +00:00
int CCollision : : IntersectLine ( vec2 Pos0 , vec2 Pos1 , vec2 * pOutCollision , vec2 * pOutBeforeCollision , bool AllowThrough )
{
2011-02-13 06:47:51 +00:00
float Distance = distance ( Pos0 , Pos1 ) ;
int End ( Distance + 1 ) ;
2011-01-06 03:46:10 +00:00
vec2 Last = Pos0 ;
2011-02-05 04:23:56 +00:00
int ix = 0 , iy = 0 ; // Temporary position for checking collision
int dx = 0 , dy = 0 ; // Offset for checking the "through" tile
2011-01-07 23:26:17 +00:00
if ( AllowThrough )
{
2011-02-05 04:23:56 +00:00
ThroughOffset ( Pos0 , Pos1 , & dx , & dy ) ;
2011-01-07 23:26:17 +00:00
}
2014-04-30 14:06:34 +00:00
for ( int i = 0 ; i < = End ; i + + )
2010-09-26 02:25:05 +00:00
{
2014-04-30 14:06:34 +00:00
float a = i / ( float ) End ;
2011-02-13 06:53:25 +00:00
vec2 Pos = mix ( Pos0 , Pos1 , a ) ;
2014-04-22 21:46:55 +00:00
ix = round_to_int ( Pos . x ) ;
iy = round_to_int ( Pos . y ) ;
2013-07-18 22:27:17 +00:00
if ( ( CheckPoint ( ix , iy ) & & ! ( AllowThrough & & IsThrough ( ix + dx , iy + dy ) ) ) )
{
if ( pOutCollision )
* pOutCollision = Pos ;
if ( pOutBeforeCollision )
* pOutBeforeCollision = Last ;
return GetCollisionAt ( ix , iy ) ;
}
Last = Pos ;
}
if ( pOutCollision )
* pOutCollision = Pos1 ;
if ( pOutBeforeCollision )
* pOutBeforeCollision = Pos1 ;
return 0 ;
}
2013-08-13 02:59:25 +00:00
int CCollision : : IntersectLineTeleHook ( vec2 Pos0 , vec2 Pos1 , vec2 * pOutCollision , vec2 * pOutBeforeCollision , int * pTeleNr , bool AllowThrough )
2013-07-18 22:27:17 +00:00
{
float Distance = distance ( Pos0 , Pos1 ) ;
int End ( Distance + 1 ) ;
vec2 Last = Pos0 ;
int ix = 0 , iy = 0 ; // Temporary position for checking collision
int dx = 0 , dy = 0 ; // Offset for checking the "through" tile
if ( AllowThrough )
{
ThroughOffset ( Pos0 , Pos1 , & dx , & dy ) ;
}
2014-04-30 14:06:34 +00:00
for ( int i = 0 ; i < = End ; i + + )
2013-07-18 22:27:17 +00:00
{
2014-04-30 14:06:34 +00:00
float a = i / ( float ) End ;
2013-07-18 22:27:17 +00:00
vec2 Pos = mix ( Pos0 , Pos1 , a ) ;
2014-04-22 21:46:55 +00:00
ix = round_to_int ( Pos . x ) ;
iy = round_to_int ( Pos . y ) ;
2013-07-18 22:27:17 +00:00
int Nx = clamp ( ix / 32 , 0 , m_Width - 1 ) ;
int Ny = clamp ( iy / 32 , 0 , m_Height - 1 ) ;
2013-08-13 02:59:25 +00:00
if ( g_Config . m_SvOldTeleportHook )
* pTeleNr = IsTeleport ( Ny * m_Width + Nx ) ;
else
* pTeleNr = IsTeleportHook ( Ny * m_Width + Nx ) ;
if ( * pTeleNr )
{
if ( pOutCollision )
* pOutCollision = Pos ;
if ( pOutBeforeCollision )
* pOutBeforeCollision = Last ;
return COLFLAG_TELE ;
}
if ( ( CheckPoint ( ix , iy ) & & ! ( AllowThrough & & IsThrough ( ix + dx , iy + dy ) ) ) )
{
if ( pOutCollision )
* pOutCollision = Pos ;
if ( pOutBeforeCollision )
* pOutBeforeCollision = Last ;
return GetCollisionAt ( ix , iy ) ;
}
Last = Pos ;
}
if ( pOutCollision )
* pOutCollision = Pos1 ;
if ( pOutBeforeCollision )
* pOutBeforeCollision = Pos1 ;
return 0 ;
}
int CCollision : : IntersectLineTeleWeapon ( vec2 Pos0 , vec2 Pos1 , vec2 * pOutCollision , vec2 * pOutBeforeCollision , int * pTeleNr , bool AllowThrough )
{
float Distance = distance ( Pos0 , Pos1 ) ;
int End ( Distance + 1 ) ;
vec2 Last = Pos0 ;
int ix = 0 , iy = 0 ; // Temporary position for checking collision
int dx = 0 , dy = 0 ; // Offset for checking the "through" tile
if ( AllowThrough )
{
ThroughOffset ( Pos0 , Pos1 , & dx , & dy ) ;
}
2014-04-30 14:06:34 +00:00
for ( int i = 0 ; i < = End ; i + + )
2013-08-13 02:59:25 +00:00
{
2014-04-30 14:06:34 +00:00
float a = i / ( float ) End ;
2013-08-13 02:59:25 +00:00
vec2 Pos = mix ( Pos0 , Pos1 , a ) ;
2014-04-22 21:46:55 +00:00
ix = round_to_int ( Pos . x ) ;
iy = round_to_int ( Pos . y ) ;
2013-08-13 02:59:25 +00:00
int Nx = clamp ( ix / 32 , 0 , m_Width - 1 ) ;
int Ny = clamp ( iy / 32 , 0 , m_Height - 1 ) ;
if ( g_Config . m_SvOldTeleportWeapons )
* pTeleNr = IsTeleport ( Ny * m_Width + Nx ) ;
else
* pTeleNr = IsTeleportWeapon ( Ny * m_Width + Nx ) ;
2013-07-18 22:27:17 +00:00
if ( * pTeleNr )
{
if ( pOutCollision )
* pOutCollision = Pos ;
if ( pOutBeforeCollision )
* pOutBeforeCollision = Last ;
return COLFLAG_TELE ;
}
if ( ( CheckPoint ( ix , iy ) & & ! ( AllowThrough & & IsThrough ( ix + dx , iy + dy ) ) ) )
2010-09-26 02:25:05 +00:00
{
2011-01-06 03:46:10 +00:00
if ( pOutCollision )
* pOutCollision = Pos ;
if ( pOutBeforeCollision )
* pOutBeforeCollision = Last ;
2011-01-07 23:26:17 +00:00
return GetCollisionAt ( ix , iy ) ;
2010-09-26 02:25:05 +00:00
}
2013-07-18 22:27:17 +00:00
2011-01-06 03:46:10 +00:00
Last = Pos ;
2010-09-26 02:25:05 +00:00
}
2011-01-06 03:46:10 +00:00
if ( pOutCollision )
* pOutCollision = Pos1 ;
if ( pOutBeforeCollision )
* pOutBeforeCollision = Pos1 ;
return 0 ;
}
2010-09-26 02:25:05 +00:00
2011-01-06 03:46:10 +00:00
// TODO: OPT: rewrite this smarter!
void CCollision : : MovePoint ( vec2 * pInoutPos , vec2 * pInoutVel , float Elasticity , int * pBounces )
{
if ( pBounces )
* pBounces = 0 ;
2011-04-13 18:37:12 +00:00
2011-01-06 03:46:10 +00:00
vec2 Pos = * pInoutPos ;
vec2 Vel = * pInoutVel ;
if ( CheckPoint ( Pos + Vel ) )
2010-09-26 02:25:05 +00:00
{
2011-01-06 03:46:10 +00:00
int Affected = 0 ;
if ( CheckPoint ( Pos . x + Vel . x , Pos . y ) )
2010-09-26 02:25:05 +00:00
{
2011-01-06 03:46:10 +00:00
pInoutVel - > x * = - Elasticity ;
if ( pBounces )
2011-04-13 18:37:12 +00:00
( * pBounces ) + + ;
2011-01-06 03:46:10 +00:00
Affected + + ;
}
if ( CheckPoint ( Pos . x , Pos . y + Vel . y ) )
{
pInoutVel - > y * = - Elasticity ;
if ( pBounces )
2011-04-13 18:37:12 +00:00
( * pBounces ) + + ;
2011-01-06 03:46:10 +00:00
Affected + + ;
2010-09-26 02:25:05 +00:00
}
2011-04-13 18:37:12 +00:00
2011-01-06 03:46:10 +00:00
if ( Affected = = 0 )
{
pInoutVel - > x * = - Elasticity ;
pInoutVel - > y * = - Elasticity ;
}
}
else
{
* pInoutPos = Pos + Vel ;
2010-09-26 02:25:05 +00:00
}
2011-01-06 03:46:10 +00:00
}
2010-09-26 02:25:05 +00:00
2011-01-06 03:46:10 +00:00
bool CCollision : : TestBox ( vec2 Pos , vec2 Size )
{
Size * = 0.5f ;
if ( CheckPoint ( Pos . x - Size . x , Pos . y - Size . y ) )
return true ;
if ( CheckPoint ( Pos . x + Size . x , Pos . y - Size . y ) )
return true ;
if ( CheckPoint ( Pos . x - Size . x , Pos . y + Size . y ) )
return true ;
if ( CheckPoint ( Pos . x + Size . x , Pos . y + Size . y ) )
return true ;
return false ;
2010-09-26 02:25:05 +00:00
}
2011-01-06 03:46:10 +00:00
void CCollision : : MoveBox ( vec2 * pInoutPos , vec2 * pInoutVel , vec2 Size , float Elasticity )
2010-08-10 04:28:17 +00:00
{
2011-01-06 03:46:10 +00:00
// do the move
vec2 Pos = * pInoutPos ;
vec2 Vel = * pInoutVel ;
2011-04-13 18:37:12 +00:00
2011-01-06 03:46:10 +00:00
float Distance = length ( Vel ) ;
int Max = ( int ) Distance ;
2011-04-13 18:37:12 +00:00
2011-01-06 03:46:10 +00:00
if ( Distance > 0.00001f )
{
//vec2 old_pos = pos;
float Fraction = 1.0f / ( float ) ( Max + 1 ) ;
for ( int i = 0 ; i < = Max ; i + + )
{
//float amount = i/(float)max;
//if(max == 0)
//amount = 0;
2011-04-13 18:37:12 +00:00
2011-01-06 03:46:10 +00:00
vec2 NewPos = Pos + Vel * Fraction ; // TODO: this row is not nice
2011-04-13 18:37:12 +00:00
2011-01-06 03:46:10 +00:00
if ( TestBox ( vec2 ( NewPos . x , NewPos . y ) , Size ) )
{
int Hits = 0 ;
2011-04-13 18:37:12 +00:00
2011-01-06 03:46:10 +00:00
if ( TestBox ( vec2 ( Pos . x , NewPos . y ) , Size ) )
{
NewPos . y = Pos . y ;
Vel . y * = - Elasticity ;
Hits + + ;
}
2011-04-13 18:37:12 +00:00
2011-01-06 03:46:10 +00:00
if ( TestBox ( vec2 ( NewPos . x , Pos . y ) , Size ) )
{
NewPos . x = Pos . x ;
Vel . x * = - Elasticity ;
Hits + + ;
}
2011-04-13 18:37:12 +00:00
2011-01-06 03:46:10 +00:00
// neither of the tests got a collision.
// this is a real _corner case_!
if ( Hits = = 0 )
{
NewPos . y = Pos . y ;
Vel . y * = - Elasticity ;
NewPos . x = Pos . x ;
Vel . x * = - Elasticity ;
}
}
2011-04-13 18:37:12 +00:00
2011-01-06 03:46:10 +00:00
Pos = NewPos ;
}
}
2011-04-13 18:37:12 +00:00
2011-01-06 03:46:10 +00:00
* pInoutPos = Pos ;
* pInoutVel = Vel ;
}
2010-08-21 19:48:47 +00:00
2011-04-09 06:41:31 +00:00
// DDRace
void CCollision : : Dest ( )
{
if ( m_pDoor )
delete [ ] m_pDoor ;
if ( m_pSwitchers )
delete [ ] m_pSwitchers ;
m_pTiles = 0 ;
m_Width = 0 ;
m_Height = 0 ;
m_pLayers = 0 ;
m_pTele = 0 ;
m_pSpeedup = 0 ;
m_pFront = 0 ;
m_pSwitch = 0 ;
2014-03-12 22:12:50 +00:00
m_pTune = 0 ;
2011-04-09 06:41:31 +00:00
m_pDoor = 0 ;
m_pSwitchers = 0 ;
}
2011-01-06 03:46:10 +00:00
int CCollision : : IsSolid ( int x , int y )
{
return ( GetTile ( x , y ) & COLFLAG_SOLID ) ;
2010-08-10 04:28:17 +00:00
}
2011-01-06 03:46:10 +00:00
int CCollision : : IsThrough ( int x , int y )
2010-08-10 04:28:17 +00:00
{
2011-02-13 05:35:13 +00:00
int Nx = clamp ( x / 32 , 0 , m_Width - 1 ) ;
int Ny = clamp ( y / 32 , 0 , m_Height - 1 ) ;
int Index = m_pTiles [ Ny * m_Width + Nx ] . m_Index ;
2011-01-06 03:46:10 +00:00
int Findex = 0 ;
if ( m_pFront )
2011-02-13 05:35:13 +00:00
Findex = m_pFront [ Ny * m_Width + Nx ] . m_Index ;
2011-08-13 00:12:40 +00:00
if ( Index = = TILE_THROUGH )
return Index ;
if ( Findex = = TILE_THROUGH )
return Findex ;
2011-03-16 15:36:54 +00:00
return 0 ;
2010-08-10 04:28:17 +00:00
}
2010-09-25 16:39:52 +00:00
2014-06-21 16:14:22 +00:00
int CCollision : : IsWallJump ( int Index )
{
if ( Index < 0 )
return 0 ;
return m_pTiles [ Index ] . m_Index = = TILE_WALLJUMP ;
}
2011-01-06 03:46:10 +00:00
int CCollision : : IsNoLaser ( int x , int y )
2010-08-20 20:40:12 +00:00
{
2011-08-31 00:28:43 +00:00
return ( CCollision : : GetTile ( x , y ) & COLFLAG_NOLASER ) ;
2011-01-06 03:46:10 +00:00
}
2010-08-21 02:20:01 +00:00
2011-01-06 03:46:10 +00:00
int CCollision : : IsFNoLaser ( int x , int y )
{
2011-08-31 00:28:43 +00:00
return ( CCollision : : GetFTile ( x , y ) & COLFLAG_NOLASER ) ;
2010-08-20 20:40:12 +00:00
}
2010-07-29 05:21:18 +00:00
2011-01-06 03:46:10 +00:00
int CCollision : : IsTeleport ( int Index )
2010-11-01 01:51:17 +00:00
{
2011-01-30 18:07:02 +00:00
if ( Index < 0 | | ! m_pTele )
2011-01-06 03:46:10 +00:00
return 0 ;
if ( m_pTele [ Index ] . m_Type = = TILE_TELEIN )
2011-01-30 18:07:02 +00:00
return m_pTele [ Index ] . m_Number ;
2011-01-06 03:46:10 +00:00
2011-01-30 18:07:02 +00:00
return 0 ;
2010-11-01 01:51:17 +00:00
}
2011-01-06 03:46:10 +00:00
int CCollision : : IsEvilTeleport ( int Index )
2010-11-01 01:51:17 +00:00
{
2011-01-06 03:46:10 +00:00
if ( Index < 0 )
return 0 ;
if ( ! m_pTele )
2010-11-01 01:51:17 +00:00
return 0 ;
2011-01-06 03:46:10 +00:00
if ( m_pTele [ Index ] . m_Type = = TILE_TELEINEVIL )
2011-01-30 18:07:02 +00:00
return m_pTele [ Index ] . m_Number ;
return 0 ;
2010-11-05 11:56:44 +00:00
}
2011-05-17 23:12:39 +00:00
int CCollision : : IsCheckTeleport ( int Index )
{
if ( Index < 0 )
return 0 ;
if ( ! m_pTele )
return 0 ;
if ( m_pTele [ Index ] . m_Type = = TILE_TELECHECKIN )
return m_pTele [ Index ] . m_Number ;
return 0 ;
}
2014-02-01 21:20:41 +00:00
int CCollision : : IsCheckEvilTeleport ( int Index )
{
if ( Index < 0 )
return 0 ;
if ( ! m_pTele )
return 0 ;
if ( m_pTele [ Index ] . m_Type = = TILE_TELECHECKINEVIL )
return m_pTele [ Index ] . m_Number ;
return 0 ;
}
2011-05-17 23:12:39 +00:00
int CCollision : : IsTCheckpoint ( int Index )
{
if ( Index < 0 )
return 0 ;
if ( ! m_pTele )
return 0 ;
if ( m_pTele [ Index ] . m_Type = = TILE_TELECHECK )
return m_pTele [ Index ] . m_Number ;
return 0 ;
}
2013-08-13 02:59:25 +00:00
int CCollision : : IsTeleportWeapon ( int Index )
{
if ( Index < 0 | | ! m_pTele )
return 0 ;
if ( m_pTele [ Index ] . m_Type = = TILE_TELEINWEAPON )
return m_pTele [ Index ] . m_Number ;
return 0 ;
}
int CCollision : : IsTeleportHook ( int Index )
{
if ( Index < 0 | | ! m_pTele )
return 0 ;
if ( m_pTele [ Index ] . m_Type = = TILE_TELEINHOOK )
return m_pTele [ Index ] . m_Number ;
return 0 ;
}
2011-01-06 03:46:10 +00:00
int CCollision : : IsSpeedup ( int Index )
{
2011-01-30 18:07:02 +00:00
if ( Index < 0 | | ! m_pSpeedup )
2011-01-06 03:46:10 +00:00
return 0 ;
if ( m_pSpeedup [ Index ] . m_Force > 0 )
2011-01-21 17:59:52 +00:00
return Index ;
2011-01-06 03:46:10 +00:00
return 0 ;
2010-11-05 11:56:44 +00:00
}
2014-03-12 22:12:50 +00:00
int CCollision : : IsTune ( int Index )
{
if ( Index < 0 | | ! m_pTune )
2014-03-12 23:24:42 +00:00
return 0 ;
2014-03-12 22:12:50 +00:00
if ( m_pTune [ Index ] . m_Type )
return m_pTune [ Index ] . m_Number ;
2014-03-12 23:24:42 +00:00
return 0 ;
2014-03-12 22:12:50 +00:00
}
2011-01-06 03:46:10 +00:00
void CCollision : : GetSpeedup ( int Index , vec2 * Dir , int * Force , int * MaxSpeed )
{
2011-01-21 17:59:52 +00:00
if ( Index < 0 | | ! m_pSpeedup )
2011-01-06 03:46:10 +00:00
return ;
float Angle = m_pSpeedup [ Index ] . m_Angle * ( pi / 180.0f ) ;
* Force = m_pSpeedup [ Index ] . m_Force ;
* Dir = vec2 ( cos ( Angle ) , sin ( Angle ) ) ;
if ( MaxSpeed )
* MaxSpeed = m_pSpeedup [ Index ] . m_MaxSpeed ;
}
int CCollision : : IsSwitch ( int Index )
{
//dbg_msg("IsSwitch","Index %d, pSwitch %d, m_Type %d, m_Number %d", Index, m_pSwitch, (m_pSwitch)?m_pSwitch[Index].m_Type:0, (m_pSwitch)?m_pSwitch[Index].m_Number:0);
2011-01-30 18:07:02 +00:00
if ( Index < 0 | | ! m_pSwitch )
2011-01-06 03:46:10 +00:00
return 0 ;
2011-01-25 09:34:14 +00:00
if ( m_pSwitch [ Index ] . m_Type > 0 )
2011-01-06 03:46:10 +00:00
return m_pSwitch [ Index ] . m_Type ;
return 0 ;
}
int CCollision : : GetSwitchNumber ( int Index )
{
//dbg_msg("GetSwitchNumber","Index %d, pSwitch %d, m_Type %d, m_Number %d", Index, m_pSwitch, (m_pSwitch)?m_pSwitch[Index].m_Type:0, (m_pSwitch)?m_pSwitch[Index].m_Number:0);
2011-01-30 18:07:02 +00:00
if ( Index < 0 | | ! m_pSwitch )
2011-01-06 03:46:10 +00:00
return 0 ;
if ( m_pSwitch [ Index ] . m_Type > 0 & & m_pSwitch [ Index ] . m_Number > 0 )
return m_pSwitch [ Index ] . m_Number ;
return 0 ;
}
int CCollision : : GetSwitchDelay ( int Index )
{
//dbg_msg("GetSwitchNumber","Index %d, pSwitch %d, m_Type %d, m_Number %d", Index, m_pSwitch, (m_pSwitch)?m_pSwitch[Index].m_Type:0, (m_pSwitch)?m_pSwitch[Index].m_Number:0);
2011-01-30 18:07:02 +00:00
if ( Index < 0 | | ! m_pSwitch )
2011-01-06 03:46:10 +00:00
return 0 ;
2011-01-25 09:34:14 +00:00
if ( m_pSwitch [ Index ] . m_Type > 0 )
2011-01-06 03:46:10 +00:00
return m_pSwitch [ Index ] . m_Delay ;
return 0 ;
}
2011-01-21 13:18:50 +00:00
int CCollision : : IsMover ( int x , int y , int * Flags )
2008-01-13 11:15:32 +00:00
{
2011-02-13 05:35:13 +00:00
int Nx = clamp ( x / 32 , 0 , m_Width - 1 ) ;
int Ny = clamp ( y / 32 , 0 , m_Height - 1 ) ;
int Index = m_pTiles [ Ny * m_Width + Nx ] . m_Index ;
* Flags = m_pTiles [ Ny * m_Width + Nx ] . m_Flags ;
2011-01-06 03:46:10 +00:00
if ( Index < 0 )
return 0 ;
if ( Index = = TILE_CP | | Index = = TILE_CP_F )
return Index ;
else
return 0 ;
}
vec2 CCollision : : CpSpeed ( int Index , int Flags )
{
if ( Index < 0 )
return vec2 ( 0 , 0 ) ;
vec2 target ;
if ( Index = = TILE_CP | | Index = = TILE_CP_F )
switch ( Flags )
{
case ROTATION_0 :
target . x = 0 ;
target . y = - 4 ;
break ;
case ROTATION_90 :
target . x = 4 ;
target . y = 0 ;
break ;
case ROTATION_180 :
target . x = 0 ;
target . y = 4 ;
break ;
case ROTATION_270 :
target . x = - 4 ;
target . y = 0 ;
break ;
default :
target = vec2 ( 0 , 0 ) ;
break ;
}
if ( Index = = TILE_CP_F )
target * = 4 ;
return target ;
}
int CCollision : : GetPureMapIndex ( vec2 Pos )
{
2011-02-13 05:35:13 +00:00
int Nx = clamp ( ( int ) Pos . x / 32 , 0 , m_Width - 1 ) ;
int Ny = clamp ( ( int ) Pos . y / 32 , 0 , m_Height - 1 ) ;
return Ny * m_Width + Nx ;
2011-01-06 03:46:10 +00:00
}
2011-02-06 18:38:24 +00:00
bool CCollision : : TileExists ( int Index )
2011-02-10 00:08:13 +00:00
{
if ( Index < 0 )
return false ;
2013-08-14 02:24:29 +00:00
if ( m_pTiles [ Index ] . m_Index > = TILE_FREEZE & & m_pTiles [ Index ] . m_Index < = TILE_NPH_START )
2011-02-10 00:08:13 +00:00
return true ;
2013-08-14 02:24:29 +00:00
if ( m_pFront & & m_pFront [ Index ] . m_Index > = TILE_FREEZE & & m_pFront [ Index ] . m_Index < = TILE_NPH_START )
2011-02-10 00:08:13 +00:00
return true ;
2014-02-01 21:20:41 +00:00
if ( m_pTele & & ( m_pTele [ Index ] . m_Type = = TILE_TELEIN | | m_pTele [ Index ] . m_Type = = TILE_TELEINEVIL | | m_pTele [ Index ] . m_Type = = TILE_TELECHECKINEVIL | | m_pTele [ Index ] . m_Type = = TILE_TELECHECK | | m_pTele [ Index ] . m_Type = = TILE_TELECHECKIN ) )
2011-02-10 00:08:13 +00:00
return true ;
2011-02-10 00:20:02 +00:00
if ( m_pSpeedup & & m_pSpeedup [ Index ] . m_Force > 0 )
2011-02-10 00:08:13 +00:00
return true ;
2011-02-10 00:20:02 +00:00
if ( m_pDoor & & m_pDoor [ Index ] . m_Index )
2011-02-10 00:08:13 +00:00
return true ;
2011-02-10 00:20:02 +00:00
if ( m_pSwitch & & m_pSwitch [ Index ] . m_Type )
2011-02-10 00:08:13 +00:00
return true ;
2014-03-12 22:12:50 +00:00
if ( m_pTune & & m_pTune [ Index ] . m_Type )
return true ;
2011-02-10 00:20:02 +00:00
return TileExistsNext ( Index ) ;
2011-02-10 00:08:13 +00:00
}
bool CCollision : : TileExistsNext ( int Index )
2011-01-29 23:58:47 +00:00
{
2011-02-06 18:38:24 +00:00
if ( Index < 0 )
return false ;
int TileOnTheLeft = ( Index - 1 > 0 ) ? Index - 1 : Index ;
int TileOnTheRight = ( Index + 1 < m_Width * m_Height ) ? Index + 1 : Index ;
int TileBelow = ( Index + m_Width < m_Width * m_Height ) ? Index + m_Width : Index ;
int TileAbove = ( Index - m_Width > 0 ) ? Index - m_Width : Index ;
2011-02-10 00:08:13 +00:00
2011-02-10 00:20:02 +00:00
if ( ( m_pTiles [ TileOnTheRight ] . m_Index = = TILE_STOP & & m_pTiles [ TileOnTheRight ] . m_Flags = = ROTATION_270 ) | | ( m_pTiles [ TileOnTheLeft ] . m_Index = = TILE_STOP & & m_pTiles [ TileOnTheLeft ] . m_Flags = = ROTATION_90 ) )
2011-02-10 00:08:13 +00:00
return true ;
2011-02-10 02:47:11 +00:00
if ( ( m_pTiles [ TileBelow ] . m_Index = = TILE_STOP & & m_pTiles [ TileBelow ] . m_Flags = = ROTATION_0 ) | | ( m_pTiles [ TileAbove ] . m_Index = = TILE_STOP & & m_pTiles [ TileAbove ] . m_Flags = = ROTATION_180 ) )
2011-02-10 00:08:13 +00:00
return true ;
2011-02-10 00:20:02 +00:00
if ( m_pTiles [ TileOnTheRight ] . m_Index = = TILE_STOPA | | m_pTiles [ TileOnTheLeft ] . m_Index = = TILE_STOPA | | ( ( m_pTiles [ TileOnTheRight ] . m_Index = = TILE_STOPS | | m_pTiles [ TileOnTheLeft ] . m_Index = = TILE_STOPS ) & & m_pTiles [ TileOnTheRight ] . m_Flags | ROTATION_270 | ROTATION_90 ) )
2011-02-10 00:08:13 +00:00
return true ;
2011-02-10 00:20:02 +00:00
if ( m_pTiles [ TileBelow ] . m_Index = = TILE_STOPA | | m_pTiles [ TileAbove ] . m_Index = = TILE_STOPA | | ( ( m_pTiles [ TileBelow ] . m_Index = = TILE_STOPS | | m_pTiles [ TileAbove ] . m_Index = = TILE_STOPS ) & & m_pTiles [ TileBelow ] . m_Flags | ROTATION_180 | ROTATION_0 ) )
2011-01-30 17:03:22 +00:00
return true ;
2011-02-10 00:20:02 +00:00
if ( m_pFront )
{
if ( m_pFront [ TileOnTheRight ] . m_Index = = TILE_STOPA | | m_pFront [ TileOnTheLeft ] . m_Index = = TILE_STOPA | | ( ( m_pFront [ TileOnTheRight ] . m_Index = = TILE_STOPS | | m_pFront [ TileOnTheLeft ] . m_Index = = TILE_STOPS ) & & m_pFront [ TileOnTheRight ] . m_Flags | ROTATION_270 | ROTATION_90 ) )
return true ;
if ( m_pFront [ TileBelow ] . m_Index = = TILE_STOPA | | m_pFront [ TileAbove ] . m_Index = = TILE_STOPA | | ( ( m_pFront [ TileBelow ] . m_Index = = TILE_STOPS | | m_pFront [ TileAbove ] . m_Index = = TILE_STOPS ) & & m_pFront [ TileBelow ] . m_Flags | ROTATION_180 | ROTATION_0 ) )
return true ;
if ( ( m_pFront [ TileOnTheRight ] . m_Index = = TILE_STOP & & m_pFront [ TileOnTheRight ] . m_Flags = = ROTATION_270 ) | | ( m_pFront [ TileOnTheLeft ] . m_Index = = TILE_STOP & & m_pFront [ TileOnTheLeft ] . m_Flags = = ROTATION_90 ) )
return true ;
2011-02-10 02:47:11 +00:00
if ( ( m_pFront [ TileBelow ] . m_Index = = TILE_STOP & & m_pFront [ TileBelow ] . m_Flags = = ROTATION_0 ) | | ( m_pFront [ TileAbove ] . m_Index = = TILE_STOP & & m_pFront [ TileAbove ] . m_Flags = = ROTATION_180 ) )
2011-02-10 00:20:02 +00:00
return true ;
}
if ( m_pDoor )
{
if ( m_pDoor [ TileOnTheRight ] . m_Index = = TILE_STOPA | | m_pDoor [ TileOnTheLeft ] . m_Index = = TILE_STOPA | | ( ( m_pDoor [ TileOnTheRight ] . m_Index = = TILE_STOPS | | m_pDoor [ TileOnTheLeft ] . m_Index = = TILE_STOPS ) & & m_pDoor [ TileOnTheRight ] . m_Flags | ROTATION_270 | ROTATION_90 ) )
return true ;
if ( m_pDoor [ TileBelow ] . m_Index = = TILE_STOPA | | m_pDoor [ TileAbove ] . m_Index = = TILE_STOPA | | ( ( m_pDoor [ TileBelow ] . m_Index = = TILE_STOPS | | m_pDoor [ TileAbove ] . m_Index = = TILE_STOPS ) & & m_pDoor [ TileBelow ] . m_Flags | ROTATION_180 | ROTATION_0 ) )
return true ;
if ( ( m_pDoor [ TileOnTheRight ] . m_Index = = TILE_STOP & & m_pDoor [ TileOnTheRight ] . m_Flags = = ROTATION_270 ) | | ( m_pDoor [ TileOnTheLeft ] . m_Index = = TILE_STOP & & m_pDoor [ TileOnTheLeft ] . m_Flags = = ROTATION_90 ) )
return true ;
2011-02-10 02:47:11 +00:00
if ( ( m_pDoor [ TileBelow ] . m_Index = = TILE_STOP & & m_pDoor [ TileBelow ] . m_Flags = = ROTATION_0 ) | | ( m_pDoor [ TileAbove ] . m_Index = = TILE_STOP & & m_pDoor [ TileAbove ] . m_Flags = = ROTATION_180 ) )
2011-02-10 00:20:02 +00:00
return true ;
}
return false ;
2011-01-30 17:03:22 +00:00
}
int CCollision : : GetMapIndex ( vec2 Pos )
{
2011-02-13 05:35:13 +00:00
int Nx = clamp ( ( int ) Pos . x / 32 , 0 , m_Width - 1 ) ;
int Ny = clamp ( ( int ) Pos . y / 32 , 0 , m_Height - 1 ) ;
int Index = Ny * m_Width + Nx ;
2011-01-30 17:03:22 +00:00
/*if (m_pTele && (m_pTele[Index].m_Type == TILE_TELEIN)) dbg_msg("m_pTele && TELEIN","Index %d",Index);
else if ( m_pTele & & m_pTele [ Index ] . m_Type = = TILE_TELEOUT ) dbg_msg ( " TELEOUT " , " Index %d " , Index ) ;
else dbg_msg ( " GetMapIndex( " , " Index %d " , Index ) ; //REMOVE */
if ( TileExists ( Index ) )
2011-01-29 23:58:47 +00:00
return Index ;
else
return - 1 ;
}
2011-01-06 03:46:10 +00:00
std : : list < int > CCollision : : GetMapIndices ( vec2 PrevPos , vec2 Pos , unsigned MaxIndices )
{
std : : list < int > Indices ;
float d = distance ( PrevPos , Pos ) ;
2011-01-29 23:58:47 +00:00
int End ( d + 1 ) ;
2011-01-06 03:46:10 +00:00
if ( ! d )
{
2011-02-13 05:35:13 +00:00
int Nx = clamp ( ( int ) Pos . x / 32 , 0 , m_Width - 1 ) ;
int Ny = clamp ( ( int ) Pos . y / 32 , 0 , m_Height - 1 ) ;
int Index = Ny * m_Width + Nx ;
2011-01-29 23:58:47 +00:00
/*if (m_pTele && (m_pTele[Index].m_Type == TILE_TELEIN)) dbg_msg("m_pTele && TELEIN","Index %d",Index);
else if ( m_pTele & & m_pTele [ Index ] . m_Type = = TILE_TELEOUT ) dbg_msg ( " TELEOUT " , " Index %d " , Index ) ;
else dbg_msg ( " GetMapIndex( " , " Index %d " , Index ) ; //REMOVE */
2011-01-06 03:46:10 +00:00
2011-01-30 17:03:22 +00:00
if ( TileExists ( Index ) )
2011-01-06 03:46:10 +00:00
{
2011-01-29 23:58:47 +00:00
Indices . push_back ( Index ) ;
2011-01-06 03:46:10 +00:00
return Indices ;
}
2011-02-01 12:01:05 +00:00
else
return Indices ;
2011-01-06 03:46:10 +00:00
}
2011-02-01 12:01:05 +00:00
else
2011-01-06 03:46:10 +00:00
{
2011-02-01 12:01:05 +00:00
float a = 0.0f ;
vec2 Tmp = vec2 ( 0 , 0 ) ;
2011-02-13 05:35:13 +00:00
int Nx = 0 ;
int Ny = 0 ;
2011-02-01 12:01:05 +00:00
int Index , LastIndex = 0 ;
for ( int i = 0 ; i < End ; i + + )
2011-01-06 03:46:10 +00:00
{
2011-02-01 12:01:05 +00:00
a = i / d ;
Tmp = mix ( PrevPos , Pos , a ) ;
2011-02-13 05:35:13 +00:00
Nx = clamp ( ( int ) Tmp . x / 32 , 0 , m_Width - 1 ) ;
Ny = clamp ( ( int ) Tmp . y / 32 , 0 , m_Height - 1 ) ;
Index = Ny * m_Width + Nx ;
2011-02-01 12:01:05 +00:00
//dbg_msg("lastindex","%d",LastIndex);
//dbg_msg("index","%d",Index);
if ( TileExists ( Index ) & & LastIndex ! = Index )
{
if ( MaxIndices & & Indices . size ( ) > MaxIndices )
return Indices ;
Indices . push_back ( Index ) ;
LastIndex = Index ;
//dbg_msg("pushed","%d",Index);
}
2011-01-06 03:46:10 +00:00
}
2011-02-01 12:01:05 +00:00
return Indices ;
}
2011-01-06 03:46:10 +00:00
}
vec2 CCollision : : GetPos ( int Index )
{
if ( Index < 0 )
return vec2 ( 0 , 0 ) ;
2011-01-30 18:07:02 +00:00
2011-01-06 03:46:10 +00:00
int x = Index % m_Width ;
int y = Index / m_Width ;
2011-01-30 18:07:02 +00:00
return vec2 ( x * 32 + 16 , y * 32 + 16 ) ;
2011-01-06 03:46:10 +00:00
}
int CCollision : : GetTileIndex ( int Index )
{
/*dbg_msg("GetTileIndex","m_pTiles[%d].m_Index = %d",Index,m_pTiles[Index].m_Index);//Remove*/
if ( Index < 0 )
2010-11-04 19:33:03 +00:00
return 0 ;
2011-01-06 03:46:10 +00:00
return m_pTiles [ Index ] . m_Index ;
2010-11-04 19:33:03 +00:00
}
2011-01-06 03:46:10 +00:00
int CCollision : : GetFTileIndex ( int Index )
{
/*dbg_msg("GetFTileIndex","m_pFront[%d].m_Index = %d",Index,m_pFront[Index].m_Index);//Remove*/
if ( Index < 0 | | ! m_pFront )
return 0 ;
return m_pFront [ Index ] . m_Index ;
}
int CCollision : : GetTileFlags ( int Index )
{
/*dbg_msg("GetTileIndex","m_pTiles[%d].m_Index = %d",Index,m_pTiles[Index].m_Index);//Remove*/
if ( Index < 0 )
2010-08-10 04:28:17 +00:00
return 0 ;
2011-01-06 03:46:10 +00:00
return m_pTiles [ Index ] . m_Flags ;
}
int CCollision : : GetFTileFlags ( int Index )
{
/*dbg_msg("GetFTileIndex","m_pFront[%d].m_Index = %d",Index,m_pFront[Index].m_Index);//Remove*/
if ( Index < 0 | | ! m_pFront )
return 0 ;
return m_pFront [ Index ] . m_Flags ;
}
2011-02-13 05:35:13 +00:00
int CCollision : : GetIndex ( int Nx , int Ny )
2011-01-29 23:58:47 +00:00
{
2011-02-13 05:35:13 +00:00
return m_pTiles [ Ny * m_Width + Nx ] . m_Index ;
2011-01-06 03:46:10 +00:00
}
2013-07-18 22:27:17 +00:00
int CCollision : : GetIndex ( vec2 Pos )
{
int nx = clamp ( ( int ) Pos . x / 32 , 0 , m_Width - 1 ) ;
int ny = clamp ( ( int ) Pos . y / 32 , 0 , m_Height - 1 ) ;
return ny * m_Width + nx ;
}
int CCollision : : GetIndex ( vec2 PrevPos , vec2 Pos )
{
float Distance = distance ( PrevPos , Pos ) ;
if ( ! Distance )
{
int Nx = clamp ( ( int ) Pos . x / 32 , 0 , m_Width - 1 ) ;
int Ny = clamp ( ( int ) Pos . y / 32 , 0 , m_Height - 1 ) ;
if ( ( m_pTele ) | |
( m_pSpeedup & & m_pSpeedup [ Ny * m_Width + Nx ] . m_Force > 0 ) )
{
return Ny * m_Width + Nx ;
}
}
float a = 0.0f ;
vec2 Tmp = vec2 ( 0 , 0 ) ;
int Nx = 0 ;
int Ny = 0 ;
for ( float f = 0 ; f < Distance ; f + + )
{
a = f / Distance ;
Tmp = mix ( PrevPos , Pos , a ) ;
Nx = clamp ( ( int ) Tmp . x / 32 , 0 , m_Width - 1 ) ;
Ny = clamp ( ( int ) Tmp . y / 32 , 0 , m_Height - 1 ) ;
if ( ( m_pTele ) | |
( m_pSpeedup & & m_pSpeedup [ Ny * m_Width + Nx ] . m_Force > 0 ) )
{
return Ny * m_Width + Nx ;
}
}
return - 1 ;
}
2011-02-13 05:35:13 +00:00
int CCollision : : GetFIndex ( int Nx , int Ny )
2011-01-29 23:58:47 +00:00
{
2011-01-06 03:46:10 +00:00
if ( ! m_pFront ) return 0 ;
2011-02-13 05:35:13 +00:00
return m_pFront [ Ny * m_Width + Nx ] . m_Index ;
2008-09-23 14:10:05 +00:00
}
2010-08-21 19:48:47 +00:00
int CCollision : : GetFTile ( int x , int y )
{
if ( ! m_pFront )
return 0 ;
2011-02-13 05:35:13 +00:00
int Nx = clamp ( x / 32 , 0 , m_Width - 1 ) ;
int Ny = clamp ( y / 32 , 0 , m_Height - 1 ) ;
/*dbg_msg("GetFTile","m_Index %d",m_pFront[Ny*m_Width+Nx].m_Index);//Remove */
if ( m_pFront [ Ny * m_Width + Nx ] . m_Index = = COLFLAG_DEATH
| | m_pFront [ Ny * m_Width + Nx ] . m_Index = = COLFLAG_NOLASER )
return m_pFront [ Ny * m_Width + Nx ] . m_Index ;
2010-08-21 19:48:47 +00:00
else
return 0 ;
}
2010-11-13 13:22:19 +00:00
int CCollision : : Entity ( int x , int y , int Layer )
2010-08-21 06:40:03 +00:00
{
2010-10-08 22:05:17 +00:00
if ( ( 0 > x | | x > = m_Width ) | | ( 0 > y | | y > = m_Height ) )
2010-10-08 19:09:54 +00:00
{
2010-11-14 09:36:00 +00:00
char aBuf [ 12 ] ;
switch ( Layer )
{
case LAYER_GAME :
str_format ( aBuf , sizeof ( aBuf ) , " Game " ) ;
break ;
case LAYER_FRONT :
str_format ( aBuf , sizeof ( aBuf ) , " Front " ) ;
break ;
case LAYER_SWITCH :
str_format ( aBuf , sizeof ( aBuf ) , " Switch " ) ;
break ;
case LAYER_TELE :
str_format ( aBuf , sizeof ( aBuf ) , " Tele " ) ;
break ;
case LAYER_SPEEDUP :
str_format ( aBuf , sizeof ( aBuf ) , " Speedup " ) ;
break ;
2014-03-12 22:12:50 +00:00
case LAYER_TUNE :
str_format ( aBuf , sizeof ( aBuf ) , " Tune " ) ;
break ;
2010-11-14 09:36:00 +00:00
default :
str_format ( aBuf , sizeof ( aBuf ) , " Unknown " ) ;
}
2014-03-28 23:24:34 +00:00
dbg_msg ( " CCollision::Entity " , " Something is VERY wrong with the %s layer please report this at http://ddnet.tw, you will need to post the map as well and any steps that u think may have led to this " , aBuf ) ;
2010-10-08 19:09:54 +00:00
return 0 ;
}
2010-11-13 13:22:19 +00:00
switch ( Layer )
{
case LAYER_GAME :
return m_pTiles [ y * m_Width + x ] . m_Index - ENTITY_OFFSET ;
case LAYER_FRONT :
return m_pFront [ y * m_Width + x ] . m_Index - ENTITY_OFFSET ;
case LAYER_SWITCH :
return m_pSwitch [ y * m_Width + x ] . m_Type - ENTITY_OFFSET ;
case LAYER_TELE :
return m_pTele [ y * m_Width + x ] . m_Type - ENTITY_OFFSET ;
case LAYER_SPEEDUP :
return m_pSpeedup [ y * m_Width + x ] . m_Type - ENTITY_OFFSET ;
2014-03-12 22:12:50 +00:00
case LAYER_TUNE :
return m_pTune [ y * m_Width + x ] . m_Type - ENTITY_OFFSET ;
2010-11-13 13:22:19 +00:00
default :
return 0 ;
break ;
}
2010-08-12 11:01:57 +00:00
}
2010-09-25 16:39:52 +00:00
2010-08-10 04:28:17 +00:00
void CCollision : : SetCollisionAt ( float x , float y , int flag )
2010-08-21 19:48:47 +00:00
{
2014-04-22 21:46:55 +00:00
int Nx = clamp ( round_to_int ( x ) / 32 , 0 , m_Width - 1 ) ;
int Ny = clamp ( round_to_int ( y ) / 32 , 0 , m_Height - 1 ) ;
2010-08-21 19:48:47 +00:00
2011-02-13 05:35:13 +00:00
m_pTiles [ Ny * m_Width + Nx ] . m_Index = flag ;
2010-08-21 19:48:47 +00:00
}
2008-01-13 11:15:32 +00:00
2010-11-13 13:22:19 +00:00
void CCollision : : SetDCollisionAt ( float x , float y , int Type , int Flags , int Number )
2010-09-25 16:39:52 +00:00
{
2010-11-13 13:22:19 +00:00
if ( ! m_pDoor )
2010-09-25 16:39:52 +00:00
return ;
2014-04-22 21:46:55 +00:00
int Nx = clamp ( round_to_int ( x ) / 32 , 0 , m_Width - 1 ) ;
int Ny = clamp ( round_to_int ( y ) / 32 , 0 , m_Height - 1 ) ;
2010-09-25 16:39:52 +00:00
2011-02-13 05:35:13 +00:00
m_pDoor [ Ny * m_Width + Nx ] . m_Index = Type ;
m_pDoor [ Ny * m_Width + Nx ] . m_Flags = Flags ;
m_pDoor [ Ny * m_Width + Nx ] . m_Number = Number ;
2010-09-25 16:39:52 +00:00
}
2010-11-13 13:22:19 +00:00
int CCollision : : GetDTileIndex ( int Index )
2010-09-25 16:39:52 +00:00
{
2010-11-13 13:22:19 +00:00
if ( ! m_pDoor | | Index < 0 | | ! m_pDoor [ Index ] . m_Index )
return 0 ;
return m_pDoor [ Index ] . m_Index ;
2010-09-25 16:39:52 +00:00
}
2010-11-13 13:22:19 +00:00
int CCollision : : GetDTileNumber ( int Index )
2010-09-25 16:39:52 +00:00
{
2010-11-13 13:22:19 +00:00
if ( ! m_pDoor | | Index < 0 | | ! m_pDoor [ Index ] . m_Index )
2010-09-25 16:39:52 +00:00
return 0 ;
2010-11-13 13:22:19 +00:00
if ( m_pDoor [ Index ] . m_Number ) return m_pDoor [ Index ] . m_Number ;
2010-09-25 16:39:52 +00:00
return 0 ;
}
2010-11-13 13:22:19 +00:00
int CCollision : : GetDTileFlags ( int Index )
2010-11-01 01:51:17 +00:00
{
2010-11-13 13:22:19 +00:00
if ( ! m_pDoor | | Index < 0 | | ! m_pDoor [ Index ] . m_Index )
2010-11-01 01:51:17 +00:00
return 0 ;
2010-11-13 13:22:19 +00:00
return m_pDoor [ Index ] . m_Flags ;
2010-11-01 01:51:17 +00:00
}
2010-08-21 02:20:01 +00:00
void ThroughOffset ( vec2 Pos0 , vec2 Pos1 , int * Ox , int * Oy )
{
float x = Pos0 . x - Pos1 . x ;
float y = Pos0 . y - Pos1 . y ;
if ( fabs ( x ) > fabs ( y ) )
{
if ( x < 0 )
{
* Ox = - 32 ;
* Oy = 0 ;
}
else
{
* Ox = 32 ;
* Oy = 0 ;
}
}
else
{
if ( y < 0 )
{
* Ox = 0 ;
* Oy = - 32 ;
}
else
{
* Ox = 0 ;
* Oy = 32 ;
}
}
}
2011-04-09 06:41:31 +00:00
2011-01-06 03:46:10 +00:00
int CCollision : : IntersectNoLaser ( vec2 Pos0 , vec2 Pos1 , vec2 * pOutCollision , vec2 * pOutBeforeCollision )
2008-01-13 11:15:32 +00:00
{
2010-05-29 07:25:38 +00:00
float d = distance ( Pos0 , Pos1 ) ;
vec2 Last = Pos0 ;
2011-01-06 03:46:10 +00:00
for ( float f = 0 ; f < d ; f + + )
2008-01-13 11:15:32 +00:00
{
2011-01-06 03:46:10 +00:00
float a = f / d ;
2010-08-10 04:28:17 +00:00
vec2 Pos = mix ( Pos0 , Pos1 , a ) ;
2014-04-22 21:46:55 +00:00
int Nx = clamp ( round_to_int ( Pos . x ) / 32 , 0 , m_Width - 1 ) ;
int Ny = clamp ( round_to_int ( Pos . y ) / 32 , 0 , m_Height - 1 ) ;
2011-02-13 05:35:13 +00:00
if ( GetIndex ( Nx , Ny ) = = COLFLAG_SOLID
| | GetIndex ( Nx , Ny ) = = ( COLFLAG_SOLID | COLFLAG_NOHOOK )
| | GetIndex ( Nx , Ny ) = = COLFLAG_NOLASER
| | GetFIndex ( Nx , Ny ) = = COLFLAG_NOLASER )
2010-08-10 04:28:17 +00:00
{
if ( pOutCollision )
* pOutCollision = Pos ;
if ( pOutBeforeCollision )
2010-08-21 17:32:42 +00:00
* pOutBeforeCollision = Last ;
2011-02-13 05:35:13 +00:00
if ( GetFIndex ( Nx , Ny ) = = COLFLAG_NOLASER ) return GetFCollisionAt ( Pos . x , Pos . y ) ;
2010-08-29 03:46:09 +00:00
else return GetCollisionAt ( Pos . x , Pos . y ) ;
2011-04-09 06:41:31 +00:00
2010-08-21 17:32:42 +00:00
}
Last = Pos ;
}
if ( pOutCollision )
* pOutCollision = Pos1 ;
if ( pOutBeforeCollision )
* pOutBeforeCollision = Pos1 ;
return 0 ;
}
2010-08-21 19:14:57 +00:00
int CCollision : : IntersectNoLaserNW ( vec2 Pos0 , vec2 Pos1 , vec2 * pOutCollision , vec2 * pOutBeforeCollision )
2010-08-21 17:32:42 +00:00
{
float d = distance ( Pos0 , Pos1 ) ;
vec2 Last = Pos0 ;
for ( float f = 0 ; f < d ; f + + )
{
float a = f / d ;
vec2 Pos = mix ( Pos0 , Pos1 , a ) ;
2014-04-22 21:46:55 +00:00
if ( IsNoLaser ( round_to_int ( Pos . x ) , round_to_int ( Pos . y ) ) | | IsFNoLaser ( round_to_int ( Pos . x ) , round_to_int ( Pos . y ) ) )
2010-08-21 17:32:42 +00:00
{
if ( pOutCollision )
* pOutCollision = Pos ;
if ( pOutBeforeCollision )
2010-08-10 04:28:17 +00:00
* pOutBeforeCollision = Last ;
2014-04-22 21:46:55 +00:00
if ( IsNoLaser ( round_to_int ( Pos . x ) , round_to_int ( Pos . y ) ) ) return GetCollisionAt ( Pos . x , Pos . y ) ;
2010-08-21 19:48:47 +00:00
else return GetFCollisionAt ( Pos . x , Pos . y ) ;
2010-08-10 04:28:17 +00:00
}
Last = Pos ;
}
if ( pOutCollision )
* pOutCollision = Pos1 ;
if ( pOutBeforeCollision )
* pOutBeforeCollision = Pos1 ;
return 0 ;
}
int CCollision : : IntersectAir ( vec2 Pos0 , vec2 Pos1 , vec2 * pOutCollision , vec2 * pOutBeforeCollision )
{
float d = distance ( Pos0 , Pos1 ) ;
vec2 Last = Pos0 ;
2010-08-21 19:48:47 +00:00
2010-08-10 04:28:17 +00:00
for ( float f = 0 ; f < d ; f + + )
{
float a = f / d ;
vec2 Pos = mix ( Pos0 , Pos1 , a ) ;
2014-04-22 21:46:55 +00:00
if ( IsSolid ( round_to_int ( Pos . x ) , round_to_int ( Pos . y ) ) | | ( ! GetTile ( round_to_int ( Pos . x ) , round_to_int ( Pos . y ) ) & & ! GetFTile ( round_to_int ( Pos . x ) , round_to_int ( Pos . y ) ) ) )
2010-08-10 04:28:17 +00:00
{
if ( pOutCollision )
* pOutCollision = Pos ;
if ( pOutBeforeCollision )
* pOutBeforeCollision = Last ;
2014-04-22 21:46:55 +00:00
if ( ! GetTile ( round_to_int ( Pos . x ) , round_to_int ( Pos . y ) ) & & ! GetFTile ( round_to_int ( Pos . x ) , round_to_int ( Pos . y ) ) )
2010-08-10 04:28:17 +00:00
return - 1 ;
else
2014-04-22 21:46:55 +00:00
if ( ! GetTile ( round_to_int ( Pos . x ) , round_to_int ( Pos . y ) ) ) return GetTile ( round_to_int ( Pos . x ) , round_to_int ( Pos . y ) ) ;
else return GetFTile ( round_to_int ( Pos . x ) , round_to_int ( Pos . y ) ) ;
2010-08-10 04:28:17 +00:00
}
Last = Pos ;
}
if ( pOutCollision )
* pOutCollision = Pos1 ;
if ( pOutBeforeCollision )
* pOutBeforeCollision = Pos1 ;
return 0 ;
}
2011-05-17 23:12:39 +00:00
int CCollision : : IsCheckpoint ( int Index )
{
if ( Index < 0 )
return - 1 ;
int z = m_pTiles [ Index ] . m_Index ;
if ( z > = 35 & & z < = 59 )
return z - 35 ;
return - 1 ;
}
int CCollision : : IsFCheckpoint ( int Index )
{
if ( Index < 0 | | ! m_pFront )
return - 1 ;
int z = m_pFront [ Index ] . m_Index ;
if ( z > = 35 & & z < = 59 )
return z - 35 ;
return - 1 ;
}