THE N BUNKER Discord Server nplusplus
FITC05 slides: Collision detection in Flash
Slides of Raigan Burn's talk at FITC '05 (archived). Download slides (backed up from here, archived here). The additional Flash figures discussed in the talk are available here.
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?