phaser/wip/phaser clean up/fitc/FITC_beyondHittest.txt
2013-09-13 16:24:01 +01:00

715 lines
36 KiB
Text

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?