The talk, entitled Beyond hitTest(): Proper collision detection in ActionScript, delves into the techniques used in N to code a robust and fast physics engine in ActionScript (used for Flash applications).
–= Script =– PART -1: intro/preamble [3]** -download the slides at: [++TODO: URL to slides.. metanet/tutorials/fitc05.zip?] who am i -one of two people who made N -we've been using flash since v5 (i.e since actionscript was useful and easy to use) <short demo of N, just watch a mainmenu replay>** -promo blurb: "N is a platform/run-and-jump game which combines oldschool gameplay with modern collision detection + physics simulation" -we made N with flash prove that flash/actionscript could be used for "real video games" [4]** -"the curse of sylvaniah" (by Strille/Luxregina) is another great game which also proves our point: games made in flash can be "real video games" [5]** -collision detection is a vast feild of research -impossible to cover properly in an hour. -i'll present specific methods well-suited for use in flash/actionscript -some of the ideas we used in N, as well as some of the stuff we've learnt since making N -there is a LOT of stuff to cover -i'm going to try to introduce you to the ideas involved without a lot of technical detail -understand the concepts, independent from the implementation of the concept -there WILL be some code and formulas and stuff -it's more important to understand the meaning behind the code and formulas. -you can check out our online tutorials if you need to look at source. -warning: i'm a programmer. these slides count as "programmer art". -ask: -how many people know what a vector is? -how many people know what a dotproduct is? [6]** -to begin: -this lecture is about collision detection -implicitly, it's about game programming in flash -game programming in flash feels a bit wrong. -it certainly wasn't made for video games. -there is a sense of "we're abusing this platform" -but we're going to write games in flash anyway, so why not try to do it well. -i'll start by trying to convince you about why collision detection matters -then i'll discuss some solutions for dealing with collision detection MOTIVATION: -why does collision detection matter? is it only useful for ninja platformers? [7]** -no. a lot of games would benefit from better collision detection/response -everyone's favorite, the top-view racing game -pool, pinball, -basketball/sports (show McShitOut and/or scribball demo) -platforming games [8]** -most importantly: _new_ types of genre-defying games which you're going to invent next week [9]** -having a good collision detection+response system enables a wide range of (otherwise inaccessible) gameplay possibilities. [10]** -HitTest: -why do we need to learn about collision detection? -doesn't flash already have built-in collision detection? -yes, but it has two major weaknesses 1: only returns a yes/no answer 2: only works with axis-aligned rectangles [11]** -what can you do with a yes/no answer?: [12]** -destroy one/both objects [13]** -move one/both objects to old position [14]** -reverse direction of one/both objects -or any combination of the above [15]** -what can't you do with a yes/no answer?: [16]** -friction and bounce [17]** -sliding along obstacles [18]** -rotating to orient to the ground -etc. [19]** -what can you do with axis-aligned rectangles?: -anything! ..as long as it involves unrotated rectangles [20]** -what can't you do with axis-aligned rectangles?: -circles -concave surfaces -curved or angled surfaces -rotating shapes -etc. [21]** -using hittest, if you need more than a yes/no answer about a collision, you can use "tricks": -sample multiple points on an object -from the multiple yes/no results, infer information about the collision direction, etc. -if you work hard enough, you _might_ get it to work.. [22]** -it will be slower than it needs to be (due to the number of calls to hittest) -it won't work 100% of the time (because you're relying on implied/approximated and not actual information) -it just doesn't feel as solid as "the real thing" [23]** -HitTest is awesome -- if you're living in the 80s -lots of moving rectangles which explode when they touch each other -if you want to actually respond to collisions in a meaningful way, HitTest isn't enough -meaningful collision response requires meaningful information about the collision. -better information, better response, better games, better "feel" -ultimately, "real" (non-HitTest) collision detection enables "physics" -physics?! [24]** -in video games this year, "physics is the new graphics".. everyone wants more physics in their games. -one common misconception is that "physics" means "slow and complex code". physics doesn't have to be complicated or slow. <demo ragdoll>** [25]** -"physics" is a much-abused term. -most of the time it just means "things moving". -if you've ever written "position += velocity" or "newpos = oldpos + velocity", you've already been using "physics". -what are you afraid of? [26]** -the only math you need to know is some vector algebra/geometry which we'll cover -no trig: trig is horrible -it's very difficult to develop an intuition about it -it's very hard to visualize when thinking about a problem -vectors are your friends -they can be used to replace trig in 99% of situations -they are easy to visualize and develop intuitions about [27]** -most importantly: flash vs. SNES -way less graphical power, way more processing power -flash can't compete with modern (or even classic) video games when it comes to graphical power -consoles and PCs have dedicated graphics hardware; flash has only got the CPU -flash CAN compete in terms of processing power and memory -the SNES (which came out in 1991) had the same processor as an apple IIgs.. -even with the overhead of the flashplayer VM, flash outperforms the SNES in terms of both speed and complexity -double-precision floating point, which lets us do a lot of things which simply weren't possible on an SNES -because of the overhead of the flash VM, "expensive" ops like sqrt() aren't really much more expensive than any other math op (+, -, etc.) -this gives us flexibility to pursue different solutions (which might not be tractable on other platforms) -flashplayer has built-in support for sophisticated structures like hashmaps (i.e "objects") and dynamic memory management -this makes it easier for us to explore complex ideas than possible on a SNES [28]** -so: flash games have the ability to compete with modern (or classic) video games on the battlefield known as "gameplay" -collision detection and physics are two great tools for developing novel gameplay [29]** -some examples of games that are using collision detection and physics to create different types of gameplay [30]** [31]** [32]** -hopefully you're now motivated [33]** PART 0: collision response -collision response is important to mention breifly because it provides the motivation for collision detection -see our website for tutorials and links to more info -collision response is _why_ you need a collision detection solution that's more informative than HitTest -collision detection provides you with information describing a collision; -if you don't _use_ this information in a meaningful way, CD is moot [34]** -collision response "in a nutshell": -there are many different ways to handle collision response -they all of the need to know the same thing [35]** -penetration direction, penetration amount -pdir*pamt = penetration vector, projection vector, etc. -i may use "penetration vector" and "projection vector" interchangeably [36]** -one thing we want to do when notified of a collision is prevent the two colliding objects from continuing to collide -a simple solution to this is "projection" -given two colliding objects and their penetration vector -translate (move) one object by the penetration vector -OR: translate both objects by 1/2 the penetration vector -etc.. playing with the ratios allows the simulation of objects with different relative mass -i.e heavy objects aren't moved very much [37]** -aside from preventing the objects from continuing to overlap, you can modify their properties based on the direction of the collision surface -penetration vector describes the surface direction of the collision -you can measure the velocity of objects parallel to and perpendicular to the surface -we'll cover the math later, it's simple vector projection [38]** -you break the object's velocity down into those two components -scale each component seperately/differently, and recombine them to get the post-collision velocity -this lets you simulate friction/bounce -you can also let game logic make decisions based collision information -rotating object graphics so that they align themselves to the ground -inflicting damage for violent collisions (the object's velocity perpendicular to the surface tells you how violent the collision was) <demo: level 0-0, ninja skidding around and rotating to match the surface of things>** <demo: level 0-0, ninja falling to death>** [39]** PART 1: narrow-phase collision detection, aka object-vs-object testing [40]** -so, what we need to do when performing collision detection on a pair of shapes is: (a) determine if the two shapes are colliding, and if so (b) calculate the penetration vector which describes the collision [41]** -actually.. that's only half of the collision detection problem. -the other half is knowing which pairs of shapes to test in the first place [42]** -these two parts of the collision detection process are often called "narrow" and "broad" phase collision detection -broad = figuring out which pairs of objects we must test -narrow = testing each pair -sort of like sifting through something: start with a coarse filter to elliminate most things, then use a fine-grained filter on the remaining stuff -we'll start with narrow-phase and then discuss broad-phase -i'll try to answer questions breifly after each section -i'd prefer to stick to specific questions (i.e if i'm not explaining something in detail) -leave larger questions for Q&A at the end of the presentation -there are several different approaches to object-vs-object tests; the one i'm going to describe is based on something called "the method of seperating axes" <todo: refer to ginoVDB and geomtools books> -it's well-suited for flash -fast (faster than any other method we've seen) -simple (easy to understand, easy to code) -flexible (easy to adapt to many different situations) [43]** -the method of seperating axes, in english -there will be a lot of "axis" talk -axis really just means "direction". any time you hear "axis", you can mentally substitute "direction". -1 vector, many vertices -1 axis, many axes [44]** -the Method of Seperating Axes is based on the Seperating Axis Theorem: -a mathmatical theorem about the properties of convex polygons [45]** -thus, this method only works for convex shapes -what is a convex shape? probably you've at least got an intuitive understanding of convexity. there are many "practical" definitions: -no internal angles <= 180deg -a line connecting any two points inside the shape is contained within the shape -only lefthand turns when walking CCW around the surface -etc. [46]** -Seperating Axis Theorem, part 1: -if two convex polygons don't overlap, then there must be a direction along which they are "seperated" -the converse is also true: if there is no direction which seperates two objects, the objects must be overlapping -"seperated" means that, if we look at the world along that direction, there is a space between the two shapes -the direction we look along is called an axis -if the two objects are seperated, it's a seperating axis -you could think of it as a line through the objects; it's offset in diagrams to make it less cluttered/confusing <diagram: show seperated and overlapping cases> [47]** -Seperating Axis Theorem, part 2: -we don't have to test _all_ directions; if there is a seperating axis, then it must be perpendicular to an edge of one of the shapes -so, instead of testing all possible directions to find a seperating axis, we only test those directions which are perpendicular to the edges of our polygons <diagram: as before, but point out/focus on normal directions> -there's a proof for the SAT, but that's (thankfully) outside the scope of this lecture -we didn't invent this method, we just noticed that other game programmers were using it [48]** -the Method of Seperating Axes is a method of collision detection which is based on SAT: -given two shapes, determine all the potentially seperating axes for those shapes -i.e determine the directions which are perpendicular to each edges of each polygon -test each potentially seperating axis until we find an axis along which the objects are seperated -if we've tested all potentially seperating axes and found none that are seperating the objects, the objects are colliding -instead of a single, complicated 2D test (based on minimum distance or whatever), we perform a series of simple 1D tests -each test is along a different direction, or "axis" -each test boils down to a few lines of very simple (and fast) math -we'll get to the math shortly -the strength of this method is the "early out" -we don't need to test every potentially seperating axis; as soon as we find an axis which seperates the two shapes, we know (thanks to the SAT) they can't be colliding and we can skip the rest of the axes -this means when two objects aren't colliding, we do less work than when they are -in a typical game, any two objects picked at random are likely NOT colliding, so optimising the not-colliding case makes sense and really speeds things up [49]** -before we get into actual code, let's review some basic vector algebra/geometry -basic vector math: nothing to be afraid of [50]** -vectors (difference of two points) [51]** -unit vectors/direction -unit vectors: vectors whose length is 1 -very useful to use these to represent directions, INSTEAD of angles/radians/etc. -they've got some useful properties which we'll see in a moment -formula/code: -basically, you divide x and y components by the length of the vector -null (0-length) vectors don't work -when you multiple a unit vector by a scalar X, the result is a vector which points in the same direction as the unit vector, but which is X units long -in this presentation, whenever you hear "axis" (and/or "direction"), this means normalized unit vector -the process of taking a vector and scaling it until it's unit-length is called "normalization" -the vector has been normalized -NOT to be confused with the following [52]** -normal vectors (NOT to be confused with normalized vectors! althouth.. normal vectors are often normalized..) -perpendicular to a vector -formula/code: it's so simple it's weird that the results are meaningful/useful -each vector has two of these, LH and RH [53]** -by convention, polygon edges are arranged in CCW order -this means that each edge's RHnorm points "out" of the polygon edge -these are of special importance to us: the RHnorms of each edge of a polygon _are_ the potentially seperating axes we must test [54]** -dotproduct -in highschool you may have learnt a definition of dotprod involving cosine: -AdotB = |A|*|B|*cos(angle between A and B) -this is irrelevant -dotprod is a measure of the relative directions of two vectors -formula/code: as with normal vectors, it's so simple it's weird that the results are meaningful/useful -the important thing to note is that: -when two vectors point in the same direction, their dp is at maximum value -then they point in opposite directions, their dp is at minimum value -when they're perpendicular to each other, their dp is 0 [55]** -if vector A is unit length and vector B isn't, the min/max values of their dp are -/+ the length of B -the value of the dp is no longer just some value, it's now "meaningful": -it's the _length_ of vector B when "measured along" the direction described by vector A -"measured along, viewed along, the length of the image of B on A", etc. -this is important for projection [56]** -vector projection -just one multiplication step added onto the end of a dotprod -as we just learnt, when vector A is unit length, and vector B isn't, AdotB gives you the length of the "image" of B, when measured along A -we can make a vector of length AdotB, which is parallel to A -just multiply A (unit vector) by AdotB -that vector is called the projection of B onto A -you can think of it as "B when viewed/measured along the line containing A" -mapping 2D to 1D [57]** -this is the core of our method: projecting shapes onto each potentially seperating axis -if we only care about the length of the projected vector (i.e the dotproduct), we can use the dotproduct itself -this is also what we use for friction/bounce -as we saw earlier, you decompose object velocity into two perp. components by projecting them onto the surface direction [58]** -the method of seperating axes, revisited -the if(overlap) step is "where all the action is" [59]** -example: Box vs. Box -figure out which axes we have to test -aside: normally, testing two quadrilaterals would involve testing 8 potentially seperating axes (4 from each quad) -boxes are a special case which exploit the SAT's rules -we need to test all directions which are perpendicular to the surface of each shape -since, for each box, a single direction is perp. to two surfaces, we can perform a single axis test for each pair of opposite box edges -anyway: -calculate the object-object delta vector (vector from center of one object ot center of the other) -for each potentially seperating axis (show all 4 axes, then show each step below on a single axis): -calculate the projected halfsize of each object (projected = when measured along the axis) (BLUE) -calculate the projected length of the delta vector (projected = when measured along the axis) (GREEN) -calculate the difference between the sum of the halfsizes, and the delta vector -if negative, we've found a seperating axis and we can stop: the shapes don't overlap -if positive, objects overlap along the axis, continue testing (RED) [60]** -if, after testing each axis, we still haven't found a seperating axis, then the objects must be colliding [61]** -what??!? i'm confused.. -why are we using this weird concept of "halfsize"? -don't we still end up with only a yes/no answer? i thought this approach was supposed to give us more info -..wait a minute. -this might seem familiar. [62]** -one very useful insight for understanding this approach is that it's a generalisation of circle-circle collision detection (which everyone is probably familiar with) [63]** -circle-circle <diagram each step> -calculate the object-object delta vector -for each potentially seperating axis (in this case, there's only one: the axis which passes through both circles' centers) -calculate distance between circles -SAT: calculate the projected size of the delta vector (in this case, this is == the length of the delta vector) -calculate sum of radii -SAT: calculate the projected halfsize of each object (in this case, this is == their radius) -calculate the difference between the sum of halfsizes/radii and the delta vector -if positive, objects overlap along the axis [64]** -not only does this help us understand what's going on in our SAT test, it also suggests how to get more than a yes/no answer from the results -do whatever we do in the circle-circle case -if the circles ARE overlapping -the penetration direction is parallel to the axis -the amount is equal to the difference we calculated (sum-of-radii minus size-of-delta) [65]** -Box-vs-Box revisited -it's the same process as with two circles, except that we have to test more than just a single potentially seperating axis -each axis test is analogous to the circle-circle test, they just involve a bit more math, to project things onto the axis.. -in the circle case, the object halfwidths and delta vectors are parallel to the axis -as we saw with dotprods, when you project a vector onto an axis that's parallel to the vector, you get the original vector -like multiplying any number by 1 -so, for circles, the values are basically "pre-projected" and we skip the projection math -as soon as we find a seperating axis, we're done -- we know the objects don't overlap [66]** -as with circles, if the objects ARE overlapping (i.e we tested all axes and none are seperating the two objects), we can extract collision info "for free" from the per-axis calculations we made -the axis with the smallest "difference" (sum-of-halfsizes minus size-of-delta) is the projection direction -the size of the difference is the projection amount -projection direction + projection amount = projection vector. tada! [67]** -so, we can use this method to collide any two shapes together, provided that for each shape we can quickly determine: a) which directions are perpendicular to the shape's surface (i.e which axes are potentially seperating directions for that shape) b) how to project the shape onto an axis, i.e -the shape's center (when projected onto an axis) -the shape's size/halfsize (when projected onto an axis) [68]** -example: projecting a box onto an axis -this is code for an arbitrarily rotated box (in the diagrams, we're just keeping the box still and moving the axis..) -it's the same thing/relativity -an important insight for box projection is: the sum of the projections of the halfwidth vectors = projected halfwidth of box <point to diagram of this> [69]** -box representation: -position (of box center) -width/height (along object axes) -unit vector (describing orientation of box; we use the convention that the orientation vector points along local x) -see our tutorials for examples of how to project different shapes -linesegs should be obvious [70]** -step through Box-vs-Box code line-by-line, examining/explaining it -point out that you COULD make the code more generic/general -each shape has an array of unit vectors representing potential seperating axes -each shape has a function "Project" which return the object's halfsize when projected onto a given axis -however, if you want to it run as fast as possible, writing special code for each possible combination of objects is the best solution [71]** -what we left out: [66]** might help when explaining this -tracking minimum penetration axis -store all pen amounts and compare them at the end, or keep a "running minimum" -which direction to project? -projdir is parallel to the axis of minimum projection, but could point in two possible directions -use the sign of the delta<dot>axis [72]**-what about circles? -we haven't mentioned circles or curved surfaces yet, but they're very useful as collision shapes -the main difference between circles and polygons is the behaviour around corners (vertices) -circles "roll" around corners: the collision direction changes smoothly -polygons slide across them: the collision direction remains the same (surface normal) <demo: use tutorialA demo: circle falling/sliding off the top of a square>** <demo: as above, but use an AABB falling/sliding off the top of a square>** -another way to look at this difference is that, unlike polygons, there aren't a finite/discrete number of directions perpendicular to a circle's surface -this is a problem, since our approach relies on knowing which directions might be potentially seperating directions -but: since this SAT approach is a sort of generalization of circle-circle collision, surely we can support circles without too much extra work [73]** -we can -instead of reiterating what's presented in our online tutorials, i'll just refer you to them -the basic idea is that for a circle you perform the exact same tests as you would for a box, except you sometimes perform a single additional test at the end -to handle the case where the circle is colliding with a "corner" (vertex) of a shape instead of an edge (lineseg) -you don't always have to perform this test -there is a fast and simple way to determine if you have to perform this additional test -you can use information from the axes you've already tested -if the overlap along the box axes is less than the circle's radius, we know the circle is in a corner region <demonstrate the above values/etc. with the diagram> -if the circle's center is in the horiz/vertical regions, we only test the two box axes -we can tell if the circle is in these regions by looking at the results of these 2 axis tests -if the circle's NOT in these regions, we have to test it vs. the nearest box corner -again, which corner to use is easy since part of the 2 axis tests was determining the box->circle delta vector -this delta vector "points" at the box corner [74]** -what about non-convex shapes? -this is important, especially for world/level shapes -just represent them as a union of convex shapes -several (possibly overlapping) convex shapes [75]** -tilebased games use the same idea: decompose the world into small chunks [76]** -a different decomposition is: linesegs -this is leading into the next section into broad-phase [77]** -optimisations: -the key is to precompute as much information as possible, so that you don't have to calculate it at runtime -instead you just lookup your precomputed value -almost every game subscribes to the rule: "the vast majority of things in the world are static" -i.e the game code makes a distinction between (static) world/level geometry, and (dynamic) objects -makings things static is a great optimisation because we can precompute almost everything about each static object -triangles and more complex shapes are harder to project than a box -more lines of code -you _can_ still do it on the fly, it's just slower -calculations for circles and boxes are very fast and simple; they make good candidates for dynamic objects -more complex shapes can be used for static objects, since most of the calculations (calculating surface normals aka axis directions, etc.) can be done beforehand instead of at runtime [78]** QUESTIONS about Seperating Axis Thereom / Method of Seperating Axes [++TODO: figure out how much time we can spend here, and note it down so that, when presenting, we don't get stuck here for too long] [79]** PART 2: broad-phase collision detection, aka spatial database -switching gears... [80]** -knowing how to test two objects for collision is only part of the solution to the CD problem [81]** -if there are 10 objects in the world, we'd have to perform 10*10=100 tests -it doesn't matter how fast your object-object test is if you're using it 100 times per frame -for N objects, you have to use N^2 tests [82]** -we want to be able to very quickly determine which pairs of objects we should test, i.e which pairs MIGHT be colliding -how to figure out what might be colliding? -all the methods i know of for broad-phase CD use the assumption: if two objects are near each other, then they might be colliding -quickly == approximately; we don't need to know for sure, that's the job of the narrow-phase -once we know which pairs MIGHT be colliding, we can pass them to our narrow-phase collision system to figure out if they actually _are_ colliding, and if so, how. -so, we just need to find a way to quickly determine, given an object or a position in the world, all of the other objects nearby -this step is _very_ game specific -there is no "magic bullet" [83]** -for small numbers of objects (<=5), using HitTest on each possible pair is often "good enough" -you're still doing N^2 tests, but you're not doing too many of them, and they're not too expensive -it's fast, and it tells you what you need to know (that the objects might be colliding) -if HitTest returns true, you know their bounding boxes are overlapping, and can investigate further using complex tests -however, for the sake of argument, SAT code for AABBs (i.e rectangles) can be just as fast as Hittest -the main cost is the overhead of a function call [84]** -for larger numbers of objects, you need a more sophisticated way to find all the objects near a given point -this problem has been solved in many different ways: -grid: divide space into uniform boxes [85]** -quadtree: recursively subdivide space into 4 equal regions [86]** -they all amount to the same thing: partitioning space into discrete chunks, and building a database using those chunks -the data in the database is the location of objects -hence broad-phase collision systems are often called spatial databases -the two most important operations on this database are: a) neighborhood query (quickly determining which objects are near a given position) b) updating an entry in the database (i.e moving an object) -optimising (a) is very simple if you don't care about (b) -games which must support large numbers of moving objects must optimise (b) -it's hard to do both at once; this is why broad-phase is so game-specific [87]** -grids are best for flash -there are many different ways to use grids, but ALL of them are better suited for flash than non-grid-based methods -why only grids? -grids allow for constant-time neighborhood queries, and constant-time updating -the constant cost is extremely low -for a neighborhood query, you simply find the cell which contains your query point, then look in the surrounding cells -to update the position of an object in the grid, you just need to find the cells which the object touches, which is fast and simple -more on this later -all other spatial database approaches are based on search-trees of some sort -the quadtree i showed you LOOKED sort of like a grid, but the implementation looks like a normal tree data structure -each node has 4 children, etc. -when you look something up from a tree, you have to descend to the leaves, performing tests at each level of the tree -each test takes time -grids only require one test, not one test per level of the heirarchy -likewise, inserting something into a tree is more complex than with a grid -if grids are so good, why don't other games use them? -most 2D games _do_ use grids -obviously, any tile-based game is using some sort of grid -even doom used grid-based collision [88]** -the problem with grids is that they take up a LOT of space, since the entire world must be covered in cells -a 200x100-tile world means a grid with 20000 cells; if each cell needs 256bytes, that's 5MB -in 3D, this only gets worse: 200x100x100 @ 256bytes = 500MB -this is why trees are used; they require far less memory. instead of covering the entire world, you only cover the non-empty parts of the world -the tradeoff is that trees are slower and more complex to query and update [89]** -in flash, in 2D, you can afford the extra memory needed by a grid, but you _can't_ afford the extra processing time required by trees [90]** -all grid operations involve a couple math ops -you can't get any faster than that [91]** -using a grid for object-vs-object tests -i'll just provide an outline of the process -see our online tutorials for implementation details and source code [92]** -a grid is just an abstract data structure; there are many differnet ways to actually use the structure. -two popular ways are "regular" and "loose" grids <explain the following in english while using diagram to illustrate> -regular grid: -every object knows which grid cell(s) it touches -every grid cell knows which object(s) are touching it <refer to diagram> each blue cell must be tested for collision, and each blue cell must be updated when objects move -loose grid: -every object knows which grid cell contains it's center -every cell knows which object(s) it contains <refer to diagram> each red cell must be tested for collision, and each blue cell must be updated when objects move -regular vs. loose: -less tests vs less time to update moving objects -can handle any sized shape vs shapes must fit in a cell [93]** -using a grid for object-vs-world -as mentioned earlier, most games divide objects into "static" and "dynamic" groups -you CAN simply use the grid to collide dynamic vs. static objects exactly as you would for dynamic vs. dynamic objects (as we just saw) -however, if you know that most of the game world will consist of static shapes, you might want to create a special system for colliding these static shapes against dynamic objects [94]** -there isn't time to explore all of the possible ways to use a grid for object-vs-world tests -i'll breifly cover 2 approaches -tilebased and geometry-based -tilebased collision: -each grid cell stores a tile shape -each moving object collides against all other moving objects and tiles in it's neighborhood -again, our online tutorials cover this topic very well (i'd rather not just repeat info that's already available) -tilebased systems SEEM like a good choice (simple and fast) -in practise they're quite hard to get good behaviour out of -tilebased collision is usually rule-based instead of math-based; rule-based works well for simple dynamic models, but when you start needing smooth physics-based object movement, rule-based collision simply doesn't perform well -you end up doing lots of extra work to get things behaving well -doing lots of extra work defeates the purpose of using a tilebased world in the first place, which was speed and simplicity -a different grid-based approach is geometry/lineseg based -the world is made out of polygons -convex or concave, it doesn't matter -as a preprocess, before runtime, you decompose your polygons into their component linesegs -insert each lineseg into a grid -determining which cells to insert a lineseg into can be done in several ways -since it's a preprocess it doesn't really matter how slow this code is -you can simply try lineseg-vs-AABB test for all cells touching the lineseg's bounding box -or you can use raycast code (which we'll touch on soon) -at runtime, object-vs-world collision involves one or two object-vs-lineseg tests -linesegs are the simplest and fastest shapes to collide against -they have only a single potentially seperating axis -performing several object-vs-lineseg tests is MUCH faster than performing several object-vs-tileshape tests -this system can support the exact same levels and shapes as a tilebased system -but it's far simpler -instead of having many different possible tile-shapes to collide against, you have just one shape: lineseg -it's also a lot faster -testing vs. linesegs is faster than vs. timeshapes [95]** -another great advantage that grids have over other spatial databases is: raycasting is very easy -rays are lines with one endpoint -they're used to model fast-moving bullets in many games (doom, quake) -they're also very useful for line-of-sight testing (AI uses these to determine what each enemy can "see") [96]** -a very efficient and simple to understand raycasting algorithm is presented in this paper -it's very simple, and very fast -yet again, please see our online tutorials for implementation details [97]** PART 3: misc/conclusion -summary: -collision detection is a powerful tool for making fun games -the MSA is a useful tool for narrow-phase collision detection -a uniform grid is a useful tool for broad-phase collision detection -QUESTIONS?