2010-05-29 07:25:38 +00:00
|
|
|
// copyright (c) 2007 magnus auvinen, see licence.txt for more info
|
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
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
CCollision::CCollision()
|
|
|
|
{
|
|
|
|
m_pTiles = 0;
|
2010-07-29 05:21:18 +00:00
|
|
|
m_pFTiles = 0;
|
2010-05-29 07:25:38 +00:00
|
|
|
m_Width = 0;
|
|
|
|
m_Height = 0;
|
|
|
|
m_pLayers = 0;
|
2010-07-29 05:21:18 +00:00
|
|
|
isOneLayer = false;
|
2010-05-29 07:25:38 +00:00
|
|
|
}
|
2010-07-29 05:21:18 +00:00
|
|
|
int CCollision::IsSolid(int x, int y)
|
|
|
|
{
|
|
|
|
return (GetTile(x,y)&COLFLAG_SOLID);
|
|
|
|
}
|
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-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));
|
2010-07-29 05:21:18 +00:00
|
|
|
if(m_pLayers->FGameLayer() != 0) {
|
|
|
|
m_pFTiles = static_cast<CTile *>(m_pLayers->Map()->GetData(m_pLayers->FGameLayer()->m_Data));
|
|
|
|
isOneLayer = false;
|
|
|
|
} else {
|
|
|
|
m_pFTiles = 0;
|
|
|
|
isOneLayer = true;
|
|
|
|
}
|
|
|
|
//race
|
|
|
|
mem_zero(&m_Len, sizeof(m_Len));
|
|
|
|
mem_zero(&m_Tele, sizeof(m_Tele));
|
|
|
|
m_pTeleporter = new int[m_Width * m_Height];
|
|
|
|
m_pFTeleporter = new int[m_Width * m_Height];
|
|
|
|
|
|
|
|
|
|
|
|
for(int i = m_Width * m_Height - 1; i >= 0; i--)
|
|
|
|
{
|
|
|
|
if(m_pTiles[i].m_Index > 34 && m_pTiles[i].m_Index < 190)
|
|
|
|
{
|
|
|
|
if(m_pTiles[i].m_Index & 1)
|
|
|
|
m_Len[m_pTiles[i].m_Index >> 1]++;
|
|
|
|
else if(!(m_pTiles[i].m_Index & 1))
|
|
|
|
m_Tele[(m_pTiles[i].m_Index - 1) >> 1]++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for(int i = 0; i < 95; i++)
|
|
|
|
{
|
|
|
|
m_pDest[i] = new int[m_Len[i]];
|
|
|
|
m_Len[i] = 0;
|
|
|
|
}
|
|
|
|
for(int i = m_Width * m_Height - 1; i >= 0; i--)
|
|
|
|
{
|
|
|
|
if(m_pTiles[i].m_Index & 1 && m_pTiles[i].m_Index > 34 && m_pTiles[i].m_Index < 190)
|
|
|
|
m_pDest[m_pTiles[i].m_Index >> 1][m_Len[m_pTiles[i].m_Index >> 1]++] = i;
|
|
|
|
}
|
2008-09-23 14:38:13 +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-05-29 07:25:38 +00:00
|
|
|
int Index = m_pTiles[i].m_Index;
|
2010-07-29 05:21:18 +00:00
|
|
|
int FIndex = 0;
|
|
|
|
if(!isOneLayer)
|
|
|
|
FIndex = m_pFTiles[i].m_Index;
|
|
|
|
if (FIndex!=0)
|
|
|
|
dbg_msg ("flayer", "tile found at (%d, %d)",(i - (i/ m_Width) * m_Width) ,(i / m_Width));
|
|
|
|
if(Index > 190)
|
2008-09-23 14:38:13 +00:00
|
|
|
continue;
|
|
|
|
|
2010-05-29 07:25:38 +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;
|
2010-07-29 05:21:18 +00:00
|
|
|
case TILE_NOLASER:
|
|
|
|
m_pTiles[i].m_Index = COLFLAG_NOLASER;
|
|
|
|
break;
|
2010-05-29 07:25:38 +00:00
|
|
|
default:
|
|
|
|
m_pTiles[i].m_Index = 0;
|
2010-07-29 05:21:18 +00:00
|
|
|
m_pTeleporter[i] = Index;
|
2010-05-29 07:25:38 +00:00
|
|
|
}
|
2010-07-29 05:21:18 +00:00
|
|
|
m_pFTeleporter[i] = FIndex;
|
2008-09-23 14:38:13 +00:00
|
|
|
}
|
2008-01-13 11:15:32 +00:00
|
|
|
}
|
|
|
|
|
2010-07-29 05:21:18 +00:00
|
|
|
int CCollision::GetIndex(int x, int y, bool flayer) {
|
|
|
|
CTile *tiles = (flayer) ? m_pFTiles: m_pTiles;
|
|
|
|
int index = tiles[y*m_Width+x].m_Index;
|
|
|
|
return index-ENTITY_OFFSET;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
int CCollision::GetTile(int x, int y)
|
2008-01-13 11:15:32 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
int nx = clamp(x/32, 0, m_Width-1);
|
|
|
|
int ny = clamp(y/32, 0, m_Height-1);
|
2008-01-13 11:15:32 +00:00
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
return m_pTiles[ny*m_Width+nx].m_Index > 128 ? 0 : m_pTiles[ny*m_Width+nx].m_Index;
|
2008-09-23 14:10:05 +00:00
|
|
|
}
|
|
|
|
|
2010-05-29 07:25:38 +00:00
|
|
|
bool CCollision::IsTileSolid(int x, int y)
|
2008-09-23 14:10:05 +00:00
|
|
|
{
|
2010-07-29 05:21:18 +00:00
|
|
|
return (GetTile(x,y)&COLFLAG_SOLID);
|
2008-01-13 11:15:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: rewrite this smarter!
|
2010-05-29 07:25:38 +00:00
|
|
|
int CCollision::IntersectLine(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;
|
2008-01-13 11:15:32 +00:00
|
|
|
|
|
|
|
for(float f = 0; f < d; f++)
|
|
|
|
{
|
|
|
|
float a = f/d;
|
2010-05-29 07:25:38 +00:00
|
|
|
vec2 Pos = mix(Pos0, Pos1, a);
|
|
|
|
if(CheckPoint(Pos.x, Pos.y))
|
2008-01-13 11:15:32 +00:00
|
|
|
{
|
2010-05-29 07:25:38 +00:00
|
|
|
if(pOutCollision)
|
|
|
|
*pOutCollision = Pos;
|
|
|
|
if(pOutBeforeCollision)
|
|
|
|
*pOutBeforeCollision = Last;
|
|
|
|
return GetCollisionAt(Pos.x, Pos.y);
|
2008-01-13 11:15:32 +00:00
|
|
|
}
|
2010-05-29 07:25:38 +00:00
|
|
|
Last = Pos;
|
2008-01-13 11:15:32 +00:00
|
|
|
}
|
2010-05-29 07:25:38 +00:00
|
|
|
if(pOutCollision)
|
|
|
|
*pOutCollision = Pos1;
|
|
|
|
if(pOutBeforeCollision)
|
|
|
|
*pOutBeforeCollision = Pos1;
|
2008-09-23 14:38:13 +00:00
|
|
|
return 0;
|
2008-01-13 11:15:32 +00:00
|
|
|
}
|
2010-05-29 07:25:38 +00:00
|
|
|
|
|
|
|
// TODO: OPT: rewrite this smarter!
|
|
|
|
void CCollision::MovePoint(vec2 *pInoutPos, vec2 *pInoutVel, float Elasticity, int *pBounces)
|
|
|
|
{
|
|
|
|
if(pBounces)
|
|
|
|
*pBounces = 0;
|
|
|
|
|
|
|
|
vec2 Pos = *pInoutPos;
|
|
|
|
vec2 Vel = *pInoutVel;
|
|
|
|
if(CheckPoint(Pos + Vel))
|
|
|
|
{
|
|
|
|
int Affected = 0;
|
|
|
|
if(CheckPoint(Pos.x + Vel.x, Pos.y))
|
|
|
|
{
|
|
|
|
pInoutVel->x *= -Elasticity;
|
|
|
|
if(pBounces)
|
|
|
|
(*pBounces)++;
|
|
|
|
Affected++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(CheckPoint(Pos.x, Pos.y + Vel.y))
|
|
|
|
{
|
|
|
|
pInoutVel->y *= -Elasticity;
|
|
|
|
if(pBounces)
|
|
|
|
(*pBounces)++;
|
|
|
|
Affected++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(Affected == 0)
|
|
|
|
{
|
|
|
|
pInoutVel->x *= -Elasticity;
|
|
|
|
pInoutVel->y *= -Elasticity;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*pInoutPos = Pos + Vel;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CCollision::MoveBox(vec2 *pInoutPos, vec2 *pInoutVel, vec2 Size, float Elasticity)
|
|
|
|
{
|
|
|
|
// do the move
|
|
|
|
vec2 Pos = *pInoutPos;
|
|
|
|
vec2 Vel = *pInoutVel;
|
|
|
|
|
|
|
|
float Distance = length(Vel);
|
|
|
|
int Max = (int)Distance;
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
vec2 NewPos = Pos + Vel*Fraction; // TODO: this row is not nice
|
|
|
|
|
|
|
|
if(TestBox(vec2(NewPos.x, NewPos.y), Size))
|
|
|
|
{
|
|
|
|
int Hits = 0;
|
|
|
|
|
|
|
|
if(TestBox(vec2(Pos.x, NewPos.y), Size))
|
|
|
|
{
|
|
|
|
NewPos.y = Pos.y;
|
|
|
|
Vel.y *= -Elasticity;
|
|
|
|
Hits++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(TestBox(vec2(NewPos.x, Pos.y), Size))
|
|
|
|
{
|
|
|
|
NewPos.x = Pos.x;
|
|
|
|
Vel.x *= -Elasticity;
|
|
|
|
Hits++;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Pos = NewPos;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*pInoutPos = Pos;
|
|
|
|
*pInoutVel = Vel;
|
|
|
|
}
|
2010-07-29 05:21:18 +00:00
|
|
|
|
|
|
|
int CCollision::IsNolaser(int x, int y)
|
|
|
|
{
|
|
|
|
return (CCollision::GetTile(x,y) & COLFLAG_NOLASER);
|
|
|
|
}
|
|
|
|
|
|
|
|
//race
|
|
|
|
int CCollision::IsTeleport(int x, int y)
|
|
|
|
{
|
|
|
|
int nx = x/32;
|
|
|
|
int ny = y/32;
|
|
|
|
if(y < 0 || nx < 0 || nx >= m_Width || ny >= m_Height)
|
|
|
|
return 0;
|
|
|
|
int z = m_pTeleporter[ny * m_Width + nx]-1;
|
|
|
|
if(z > 34 && z < 190 && z & 1)
|
|
|
|
return z >> 1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int CCollision::IsBegin(int x, int y)
|
|
|
|
{
|
|
|
|
int nx = x/32;
|
|
|
|
int ny = y/32;
|
|
|
|
if(y < 0 || nx < 0 || nx >= m_Width || ny >= m_Height)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return m_pTeleporter[ny*m_Width+nx] == TILE_BEGIN;
|
|
|
|
}
|
|
|
|
|
|
|
|
int CCollision::IsEnd(int x, int y)
|
|
|
|
{
|
|
|
|
int nx = x/32;
|
|
|
|
int ny = y/32;
|
|
|
|
if(y < 0 || nx < 0 || nx >= m_Width || ny >= m_Height)
|
|
|
|
return 0;
|
|
|
|
return m_pTeleporter[ny * m_Width + nx] == TILE_END;
|
|
|
|
}
|
|
|
|
|
|
|
|
int CCollision::IsFreeze(int x, int y)
|
|
|
|
{
|
|
|
|
int nx = x/32;
|
|
|
|
int ny = y/32;
|
|
|
|
if(y < 0 || nx < 0 || nx >= m_Width || ny >= m_Height)
|
|
|
|
return 0;
|
|
|
|
return (m_pTeleporter[ny * m_Width + nx] == TILE_FREEZE) || (m_pFTeleporter[ny * m_Width + nx] == TILE_FREEZE);
|
|
|
|
}
|
|
|
|
|
|
|
|
int CCollision::IsUnfreeze(int x, int y)
|
|
|
|
{
|
|
|
|
int nx = x/32;
|
|
|
|
int ny = y/32;
|
|
|
|
if(y < 0 || nx < 0 || nx >= m_Width || ny >= m_Height)
|
|
|
|
return 0;
|
|
|
|
return (m_pTeleporter[ny * m_Width + nx] == TILE_UNFREEZE) || (m_pFTeleporter[ny * m_Width + nx] == TILE_UNFREEZE);
|
|
|
|
}
|
|
|
|
|
|
|
|
int CCollision::IsKick(int x, int y)
|
|
|
|
{
|
|
|
|
int nx = x/32;
|
|
|
|
int ny = y/32;
|
|
|
|
if(y < 0 || nx < 0 || nx >= m_Width || ny >= m_Height)
|
|
|
|
return 0;
|
|
|
|
return (m_pTeleporter[ny * m_Width + nx] == TILE_KICK) || (m_pFTeleporter[ny * m_Width + nx] == TILE_KICK);
|
|
|
|
}
|
|
|
|
|
|
|
|
int CCollision::IsCp(int x, int y)
|
|
|
|
{
|
|
|
|
int nx = x/32;
|
|
|
|
int ny = y/32;
|
|
|
|
if(y < 0 || nx < 0 || nx >= m_Width || ny >= m_Height)
|
|
|
|
return 0;
|
|
|
|
int ind = m_pTeleporter[ny * m_Width + nx];
|
|
|
|
if (ind >= TILE_CP_D && ind <= TILE_CP_L_F)
|
|
|
|
return ind;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int CCollision::IsBoost(int x, int y)
|
|
|
|
{
|
|
|
|
int nx = x/32;
|
|
|
|
int ny = y/32;
|
|
|
|
if(y < 0 || nx < 0 || nx >= m_Width || ny >= m_Height)
|
|
|
|
return 0;
|
|
|
|
if ((m_pTeleporter[ny * m_Width + nx] >= TILE_BOOST_L && m_pTeleporter[ny * m_Width + nx] <= TILE_BOOST_U) || (m_pTeleporter[ny * m_Width + nx] >= TILE_BOOST_L2 && m_pTeleporter[ny * m_Width + nx] <= TILE_BOOST_U2))
|
|
|
|
return m_pTeleporter[ny * m_Width + nx];
|
|
|
|
else if ((m_pFTeleporter[ny * m_Width + nx] >= TILE_BOOST_L && m_pFTeleporter[ny * m_Width + nx]<= TILE_BOOST_U) || (m_pFTeleporter[ny * m_Width + nx] >= TILE_BOOST_L2 && m_pFTeleporter[ny * m_Width + nx] <= TILE_BOOST_U2))
|
|
|
|
return m_pFTeleporter[ny * m_Width + nx];
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
vec2 CCollision::CpSpeed(int index)
|
|
|
|
{
|
|
|
|
|
|
|
|
vec2 target;
|
|
|
|
|
|
|
|
switch(index)
|
|
|
|
{
|
|
|
|
case TILE_CP_U:
|
|
|
|
case TILE_CP_U_F:
|
|
|
|
target.x=0;
|
|
|
|
target.y=-4;
|
|
|
|
break;
|
|
|
|
case TILE_CP_R:
|
|
|
|
case TILE_CP_R_F:
|
|
|
|
target.x=4;
|
|
|
|
target.y=0;
|
|
|
|
break;
|
|
|
|
case TILE_CP_D:
|
|
|
|
case TILE_CP_D_F:
|
|
|
|
target.x=0;
|
|
|
|
target.y=4;
|
|
|
|
break;
|
|
|
|
case TILE_CP_L:
|
|
|
|
case TILE_CP_L_F:
|
|
|
|
target.x=-4;
|
|
|
|
target.y=0;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
target=vec2(0,0);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (index>=TILE_CP_D_F && index<=TILE_CP_L_F)
|
|
|
|
target*=4;
|
|
|
|
return target;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
vec2 CCollision::BoostAccel(int index)
|
|
|
|
{
|
|
|
|
if (index==TILE_BOOST_L)
|
|
|
|
return vec2(-3,0);
|
|
|
|
else if(index==TILE_BOOST_R)
|
|
|
|
return vec2(3,0);
|
|
|
|
else if(index==TILE_BOOST_D)
|
|
|
|
return vec2(0,2);
|
|
|
|
else if(index==TILE_BOOST_U)
|
|
|
|
return vec2(0,-2);
|
|
|
|
else if(index==TILE_BOOST_L2)
|
|
|
|
return vec2(-15,0);
|
|
|
|
else if(index==TILE_BOOST_R2)
|
|
|
|
return vec2(15,0);
|
|
|
|
else if(index==TILE_BOOST_D2)
|
|
|
|
return vec2(0,15);
|
|
|
|
else if(index==TILE_BOOST_U2)
|
|
|
|
return vec2(0,-15);
|
|
|
|
|
|
|
|
return vec2(0,0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
vec2 CCollision::Teleport(int a)
|
|
|
|
{
|
|
|
|
if(m_Len[a] > 0)
|
|
|
|
{
|
|
|
|
int r = rand()%m_Len[a];
|
|
|
|
int x = (m_pDest[a][r] % m_Width)<<5;
|
|
|
|
int y = (m_pDest[a][r] / m_Width)<<5;
|
|
|
|
return vec2((float)x+16.0, (float)y+16.0);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return vec2(0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CCollision::Set(int x, int y, int flag)
|
|
|
|
{
|
|
|
|
int nx = clamp(x/32, 0, m_Width-1);
|
|
|
|
int ny = clamp(y/32, 0, m_Height-1);
|
|
|
|
|
|
|
|
m_pTiles[ny * m_Width + nx].m_Index = flag;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int CCollision::IntersectNolaser2(vec2 pos0, vec2 pos1, vec2 *out_collision, vec2 *out_before_collision)
|
|
|
|
{
|
|
|
|
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);
|
|
|
|
if(CCollision::IsNolaser(round(pos.x), round(pos.y)))
|
|
|
|
{
|
|
|
|
if(out_collision)
|
|
|
|
*out_collision = pos;
|
|
|
|
if(out_before_collision)
|
|
|
|
*out_before_collision = last;
|
|
|
|
return GetTile(round(pos.x), round(pos.y));
|
|
|
|
}
|
|
|
|
last = pos;
|
|
|
|
}
|
|
|
|
if(out_collision)
|
|
|
|
*out_collision = pos1;
|
|
|
|
if(out_before_collision)
|
|
|
|
*out_before_collision = pos1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int CCollision::IntersectNolaser(vec2 pos0, vec2 pos1, vec2 *out_collision, vec2 *out_before_collision)
|
|
|
|
{
|
|
|
|
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);
|
|
|
|
if(IsNolaser(round(pos.x), round(pos.y)) || IsSolid(round(pos.x), round(pos.y)))
|
|
|
|
{
|
|
|
|
if(out_collision)
|
|
|
|
*out_collision = pos;
|
|
|
|
if(out_before_collision)
|
|
|
|
*out_before_collision = last;
|
|
|
|
return GetTile(round(pos.x), round(pos.y));
|
|
|
|
}
|
|
|
|
last = pos;
|
|
|
|
}
|
|
|
|
if(out_collision)
|
|
|
|
*out_collision = pos1;
|
|
|
|
if(out_before_collision)
|
|
|
|
*out_before_collision = pos1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int CCollision::IntersectAir(vec2 pos0, vec2 pos1, vec2 *out_collision, vec2 *out_before_collision)
|
|
|
|
{
|
|
|
|
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);
|
|
|
|
if(IsSolid(round(pos.x), round(pos.y)) || !GetTile(round(pos.x), round(pos.y)))
|
|
|
|
{
|
|
|
|
if(out_collision)
|
|
|
|
*out_collision = pos;
|
|
|
|
if(out_before_collision)
|
|
|
|
*out_before_collision = last;
|
|
|
|
if(!GetTile(round(pos.x), round(pos.y)))
|
|
|
|
return -1;
|
|
|
|
else
|
|
|
|
return GetTile(round(pos.x), round(pos.y));
|
|
|
|
}
|
|
|
|
last = pos;
|
|
|
|
}
|
|
|
|
if(out_collision)
|
|
|
|
*out_collision = pos1;
|
|
|
|
if(out_before_collision)
|
|
|
|
*out_before_collision = pos1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|