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 bool rectcollision(base_type* one, base_type* two)
20 return (one->x >= two->x - one->width + 1 &&
21 one->x <= two->x + two->width - 1 &&
22 one->y >= two->y - one->height + 1 &&
23 one->y <= two->y + two->height - 1);
26 bool rectcollision_offset(base_type* one, base_type* two, float off_x, float off_y)
28 return (one->x >= two->x - one->width +off_x + 1 &&
29 one->x <= two->x + two->width + off_x - 1 &&
30 one->y >= two->y - one->height + off_y + 1 &&
31 one->y <= two->y + two->height + off_y - 1);
34 bool collision_object_map(base_type* pbase)
36 int v = (int)pbase->height / 16;
37 int h = (int)pbase->width / 16;
39 if(issolid(pbase->x + 1, pbase->y + 1) ||
40 issolid(pbase->x + pbase->width -1, pbase->y + 1) ||
41 issolid(pbase->x +1, pbase->y + pbase->height -1) ||
42 issolid(pbase->x + pbase->width -1, pbase->y + pbase->height - 1))
45 for(int i = 1; i < h; ++i)
47 if(issolid(pbase->x + i*16,pbase->y + 1))
51 for(int i = 1; i < h; ++i)
53 if( issolid(pbase->x + i*16,pbase->y + pbase->height - 1))
57 for(int i = 1; i < v; ++i)
59 if( issolid(pbase->x + 1, pbase->y + i*16))
62 for(int i = 1; i < v; ++i)
64 if( issolid(pbase->x + pbase->width - 1, pbase->y + i*16))
72 void collision_swept_object_map(base_type* old, base_type* current)
74 int steps; /* Used to speed up the collision tests, by stepping every 16pixels in the path. */
76 float lpath; /* Holds the longest path, which is either in X or Y direction. */
77 float xd,yd; /* Hold the smallest steps in X and Y directions. */
78 float temp, xt, yt; /* Temporary variable. */
84 if(old->x == current->x && old->y == current->y)
88 else if(old->x == current->x && old->y != current->y)
90 lpath = current->y - old->y;
104 else if(old->x != current->x && old->y == current->y)
106 lpath = current->x - old->x;
121 lpath = current->x - old->x;
124 if(current->y - old->y > lpath || old->y - current->y > lpath)
125 lpath = current->y - old->y;
129 xd = (current->x - old->x) / lpath;
130 yd = (current->y - old->y) / lpath;
133 steps = (int)(lpath / (float)16);
138 for(float i = 0; i <= lpath; old->x += xd, old->y += yd, ++i)
147 if(collision_object_map(old))
152 current->y = old->y - yd;
153 while(collision_object_map(current))
157 current->x = old->x - xd;
158 while(collision_object_map(current))
164 current->x = old->x - xd;
165 current->y = old->y - yd;
166 while(collision_object_map(current))
174 if(!collision_object_map(current))
180 if(!collision_object_map(current))
187 while(!collision_object_map(current))
204 void collision_handler()
206 // CO_BULLET & CO_BADGUY check
207 for(unsigned int i = 0; i < bullets.size(); ++i)
209 for(unsigned int j = 0; j < bad_guys.size(); ++j)
211 if(bad_guys[j].dying != DYING_NOT)
213 if(rectcollision(&bullets[i].base, &bad_guys[j].base))
215 // We have detected a collision and now call the
216 // collision functions of the collided objects.
217 // collide with bad_guy first, since bullet_collision will
219 bad_guys[j].collision(0, CO_BULLET);
220 bullet_collision(&bullets[i], CO_BADGUY);
221 break; // bullet is invalid now, so break
226 /* CO_BADGUY & CO_BADGUY check */
227 for(unsigned int i = 0; i < bad_guys.size(); ++i)
229 if(bad_guys[i].dying != DYING_NOT)
232 for(unsigned int j = i+1; j < bad_guys.size(); ++j)
234 if(j == i || bad_guys[j].dying != DYING_NOT)
237 if(rectcollision(&bad_guys[i].base, &bad_guys[j].base))
239 // We have detected a collision and now call the
240 // collision functions of the collided objects.
241 bad_guys[j].collision(&bad_guys[i], CO_BADGUY);
242 bad_guys[i].collision(&bad_guys[j], CO_BADGUY);
247 if(tux.dying != DYING_NOT) return;
249 // CO_BADGUY & CO_PLAYER check
250 for(unsigned int i = 0; i < bad_guys.size(); ++i)
252 if(bad_guys[i].dying != DYING_NOT)
255 if(rectcollision_offset(&bad_guys[i].base,&tux.base,0,0))
257 // We have detected a collision and now call the collision
258 // functions of the collided objects.
259 if (tux.previous_base.y < tux.base.y &&
260 tux.previous_base.y + tux.previous_base.height < bad_guys[i].base.y + bad_guys[i].base.height/2)
262 bad_guys[i].collision(&tux, CO_PLAYER, COLLISION_SQUISH);
266 tux.collision(&bad_guys[i], CO_BADGUY);
271 // CO_UPGRADE & CO_PLAYER check
272 for(unsigned int i = 0; i < upgrades.size(); ++i)
274 if(rectcollision(&upgrades[i].base,&tux.base))
276 // We have detected a collision and now call the collision
277 // functions of the collided objects.
278 upgrade_collision(&upgrades[i], &tux, CO_PLAYER);