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 | #ifndef GAME_COLLISION_H |
4 | #define GAME_COLLISION_H |
5 | |
6 | #include <base/vmath.h> |
7 | #include <engine/shared/protocol.h> |
8 | |
9 | #include <map> |
10 | #include <vector> |
11 | |
12 | enum |
13 | { |
14 | CANTMOVE_LEFT = 1 << 0, |
15 | CANTMOVE_RIGHT = 1 << 1, |
16 | CANTMOVE_UP = 1 << 2, |
17 | CANTMOVE_DOWN = 1 << 3, |
18 | }; |
19 | |
20 | vec2 ClampVel(int MoveRestriction, vec2 Vel); |
21 | |
22 | typedef bool (*CALLBACK_SWITCHACTIVE)(int Number, void *pUser); |
23 | struct CAntibotMapData; |
24 | |
25 | class CCollision |
26 | { |
27 | public: |
28 | CCollision(); |
29 | ~CCollision(); |
30 | |
31 | void Init(class CLayers *pLayers); |
32 | void Unload(); |
33 | void FillAntibot(CAntibotMapData *pMapData); |
34 | |
35 | bool CheckPoint(float x, float y) const { return IsSolid(x: round_to_int(f: x), y: round_to_int(f: y)); } |
36 | bool CheckPoint(vec2 Pos) const { return CheckPoint(x: Pos.x, y: Pos.y); } |
37 | int GetCollisionAt(float x, float y) const { return GetTile(x: round_to_int(f: x), y: round_to_int(f: y)); } |
38 | int GetWidth() const { return m_Width; } |
39 | int GetHeight() const { return m_Height; } |
40 | int IntersectLine(vec2 Pos0, vec2 Pos1, vec2 *pOutCollision, vec2 *pOutBeforeCollision) const; |
41 | int IntersectLineTeleWeapon(vec2 Pos0, vec2 Pos1, vec2 *pOutCollision, vec2 *pOutBeforeCollision, int *pTeleNr = nullptr) const; |
42 | int IntersectLineTeleHook(vec2 Pos0, vec2 Pos1, vec2 *pOutCollision, vec2 *pOutBeforeCollision, int *pTeleNr = nullptr) const; |
43 | void MovePoint(vec2 *pInoutPos, vec2 *pInoutVel, float Elasticity, int *pBounces) const; |
44 | void MoveBox(vec2 *pInoutPos, vec2 *pInoutVel, vec2 Size, vec2 Elasticity, bool *pGrounded = nullptr) const; |
45 | bool TestBox(vec2 Pos, vec2 Size) const; |
46 | |
47 | // DDRace |
48 | void SetCollisionAt(float x, float y, int id); |
49 | void SetDTile(float x, float y, bool State); |
50 | void SetDCollisionAt(float x, float y, int Type, int Flags, int Number); |
51 | int GetDTileIndex(int Index) const; |
52 | int GetDTileFlags(int Index) const; |
53 | int GetDTileNumber(int Index) const; |
54 | int GetFCollisionAt(float x, float y) const { return GetFTile(x: round_to_int(f: x), y: round_to_int(f: y)); } |
55 | int IntersectNoLaser(vec2 Pos0, vec2 Pos1, vec2 *pOutCollision, vec2 *pOutBeforeCollision) const; |
56 | int IntersectNoLaserNW(vec2 Pos0, vec2 Pos1, vec2 *pOutCollision, vec2 *pOutBeforeCollision) const; |
57 | int IntersectAir(vec2 Pos0, vec2 Pos1, vec2 *pOutCollision, vec2 *pOutBeforeCollision) const; |
58 | int GetIndex(int x, int y) const; |
59 | int GetIndex(vec2 PrevPos, vec2 Pos) const; |
60 | int GetFIndex(int x, int y) const; |
61 | |
62 | int GetMoveRestrictions(CALLBACK_SWITCHACTIVE pfnSwitchActive, void *pUser, vec2 Pos, float Distance = 18.0f, int OverrideCenterTileIndex = -1) const; |
63 | int GetMoveRestrictions(vec2 Pos, float Distance = 18.0f) |
64 | { |
65 | return GetMoveRestrictions(pfnSwitchActive: nullptr, pUser: nullptr, Pos, Distance); |
66 | } |
67 | |
68 | int GetTile(int x, int y) const; |
69 | int GetFTile(int x, int y) const; |
70 | int Entity(int x, int y, int Layer) const; |
71 | int GetPureMapIndex(float x, float y) const; |
72 | int GetPureMapIndex(vec2 Pos) const { return GetPureMapIndex(x: Pos.x, y: Pos.y); } |
73 | std::vector<int> GetMapIndices(vec2 PrevPos, vec2 Pos, unsigned MaxIndices = 0) const; |
74 | int GetMapIndex(vec2 Pos) const; |
75 | bool TileExists(int Index) const; |
76 | bool TileExistsNext(int Index) const; |
77 | vec2 GetPos(int Index) const; |
78 | int GetTileIndex(int Index) const; |
79 | int GetFTileIndex(int Index) const; |
80 | int GetTileFlags(int Index) const; |
81 | int GetFTileFlags(int Index) const; |
82 | int IsTeleport(int Index) const; |
83 | int IsEvilTeleport(int Index) const; |
84 | bool IsCheckTeleport(int Index) const; |
85 | bool IsCheckEvilTeleport(int Index) const; |
86 | int IsTeleportWeapon(int Index) const; |
87 | int IsTeleportHook(int Index) const; |
88 | int IsTeleCheckpoint(int Index) const; |
89 | int IsSpeedup(int Index) const; |
90 | int IsTune(int Index) const; |
91 | void GetSpeedup(int Index, vec2 *pDir, int *pForce, int *pMaxSpeed) const; |
92 | int GetSwitchType(int Index) const; |
93 | int GetSwitchNumber(int Index) const; |
94 | int GetSwitchDelay(int Index) const; |
95 | |
96 | int IsSolid(int x, int y) const; |
97 | bool IsThrough(int x, int y, int xoff, int yoff, vec2 pos0, vec2 pos1) const; |
98 | bool IsHookBlocker(int x, int y, vec2 pos0, vec2 pos1) const; |
99 | int IsWallJump(int Index) const; |
100 | int IsNoLaser(int x, int y) const; |
101 | int IsFNoLaser(int x, int y) const; |
102 | |
103 | int IsTimeCheckpoint(int Index) const; |
104 | int IsFTimeCheckpoint(int Index) const; |
105 | |
106 | int IsMover(int x, int y, int *pFlags) const; |
107 | |
108 | vec2 CpSpeed(int index, int Flags = 0) const; |
109 | |
110 | class CTeleTile *TeleLayer() { return m_pTele; } |
111 | class CSwitchTile *SwitchLayer() { return m_pSwitch; } |
112 | class CTuneTile *TuneLayer() { return m_pTune; } |
113 | class CLayers *Layers() { return m_pLayers; } |
114 | int m_HighestSwitchNumber; |
115 | |
116 | /** |
117 | * Index all teleporter types (in, out and checkpoints) |
118 | * as one consecutive list. |
119 | * |
120 | * @param Number is the teleporter number (one less than what is shown in game) |
121 | * @param Offset picks the n'th occurence of that teleporter in the map |
122 | * |
123 | * @return The coordinates of the teleporter in the map |
124 | * or (-1, -1) if not found |
125 | */ |
126 | vec2 TeleAllGet(int Number, size_t Offset); |
127 | |
128 | /** |
129 | * @param Number is the teleporter number (one less than what is shown in game) |
130 | * @return The amount of occurences of that teleporter across all types (in, out, checkpoint) |
131 | */ |
132 | size_t TeleAllSize(int Number); |
133 | |
134 | const std::vector<vec2> &TeleIns(int Number) { return m_TeleIns[Number]; } |
135 | const std::vector<vec2> &TeleOuts(int Number) { return m_TeleOuts[Number]; } |
136 | const std::vector<vec2> &TeleCheckOuts(int Number) { return m_TeleCheckOuts[Number]; } |
137 | const std::vector<vec2> &TeleOthers(int Number) { return m_TeleOthers[Number]; } |
138 | |
139 | private: |
140 | class CTile *m_pTiles; |
141 | int m_Width; |
142 | int m_Height; |
143 | class CLayers *m_pLayers; |
144 | |
145 | // TILE_TELEIN |
146 | std::map<int, std::vector<vec2>> m_TeleIns; |
147 | // TILE_TELEOUT |
148 | std::map<int, std::vector<vec2>> m_TeleOuts; |
149 | // TILE_TELECHECKOUT |
150 | std::map<int, std::vector<vec2>> m_TeleCheckOuts; |
151 | // TILE_TELEINEVIL, TILE_TELECHECK, TILE_TELECHECKIN, TILE_TELECHECKINEVIL |
152 | std::map<int, std::vector<vec2>> m_TeleOthers; |
153 | |
154 | class CTeleTile *m_pTele; |
155 | class CSpeedupTile *m_pSpeedup; |
156 | class CTile *m_pFront; |
157 | class CSwitchTile *m_pSwitch; |
158 | class CTuneTile *m_pTune; |
159 | class CDoorTile *m_pDoor; |
160 | }; |
161 | |
162 | void ThroughOffset(vec2 Pos0, vec2 Pos1, int *pOffsetX, int *pOffsetY); |
163 | #endif |
164 | |