home *** CD-ROM | disk | FTP | other *** search
/ NetNews Offline 2 / NetNews Offline Volume 2.iso / news / comp / sys / amiga / programmer / 6884 < prev    next >
Encoding:
Internet Message Format  |  1996-08-05  |  6.7 KB

  1. Subject: Re: Collision Detects !!!!
  2. References: <199603311357.NAA27594@mailhost.unibol.com>
  3. Distribution: world
  4. X-Newsreader: TIN [version 1.2 PL2]
  5. Path: imada.ou.dk!breese
  6. From: breese@imada.ou.dk (Bjorn Reese)
  7. Message-ID: <1996Apr4.115256.19394@imada.ou.dk>
  8. Sender: news@imada.ou.dk
  9. Nntp-Posting-Host: salieri.imada.ou.dk
  10. Organization: Dept. of Math. & Computer Science, Odense University, Denmark
  11. Date: Thu, 4 Apr 1996 11:52:56 GMT
  12. Newsgroups: comp.sys.amiga.programmer
  13.  
  14. [ Sorry if this appears twice. My newsreader died on me when I
  15.   tried to post it the first time. ]
  16.  
  17. John Girvin (jgirvin@bfs.unibol.com) wrote:
  18.  
  19. > px2 = player->x + player->width        // PreCalc player BRHC coords.
  20. > py2 = player->y + player->height
  21. >
  22. > for (i=1; i<num_bullets; i++)
  23. > {
  24. >     if ( (bullet[i]->x - px2) < (bullet[i]->width + player->width) &&
  25. >          (bullet[i]->y - py2) < (bullet[i]->height + player->height) )
  26.  
  27. I might be missing something, but it seems to me that this only works
  28. under the assumption that the bullets are to the right and above the
  29. player (ie. bullet[i]->x < player->x and similar for y.) Furthermore,
  30. as player->width is present on both sides of the inequality it can be
  31. omitted.
  32.  
  33. > A not-so-obvious optimisation depends on the shape of your playing
  34. > area. If its tall and thin (eg: vertical scroller) then it is more
  35. > likely that the Y-coords will be "out of range" than the X coords,
  36. > so you should shift the Y comparison to be first in order to be more
  37. > likely to discard non-collisions on the first comparison. Vice-versa
  38. > if your playing area is wider than it is tall.
  39.  
  40. Yes, this is a nice optimisation technique which also may be applied
  41. to programming in general. For instance if you have to do different
  42. things if a value is positive, negative, or zero, it may be a good
  43. idea to check for the positive case first if that is most likely to
  44. happen.
  45.  
  46. Optimizing collision detection is strongly dependent on the
  47. environment in which it takes place and the number of entities to
  48. check.
  49.  
  50. The simple "check all ordered pair of entities" approach will
  51. always win over more sophisticated approaches if the number of
  52. entities are small (without specifying how small "small" is.)
  53.  
  54. With specific knowledge of the environment in which to do the
  55. collision detection must take place, there are specific tricks
  56. that you can utilize. One that immediately springs to mind is if
  57. you have a horizontal scrolling game (same applies to vertical
  58. scrolling) you can keep all entities in a list sorted by the
  59. x-coordinate. Instead of checking for collision with all other
  60. entities, it is sufficient to check with those within range.
  61.  
  62. > Also, look for references on "sector based collision detection",
  63. > especially around rec.games.programmer archives (HINT!). It might
  64. > help you more if you have lots of objects to check.
  65.  
  66. I never really liked this idea of subsections for two reasons.
  67.  
  68.   (1) Problems with boundaries. To solve this you have to check
  69.       the neighbouring subsections as well.
  70.  
  71.   (2) Static segmentation. Choosing many small subsections may
  72.       require too much management of their lists (or arrays) as
  73.       the entities moves around. Choosing fewer bigger subsection
  74.       will gain nothing if most entities are clustered in the
  75.       adjacent subsection (which they often are.)
  76.  
  77. Subsections (static partitioning) can be sketched by this
  78.  
  79.   for previous, current & next y-subsection
  80.     for previous, current & next x-subsection
  81.       CheckCollision
  82.  
  83. Add to this the cost of maintaining the entities in the subsections.
  84.  
  85.  
  86. I personally prefer a dynamic partitioning. This is an extension of
  87. the horizontal scrolling trick mentioned earlier in this letter.
  88.  
  89. What you do is maintain two linked lists; one with all entities sorted
  90. by their x-coordinate, and one by their y-coordinate. It isn't necessary
  91. to sort the entire lists each frame. As the entities only move relatively
  92. short distances you can just "bobble" the entities into their correct
  93. position (ie. let them switch position in the linked list if their
  94. keys - the x and y coordinates respectively - demands this.)
  95.  
  96. Okay, now that we've got the two ordered lists, it is sufficient to check
  97. for collision with the entities that are within range by transversing
  98. through the lists. Once we get to an entity that is out of range we can
  99. discard the rest of the list (in one direction as we have to check each
  100. list in both directions from the current entity.)
  101.  
  102. This, however, can be further "cooked down" if the collision handling
  103. is expensive in itself. Currently we check a "band" on both the x and
  104. y axis (the x's, y's and the O in the figure below) although we only
  105. need to check the intersection of these two bands (the O.) To do this
  106. we just mark entities as potential check when we run through the x
  107. list, and do the collision handling when we run through the y list
  108. if they were mark in the previous run.
  109.  
  110.     +------+-+----+
  111.     |      |y|    |
  112.     |      |y|    |
  113.     +------+-+----+
  114.     |xxxxxx|O|xxxx|
  115.     +------+-+----+
  116.     |      |y|    |
  117.     +------+-+----+
  118.  
  119.  
  120. So what you need to do is the following
  121.  
  122.   while (|dx| > dx0) do
  123.     mark agent
  124.   while (|dy| > dy0) do
  125.     if (agent is marked) then HandleCollision
  126.  
  127. Furthermore there is the cost of maintaining the two ordered list, plus
  128. the set used for marking.
  129.  
  130. The (untested) code below works under the assumption that there is a
  131. known maximum number of entities (SETSIZE), and that each entities has
  132. a unique ID number (from [0,SETSIZE-1].) Furthermore, the maximum width
  133. and height of the entities must be known (XSIZEMAX and YSIZEMAX.) An
  134. entity is called an agent.
  135.  
  136.  
  137. typedef struct Agent {
  138.   /* ... whatever ... */
  139.   int xpos, ypos;
  140.   int xsize, ysize;
  141.   int id;
  142.   struct Agent *xnext;
  143.   struct Agent *xprev;
  144.   struct Agent *ynext;
  145.   struct Agent *yprev;
  146. } agent;
  147.  
  148.  
  149. /* for each agent call Collide() */
  150.  
  151. void Collide(agent *p)
  152. {
  153.   static unsigned int scnt = 0;
  154.   static unsigned int set[SETSIZE];
  155.   agent *s;
  156.   int t;
  157.  
  158.   if (scnt++ == 0) memset(&set, '\0', SETSIZE);
  159.  
  160.   t = p->xpos + p->xsize + XSIZEMAX;
  161.   for (s = p->xnext; s && (s->xpos < t); s = s->xnext)
  162.     /* --- Mark s->id as member of set --- */
  163.     set[s->id] = scnt;
  164.   t = p->xpos - (p->xsize + XSIZEMAX);
  165.   for (s = p->xprev; s && (s->xpos > t); s = s->xprev)
  166.     set[s->id] = scnt;
  167.  
  168.   t = p->ypos + p->ysize + YSIZEMAX;
  169.   for (s = p->ynext; s && (s->ypos < t); s = s->ynext)
  170.     /* --- Is s->id member of set? --- */
  171.     if (set[s->id] == scnt) HandleCollision(p, s);
  172.   t = p->ypos - (p->ysize + YSIZEMAX);
  173.   for (s = p->yprev; s && (s->ypos > t); s = s->yprev)
  174.     if (set[s->id] == scnt) HandleCollision(p, s);
  175. }
  176.  
  177.  
  178. Sorry 'bout the long posting. I sorta got carried away ;)
  179.  
  180. --
  181. Bjorn Reese                      Email: breese@imada.ou.dk
  182. Odense University, Denmark       URL:   http://www.imada.ou.dk/~breese
  183.  
  184. "It's getting late in the game to show any pride or shame" - Marillion
  185.