fixed a warning in client (mac)
[twcon.git] / src / game / collision.cpp
blobca932d9b7f686b98c5eb706d035e109c7d08aec1
1 /* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
2 /* If you are missing that file, acquire a complete release at teeworlds.com. */
3 #include <base/system.h>
4 #include <base/math.h>
5 #include <base/vmath.h>
7 #include <math.h>
8 #include <engine/map.h>
9 #include <engine/kernel.h>
11 #include <game/mapitems.h>
12 #include <game/layers.h>
13 #include <game/collision.h>
15 CCollision::CCollision()
17 m_pTiles = 0;
18 m_Width = 0;
19 m_Height = 0;
20 m_pLayers = 0;
23 void CCollision::Init(class CLayers *pLayers)
25 m_pLayers = pLayers;
26 m_Width = m_pLayers->GameLayer()->m_Width;
27 m_Height = m_pLayers->GameLayer()->m_Height;
28 m_pTiles = static_cast<CTile *>(m_pLayers->Map()->GetData(m_pLayers->GameLayer()->m_Data));
30 for(int i = 0; i < m_Width*m_Height; i++)
32 int Index = m_pTiles[i].m_Index;
34 if(Index > 128)
35 continue;
37 switch(Index)
39 case TILE_DEATH:
40 m_pTiles[i].m_Index = COLFLAG_DEATH;
41 break;
42 case TILE_SOLID:
43 m_pTiles[i].m_Index = COLFLAG_SOLID;
44 break;
45 case TILE_NOHOOK:
46 m_pTiles[i].m_Index = COLFLAG_SOLID|COLFLAG_NOHOOK;
47 break;
48 default:
49 m_pTiles[i].m_Index = 0;
54 int CCollision::GetTile(int x, int y)
56 int Nx = clamp(x/32, 0, m_Width-1);
57 int Ny = clamp(y/32, 0, m_Height-1);
59 return m_pTiles[Ny*m_Width+Nx].m_Index > 128 ? 0 : m_pTiles[Ny*m_Width+Nx].m_Index;
62 bool CCollision::IsTileSolid(int x, int y)
64 return GetTile(x, y)&COLFLAG_SOLID;
67 // TODO: rewrite this smarter!
68 int CCollision::IntersectLine(vec2 Pos0, vec2 Pos1, vec2 *pOutCollision, vec2 *pOutBeforeCollision)
70 float Distance = distance(Pos0, Pos1);
71 int End(Distance+1);
72 vec2 Last = Pos0;
74 for(int i = 0; i < End; i++)
76 float a = i/Distance;
77 vec2 Pos = mix(Pos0, Pos1, a);
78 if(CheckPoint(Pos.x, Pos.y))
80 if(pOutCollision)
81 *pOutCollision = Pos;
82 if(pOutBeforeCollision)
83 *pOutBeforeCollision = Last;
84 return GetCollisionAt(Pos.x, Pos.y);
86 Last = Pos;
88 if(pOutCollision)
89 *pOutCollision = Pos1;
90 if(pOutBeforeCollision)
91 *pOutBeforeCollision = Pos1;
92 return 0;
95 // TODO: OPT: rewrite this smarter!
96 void CCollision::MovePoint(vec2 *pInoutPos, vec2 *pInoutVel, float Elasticity, int *pBounces)
98 if(pBounces)
99 *pBounces = 0;
101 vec2 Pos = *pInoutPos;
102 vec2 Vel = *pInoutVel;
103 if(CheckPoint(Pos + Vel))
105 int Affected = 0;
106 if(CheckPoint(Pos.x + Vel.x, Pos.y))
108 pInoutVel->x *= -Elasticity;
109 if(pBounces)
110 (*pBounces)++;
111 Affected++;
114 if(CheckPoint(Pos.x, Pos.y + Vel.y))
116 pInoutVel->y *= -Elasticity;
117 if(pBounces)
118 (*pBounces)++;
119 Affected++;
122 if(Affected == 0)
124 pInoutVel->x *= -Elasticity;
125 pInoutVel->y *= -Elasticity;
128 else
130 *pInoutPos = Pos + Vel;
134 bool CCollision::TestBox(vec2 Pos, vec2 Size)
136 Size *= 0.5f;
137 if(CheckPoint(Pos.x-Size.x, Pos.y-Size.y))
138 return true;
139 if(CheckPoint(Pos.x+Size.x, Pos.y-Size.y))
140 return true;
141 if(CheckPoint(Pos.x-Size.x, Pos.y+Size.y))
142 return true;
143 if(CheckPoint(Pos.x+Size.x, Pos.y+Size.y))
144 return true;
145 return false;
148 void CCollision::MoveBox(vec2 *pInoutPos, vec2 *pInoutVel, vec2 Size, float Elasticity)
150 // do the move
151 vec2 Pos = *pInoutPos;
152 vec2 Vel = *pInoutVel;
154 float Distance = length(Vel);
155 int Max = (int)Distance;
157 if(Distance > 0.00001f)
159 //vec2 old_pos = pos;
160 float Fraction = 1.0f/(float)(Max+1);
161 for(int i = 0; i <= Max; i++)
163 //float amount = i/(float)max;
164 //if(max == 0)
165 //amount = 0;
167 vec2 NewPos = Pos + Vel*Fraction; // TODO: this row is not nice
169 if(TestBox(vec2(NewPos.x, NewPos.y), Size))
171 int Hits = 0;
173 if(TestBox(vec2(Pos.x, NewPos.y), Size))
175 NewPos.y = Pos.y;
176 Vel.y *= -Elasticity;
177 Hits++;
180 if(TestBox(vec2(NewPos.x, Pos.y), Size))
182 NewPos.x = Pos.x;
183 Vel.x *= -Elasticity;
184 Hits++;
187 // neither of the tests got a collision.
188 // this is a real _corner case_!
189 if(Hits == 0)
191 NewPos.y = Pos.y;
192 Vel.y *= -Elasticity;
193 NewPos.x = Pos.x;
194 Vel.x *= -Elasticity;
198 Pos = NewPos;
202 *pInoutPos = Pos;
203 *pInoutVel = Vel;