Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // File "SAT.as"
- package
- {
- import Box2D.Common.Math.b2Vec2;
- import flash.display.*;
- import flash.geom.*;
- import flash.events.*;
- import flash.utils.Timer;
- /**
- * SAT.as
- * Created On: 12/03/2012 17:46
- */
- [SWF(backgroundColor="0x000000", frameRate="60", width="800", height="600")]
- public class SAT extends Sprite
- {
- private static var square:Vector.<b2Vec2>;
- private static var canvas:Sprite;
- private var A:Shape2D;
- private var B:Shape2D;
- public function SAT()
- {
- // SPRITE TO DRAW SHAPES TO:
- canvas = new Sprite();
- // SHAPE OF A:
- A = new Shape2D(Vector.<b2Vec2>([
- new b2Vec2( -100, -100),
- new b2Vec2( -100, 100),
- new b2Vec2( 100, 100),
- new b2Vec2( 100, -100)]), new b2Vec2(550, 300), 45);
- // SHAPE OF B:
- B = new Shape2D(Vector.<b2Vec2>([
- new b2Vec2( -200, -50),
- new b2Vec2( -200, 50),
- new b2Vec2( 200, 50),
- new b2Vec2( 200, -50)]), new b2Vec2(250, 300), 175);
- // ADD CANVAS TO STAGE:
- stage.addChild(canvas);
- // DRAW A & B:
- A.draw(canvas, false);
- B.draw(canvas, false);
- collides(A, B);
- /*
- // TIMER THAT TRIGGERS FUNCTION 'ROTATE' EVERY 10MS:
- var t:Timer = new Timer(10);
- t.addEventListener(TimerEvent.TIMER, rotate);
- t.start();
- */
- }
- public function rotate(e:TimerEvent):void
- {
- // INCREMENT ANGLES:
- A.angle++;
- B.angle++;
- // CLEAR GRAPHICS:
- canvas.graphics.clear();
- // FILL SHAPE IF IT'S CURRENTLY COLLIDING:
- if (collides(A, B))
- {
- A.draw(canvas, true);
- B.draw(canvas, true);
- } else {
- A.draw(canvas, false);
- B.draw(canvas, false);
- }
- }
- public function collides(A:Shape2D, B:Shape2D):Boolean
- {
- var test1:Number; // numbers to use to test for overlap
- var test2:Number;
- var testNum:Number; // number to test if its the new max/min
- var min1:Number; // current smallest(shape 1)
- var max1:Number; // current largest(shape 1)
- var min2:Number; // current smallest(shape 2)
- var max2:Number; // current largest(shape 2)
- var axis:b2Vec2; // the normal axis for projection
- var offset:Number;
- var vectorOffset:b2Vec2;
- var vectors1:Vector.<b2Vec2>; // the points
- var vectors2:Vector.<b2Vec2>; // the points
- vectors1 = A.getOBB().concat(); // these functions are in my polygon class, all they do is return a Vector.<b2Vec2> of the vertices of the polygon
- vectors2 = B.getOBB().concat();
- /* SHOULDN'T NEED THIS AS BOTH VECTORS CONSIST OF 4 OBJECTS.
- * ALSO B2VEC2 DOESN'T HAVE A TRUNCATE FUNCTION.
- *
- // add a little padding to make the test work correctly
- if (vectors1.length == 2)
- {
- var temp:b2Vec2 = new b2Vec2(-(vectors1[1].y - vectors1[0].y), vectors1[1].x - vectors1[0].x);
- temp.truncate(0.0000000001);
- vectors1.push(vectors1[1].add(temp));
- }
- if (vectors2.length == 2)
- {
- temp = new b2Vec2(-(vectors2[1].y - vectors2[0].y), vectors2[1].x - vectors2[0].x);
- temp.truncate(0.0000000001);
- vectors2.push(vectors2[1].add(temp));
- }
- */
- // find vertical offset
- vectorOffset = new b2Vec2(A.position.x - B.position.x, A.position.y - B.position.y);
- // loop to begin projection
- for (var i:int = 0; i < vectors1.length; i++)
- {
- // get the normal axis, and begin projection
- axis = findNormalAxis(vectors1, i);
- trace("AXIS:", axis.x, axis.y);
- // project polygon1
- min1 = dotProduct(axis, vectors1[0]);
- max1 = min1;//set max and min equal
- for (var j:int = 1; j < vectors1.length; j++)
- {
- testNum = dotProduct(axis, vectors1[j]);// project each point
- if (testNum < min1) min1 = testNum; // test for new smallest
- if (testNum > max1) max1 = testNum; // test for new largest
- }
- trace("MIN1:", min1);
- trace("MAX1:", max1);
- // project polygon2
- min2 = dotProduct(axis, vectors2[0]);
- max2 = min2; // set 2's max and min
- for (j = 1; j < vectors2.length; j++)
- {
- testNum = dotProduct(axis, vectors2[j]);// project the point
- if (testNum < min2) min2 = testNum; // test for new min
- if (testNum > max2) max2 = testNum; // test for new max
- }
- trace("MIN2:", min2);
- trace("MAX2:", max2);
- // apply the offset to each max/min(no need for each point, max and min are all that matter)
- offset = dotProduct(axis, vectorOffset);// calculate offset
- min1 += offset; // apply offset
- max1 += offset; // apply offset
- trace("MIN1OFFSET:", min1);
- trace("MAX1OFFSET:", max1);
- // and test if they are touching
- test1 = min1 - max2; // test min1 and max2
- test2 = min2 - max1; // test min2 and max1
- trace("TEST1:", test1);
- trace("TEST2:", test2);
- trace("TEST1 > 0 || TEST2 > 0:", test1 > 0 || test2 > 0);
- if (test1 > 0 || test2 > 0)
- { //if they are greater than 0, there is a gap
- trace("RETURN: FALSE");
- return false;//just quit
- }
- }
- //if you're here, there is a collision
- var seperation:b2Vec2 = new b2Vec2(axis.x*((max2-min1)*-1), axis.y*((max2-min1)*-1)); //return the separation, apply it to a polygon to separate the two shapes.
- return true;
- }
- private function dotProduct(vecA_:b2Vec2, vecB_:b2Vec2):Number
- {
- return (vecA_.x * vecB_.x + vecA_.y * vecB_.y);
- }
- private function findNormalAxis(verts:Vector.<b2Vec2>, index:int):b2Vec2
- {
- var vector1:b2Vec2 = verts[index];
- var vector2:b2Vec2 = (index >= verts.length - 1) ? verts[0] : verts[index + 1]; //make sure you get a real vertex, not one that is outside the length of the vector.
- var normalAxis:b2Vec2 = new b2Vec2( -(vector2.y - vector1.y), vector2.x - vector1.x);//take the two vertices, make a line out of them, and find the normal of the line
- normalAxis.Normalize(); //normalize the line(set its length to 1)
- return normalAxis;
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement