4 // Copyright (C) 2004 Tobias Glaesser <tobi.web@gmx.de>
6 // This program is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU General Public License
8 // as published by the Free Software Foundation; either version 2
9 // of the License, or (at your option) any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
22 #include "collision.h"
29 bool rectcollision(const base_type& one, const base_type& two)
31 return (one.x >= two.x - one.width + 1 &&
32 one.x <= two.x + two.width - 1 &&
33 one.y >= two.y - one.height + 1 &&
34 one.y <= two.y + two.height - 1);
37 bool rectcollision_offset(const base_type& one, const base_type& two, float off_x, float off_y)
39 return (one.x >= two.x - one.width + off_x + 1 &&
40 one.x <= two.x + two.width + off_x - 1 &&
41 one.y >= two.y - one.height + off_y + 1 &&
42 one.y <= two.y + two.height + off_y - 1);
45 bool collision_object_map(const base_type& pbase)
47 int v = (int)pbase.height / 16;
48 int h = (int)pbase.width / 16;
50 if(issolid(pbase.x + 1, pbase.y + 1) ||
51 issolid(pbase.x + pbase.width -1, pbase.y + 1) ||
52 issolid(pbase.x +1, pbase.y + pbase.height -1) ||
53 issolid(pbase.x + pbase.width -1, pbase.y + pbase.height - 1))
56 for(int i = 1; i < h; ++i)
58 if(issolid(pbase.x + i*16,pbase.y + 1))
62 for(int i = 1; i < h; ++i)
64 if( issolid(pbase.x + i*16,pbase.y + pbase.height - 1))
68 for(int i = 1; i < v; ++i)
70 if( issolid(pbase.x + 1, pbase.y + i*16))
73 for(int i = 1; i < v; ++i)
75 if( issolid(pbase.x + pbase.width - 1, pbase.y + i*16))
82 void* collision_func(const base_type& base, tiletestfunction function)
84 for(float x = base.x; x < base.x + base.width; x += 32) {
85 for(float y = base.y; y < base.y + base.height; y += 32) {
86 Tile* tile = gettile(x, y);
87 void* result = function(tile);
96 static void* test_goal_tile_function(Tile* tile)
98 if(tile && tile->goal)
103 Tile* collision_goal(const base_type& base)
105 return (Tile*) collision_func(base, test_goal_tile_function);
108 void collision_swept_object_map(base_type* old, base_type* current)
110 int steps; /* Used to speed up the collision tests, by stepping every 16pixels in the path. */
112 float lpath; /* Holds the longest path, which is either in X or Y direction. */
113 float xd,yd; /* Hold the smallest steps in X and Y directions. */
114 float temp, xt, yt; /* Temporary variable. */
120 if(old->x == current->x && old->y == current->y)
124 else if(old->x == current->x && old->y != current->y)
126 lpath = current->y - old->y;
140 else if(old->x != current->x && old->y == current->y)
142 lpath = current->x - old->x;
157 lpath = current->x - old->x;
160 if(current->y - old->y > lpath || old->y - current->y > lpath)
161 lpath = current->y - old->y;
165 xd = (current->x - old->x) / lpath;
166 yd = (current->y - old->y) / lpath;
169 steps = (int)(lpath / (float)16);
174 for(float i = 0; i <= lpath; old->x += xd, old->y += yd, ++i)
183 if(collision_object_map(*old))
188 current->y = old->y - yd;
189 while(collision_object_map(*current))
193 current->x = old->x - xd;
194 while(collision_object_map(*current))
200 current->x = old->x - xd;
201 current->y = old->y - yd;
202 while(collision_object_map(*current))
210 if(!collision_object_map(*current))
216 if(!collision_object_map(*current))
223 while(!collision_object_map(*current))
241 Tile* gettile(float x, float y)
243 return TileManager::instance()->get(World::current()->get_level()->gettileid(x, y));
246 bool issolid(float x, float y)
248 Tile* tile = gettile(x,y);
249 return tile && tile->solid;
252 bool isbrick(float x, float y)
254 Tile* tile = gettile(x,y);
255 return tile && tile->brick;
258 bool isice(float x, float y)
260 Tile* tile = gettile(x,y);
261 return tile && tile->ice;
264 bool isfullbox(float x, float y)
266 Tile* tile = gettile(x,y);
267 return tile && tile->fullbox;
270 bool isdistro(float x, float y)
272 Tile* tile = gettile(x,y);
273 return tile && tile->distro;