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"
18 int rectcollision(base_type* one, base_type* two)
21 if (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)
34 int rectcollision_offset(base_type* one, base_type* two, float off_x, float off_y)
36 if (one->x >= two->x - one->width +off_x + 1 &&
37 one->x <= two->x + two->width + off_x - 1 &&
38 one->y >= two->y - one->height + off_y + 1 &&
39 one->y <= two->y + two->height + off_y - 1)
49 int collision_object_map(base_type* pbase)
53 v = (int)pbase->height / 16;
54 h = (int)pbase->width / 16;
56 if(issolid(pbase->x + 1, pbase->y + 1) ||
57 issolid(pbase->x + pbase->width -1, pbase->y + 1) ||
58 issolid(pbase->x +1, pbase->y + pbase->height -1) ||
59 issolid(pbase->x + pbase->width -1, pbase->y + pbase->height - 1))
62 for(i = 1; i < h; ++i)
64 if(issolid(pbase->x + i*16,pbase->y + 1))
68 for(i = 1; i < h; ++i)
70 if( issolid(pbase->x + i*16,pbase->y + pbase->height - 1))
74 for(i = 1; i < v; ++i)
76 if( issolid(pbase->x + 1, pbase->y + i*16))
79 for(i = 1; i < v; ++i)
81 if( issolid(pbase->x + pbase->width - 1, pbase->y + i*16))
89 int collision_swept_object_map(base_type* old, base_type* current)
91 int steps; /* Used to speed up the collision tests, by stepping every 16pixels in the path. */
94 float lpath; /* Holds the longest path, which is either in X or Y direction. */
95 float xd,yd; /* Hold the smallest steps in X and Y directions. */
96 float temp, xt, yt; /* Temporary variable. */
102 if(old->x == current->x && old->y == current->y)
106 else if(old->x == current->x && old->y != current->y)
108 lpath = current->y - old->y;
123 else if(old->x != current->x && old->y == current->y)
125 lpath = current->x - old->x;
140 lpath = current->x - old->x;
143 if(current->y - old->y > lpath || old->y - current->y > lpath)
144 lpath = current->y - old->y;
148 xd = (current->x - old->x) / lpath;
149 yd = (current->y - old->y) / lpath;
152 steps = (int)(lpath / (float)16);
157 for(i = 0; i <= lpath; old->x += xd, old->y += yd, ++i)
166 if(collision_object_map(old))
171 current->y = old->y - yd;
172 while(collision_object_map(current))
176 current->x = old->x - xd;
177 while(collision_object_map(current))
183 current->x = old->x - xd;
184 current->y = old->y - yd;
185 while(collision_object_map(current))
193 if(!collision_object_map(current))
199 if(!collision_object_map(current))
206 while(!collision_object_map(current))
224 void collision_handler()
228 /* CO_BULLET & CO_BADGUY check */
229 for(i = 0; i < bullets.size(); ++i)
231 for(j = 0; j < bad_guys.size(); ++j)
233 if(bad_guys[j].dying == NO)
235 if(rectcollision(&bullets[i].base,&bad_guys[j].base) == YES)
237 /* We have detected a collision and now call the collision functions of the collided objects. */
238 bullet_collision(&bullets[i], CO_BADGUY);
239 badguy_collision(&bad_guys[j], &bullets[i], CO_BULLET);
245 /* CO_BADGUY & CO_BADGUY check */
246 for(i = 0; i < bad_guys.size(); ++i)
248 if(bad_guys[i].dying == NO)
250 for(j = i+1; j < bad_guys.size(); ++j)
252 if(j != i && bad_guys[j].dying == NO)
254 if(rectcollision(&bad_guys[i].base,&bad_guys[j].base) == YES)
256 /* We have detected a collision and now call the collision functions of the collided objects. */
257 badguy_collision(&bad_guys[j], &bad_guys[i], CO_BADGUY);
258 badguy_collision(&bad_guys[i], &bad_guys[j], CO_BADGUY);
267 /* CO_BADGUY & CO_PLAYER check */
268 for(i = 0; i < bad_guys.size(); ++i)
270 if(bad_guys[i].dying == NO && rectcollision_offset(&bad_guys[i].base,&tux.base,0,0) == YES )
272 /* We have detected a collision and now call the collision functions of the collided objects. */
273 if (tux.previous_base.y < tux.base.y &&
274 tux.previous_base.y + tux.previous_base.height < bad_guys[i].base.y + bad_guys[i].base.height/2 &&
275 bad_guys[i].kind != BAD_MONEY && bad_guys[i].mode != HELD)
277 badguy_collision(&bad_guys[i], &tux, CO_PLAYER);
281 player_collision(&tux, &bad_guys[i], CO_BADGUY);
286 /* CO_UPGRADE & CO_PLAYER check */
287 for(i = 0; i < upgrades.size(); ++i)
289 if(rectcollision(&upgrades[i].base,&tux.base) == YES)
291 /* We have detected a collision and now call the collision functions of the collided objects. */
292 upgrade_collision(&upgrades[i], &tux, CO_PLAYER);