2 // C Implementation: collision
7 // Author: Tobias Glaesser <tobi.web@gmx.de>, (C) 2004
9 // Copyright: See COPYING file that comes with this distribution
14 #include "collision.h"
19 bool rectcollision(base_type* one, base_type* two)
21 return (one->x >= two->x - one->width + 1 &&
22 one->x <= two->x + two->width - 1 &&
23 one->y >= two->y - one->height + 1 &&
24 one->y <= two->y + two->height - 1);
27 bool rectcollision_offset(base_type* one, base_type* two, float off_x, float off_y)
29 return (one->x >= two->x - one->width +off_x + 1 &&
30 one->x <= two->x + two->width + off_x - 1 &&
31 one->y >= two->y - one->height + off_y + 1 &&
32 one->y <= two->y + two->height + off_y - 1);
35 bool collision_object_map(base_type* pbase)
37 int v = (int)pbase->height / 16;
38 int h = (int)pbase->width / 16;
40 if(issolid(pbase->x + 1, pbase->y + 1) ||
41 issolid(pbase->x + pbase->width -1, pbase->y + 1) ||
42 issolid(pbase->x +1, pbase->y + pbase->height -1) ||
43 issolid(pbase->x + pbase->width -1, pbase->y + pbase->height - 1))
46 for(int i = 1; i < h; ++i)
48 if(issolid(pbase->x + i*16,pbase->y + 1))
52 for(int i = 1; i < h; ++i)
54 if( issolid(pbase->x + i*16,pbase->y + pbase->height - 1))
58 for(int i = 1; i < v; ++i)
60 if( issolid(pbase->x + 1, pbase->y + i*16))
63 for(int i = 1; i < v; ++i)
65 if( issolid(pbase->x + pbase->width - 1, pbase->y + i*16))
73 void collision_swept_object_map(base_type* old, base_type* current)
75 int steps; /* Used to speed up the collision tests, by stepping every 16pixels in the path. */
77 float lpath; /* Holds the longest path, which is either in X or Y direction. */
78 float xd,yd; /* Hold the smallest steps in X and Y directions. */
79 float temp, xt, yt; /* Temporary variable. */
85 if(old->x == current->x && old->y == current->y)
89 else if(old->x == current->x && old->y != current->y)
91 lpath = current->y - old->y;
105 else if(old->x != current->x && old->y == current->y)
107 lpath = current->x - old->x;
122 lpath = current->x - old->x;
125 if(current->y - old->y > lpath || old->y - current->y > lpath)
126 lpath = current->y - old->y;
130 xd = (current->x - old->x) / lpath;
131 yd = (current->y - old->y) / lpath;
134 steps = (int)(lpath / (float)16);
139 for(float i = 0; i <= lpath; old->x += xd, old->y += yd, ++i)
148 if(collision_object_map(old))
153 current->y = old->y - yd;
154 while(collision_object_map(current))
158 current->x = old->x - xd;
159 while(collision_object_map(current))
165 current->x = old->x - xd;
166 current->y = old->y - yd;
167 while(collision_object_map(current))
175 if(!collision_object_map(current))
181 if(!collision_object_map(current))
188 while(!collision_object_map(current))
205 void collision_handler()
207 // CO_BULLET & CO_BADGUY check
208 for(unsigned int i = 0; i < world.bullets.size(); ++i)
210 for(unsigned int j = 0; j < world.bad_guys.size(); ++j)
212 if(world.bad_guys[j].dying != DYING_NOT)
214 if(rectcollision(&world.bullets[i].base, &world.bad_guys[j].base))
216 // We have detected a collision and now call the
217 // collision functions of the collided objects.
218 // collide with bad_guy first, since bullet_collision will
220 world.bad_guys[j].collision(0, CO_BULLET);
221 bullet_collision(&world.bullets[i], CO_BADGUY);
222 break; // bullet is invalid now, so break
227 /* CO_BADGUY & CO_BADGUY check */
228 for(unsigned int i = 0; i < world.bad_guys.size(); ++i)
230 if(world.bad_guys[i].dying != DYING_NOT)
233 for(unsigned int j = i+1; j < world.bad_guys.size(); ++j)
235 if(j == i || world.bad_guys[j].dying != DYING_NOT)
238 if(rectcollision(&world.bad_guys[i].base, &world.bad_guys[j].base))
240 // We have detected a collision and now call the
241 // collision functions of the collided objects.
242 world.bad_guys[j].collision(&world.bad_guys[i], CO_BADGUY);
243 world.bad_guys[i].collision(&world.bad_guys[j], CO_BADGUY);
248 if(tux.dying != DYING_NOT) return;
250 // CO_BADGUY & CO_PLAYER check
251 for(unsigned int i = 0; i < world.bad_guys.size(); ++i)
253 if(world.bad_guys[i].dying != DYING_NOT)
256 if(rectcollision_offset(&world.bad_guys[i].base,&tux.base,0,0))
258 // We have detected a collision and now call the collision
259 // functions of the collided objects.
260 if (tux.previous_base.y < tux.base.y &&
261 tux.previous_base.y + tux.previous_base.height
262 < world.bad_guys[i].base.y + world.bad_guys[i].base.height/2)
264 world.bad_guys[i].collision(&tux, CO_PLAYER, COLLISION_SQUISH);
268 tux.collision(&world.bad_guys[i], CO_BADGUY);
273 // CO_UPGRADE & CO_PLAYER check
274 for(unsigned int i = 0; i < world.upgrades.size(); ++i)
276 if(rectcollision(&world.upgrades[i].base, &tux.base))
278 // We have detected a collision and now call the collision
279 // functions of the collided objects.
280 upgrade_collision(&world.upgrades[i], &tux, CO_PLAYER);
286 Tile* gettile(float x, float y)
288 return TileManager::instance()->get(GameSession::current()->get_level()->gettileid(x, y));
291 bool issolid(float x, float y)
293 Tile* tile = gettile(x,y);
294 return tile && tile->solid;
297 bool isbrick(float x, float y)
299 Tile* tile = gettile(x,y);
300 return tile && tile->brick;
303 bool isice(float x, float y)
305 Tile* tile = gettile(x,y);
306 return tile && tile->ice;
309 bool isfullbox(float x, float y)
311 Tile* tile = gettile(x,y);
312 return tile && tile->fullbox;
315 bool isdistro(float x, float y)
317 Tile* tile = gettile(x,y);
318 return tile && tile->distro;