Category Archives: motion

QuickBox2D w/ Key Controls

Actionscript:
  1. import com.actionsnippet.qbox.*;
  2. import Box2D.Common.Math.*
  3.  
  4. [SWF(backgroundColor=0xEFEFEF, width=700, height=600, frameRate=60)]
  5.  
  6. var sim:QuickBox2D = new QuickBox2D(this);
  7.  
  8. sim.setDefault({lineColor:0xCC0000, fillColor:0xCC0000});
  9.  
  10. // create compound shape (two circles and a box for the character)
  11. var charParts:Array = [];
  12. // x and y position are now relative to center of compound shape
  13. charParts[0] = sim.addBox({x:0, y:0, width:1, height:2});
  14. charParts[1] = sim.addCircle({x:0, y:-1, radius:0.5});
  15. charParts[2] = sim.addCircle({x:0, y:1, radius:0.5});
  16. var char:QuickObject = sim.addGroup({objects:charParts, x:2, y:2.5, allowSleep:false, angularDamping:0.8, linearDamping:1.5});
  17.  
  18. // vector for linear velocity of character
  19. var charVel:b2Vec2 = new b2Vec2();
  20.  
  21. // angular velocity of character
  22. var charVelAng:Number = 1;
  23. char.body.SetAngularVelocity(charVelAng);
  24.  
  25. // world/platforms
  26. sim.setDefault({lineColor:0x666666, fillColor:0x666666, height:0.5, density:0});
  27. sim.createStageWalls();
  28. sim.addBox({x:3, y:5, width:5});
  29. sim.addBox({x:11, y:5, width:5});
  30. sim.addBox({x:8, y:9, width:8});
  31. sim.addBox({x:4, y:13, width:8});
  32. sim.addCircle({x:16, y:8, radius:2});
  33. sim.addCircle({x:12, y:15, radius:2});
  34.  
  35. // falling circles
  36. sim.setDefault({lineColor:0x2870B5, fillColor:0x2870B5});
  37. for (var i:int = 0; i<15; i++){
  38.     sim.addCircle({x:5 + i, y:2, radius:0.25 ,density:1});
  39. }
  40.  
  41. sim.start();
  42.  
  43. // key controls
  44. addEventListener(Event.ENTER_FRAME, onLoop);
  45. function onLoop(evt:Event):void {
  46.     charVel = char.body.GetLinearVelocity();
  47.     charVelAng =  char.body.GetAngularVelocity();
  48.    
  49.     if (key[Keyboard.RIGHT]){
  50.         charVel.x += 1
  51.         char.body.SetLinearVelocity(charVel);
  52.        
  53.         charVelAng += 1;
  54.         char.body.SetAngularVelocity(charVelAng);
  55.     }
  56.     if (key[Keyboard.LEFT]){
  57.         charVel.x -=1;
  58.         char.body.SetLinearVelocity(charVel);
  59.        
  60.         charVelAng -= 1;
  61.         char.body.SetAngularVelocity(charVelAng);
  62.     }
  63.     if (key[Keyboard.UP]){
  64.          charVel.y = -10;
  65.          char.body.SetLinearVelocity(charVel);
  66.            
  67.          charVelAng *= 0.8;
  68.          char.body.SetAngularVelocity(charVelAng);
  69.     }
  70. }
  71. // basic key setup
  72. var key:Object = new Object();
  73. stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyPressed);
  74. stage.addEventListener(KeyboardEvent.KEY_UP, onKeyReleased);
  75. function onKeyPressed(evt:KeyboardEvent):void {
  76.     key[evt.keyCode] = true;
  77.     key.keyCode = evt.keyCode;
  78. }
  79. function onKeyReleased(evt:KeyboardEvent):void { key[evt.keyCode] = false}

This snippet shows one way to go about doing key controls using QuickBox2D

Take a look at the swf here...

This works with the current version of QuickBox2D.... tomorrow I'll be uploading the new version of QuickBox2D which supports FRIM (frame rate independent motion) and contains a few additional minor tweaks and fixes.

Also posted in Box2D, QuickBox2D, keys | Tagged , , , | 1 Comment

IGraphicsData Example

Actionscript:
  1. // note the high framerate for testing purposes
  2. [SWF(width = 800, height = 600, frameRate=60)]
  3. // red, yellow, blue
  4. var fills:Vector.<IGraphicsData> = Vector.<IGraphicsData>([new GraphicsSolidFill(0xFF0000),  new GraphicsSolidFill(0xFFCC00), new GraphicsSolidFill(0x0033FF)]);
  5.  
  6. var stroke:IGraphicsData = new GraphicsStroke();
  7.  
  8. var cmds:Vector.<int> = new Vector.<int>();
  9. var ci:int = 0;
  10. var dat:Vector.<Number> = new Vector.<Number>();
  11. var di:int = 0;
  12. var igraph:Vector.<IGraphicsData> = new Vector.<IGraphicsData>();
  13. var ig:int  = 0;
  14. var path:Vector.<GraphicsPath> = new Vector.<GraphicsPath>();
  15. var boxNum:int = 1500;
  16. var locX:Vector.<Number> = new Vector.<Number>(boxNum);
  17. var locY:Vector.<Number> = new Vector.<Number>(boxNum);
  18. var velX:Vector.<Number> = new Vector.<Number>(boxNum);
  19. var velY:Vector.<Number> = new Vector.<Number>(boxNum);
  20. var cols:int = 50;
  21. for (var i:int = 0; i<boxNum; i++){
  22.     path[i] = new GraphicsPath(new Vector.<int>(), new Vector.<Number>());
  23.     path[i].winding = GraphicsPathWinding.NON_ZERO;
  24.     var theta:Number = i * Math.PI/180;
  25.     var sin:Number = Math.cos(theta);
  26.     var cos:Number =  Math.sin(theta);
  27.     var r:Number = Math.random()*100;
  28.     var vr:Number = r * 0.05;
  29.     velX[i] = vr * cos;
  30.     velY[i] = vr * sin;
  31.     locX[i] = 400 + r * cos;
  32.     locY[i] = 300 + r * sin;
  33. }
  34.  
  35. // box vars
  36. var xp:Number, yp:Number, size:Number, hs:Number;
  37. // corners
  38. var x0:Number, y0:Number, x1:Number, y1:Number;
  39.  
  40. addEventListener(Event.ENTER_FRAME, onLoop);
  41. function onLoop(evt:Event):void {
  42.     graphics.clear();
  43.     ig = 0;
  44.     for (i= 0; i<boxNum; i++){
  45.         // inline function:
  46.         locX[i] += velX[i];
  47.         locY[i] += velY[i];
  48.         xp = locX[i];
  49.         yp = locY[i];
  50.         if (xp <0 || xp> 800){
  51.             velX[i] *= -1;
  52.         }
  53.         if (yp <0 || yp> 600){
  54.             velY[i] *= -1;
  55.         }
  56.         size = 10 + i % 10;
  57.         hs = size * 0.5;
  58.         x0 = xp - hs, y0 = yp - hs;
  59.         x1 = xp + hs, y1 = yp + hs;
  60.         ci = 0;
  61.         di = 0;
  62.         cmds = path[i].commands;
  63.         dat = path[i].data;
  64.         // GraphicsPathCommand.MOVE_TO
  65.         cmds[ci++] = 1;
  66.         dat[di++] = x0 , dat[di++] = y0;
  67.         // GraphicsPathCommand.LINE_TO
  68.         cmds[ci++] = 2;
  69.         dat[di++] = x1 , dat[di++] = y0;
  70.         // GraphicsPathCommand.LINE_TO
  71.         cmds[ci++] = 2;
  72.         dat[di++] = x1 , dat[di++] = y1;
  73.         // GraphicsPathCommand.LINE_TO
  74.         cmds[ci++] = 2;
  75.         dat[di++] = x0 , dat[di++] = y1;
  76.         // end inline function
  77.          
  78.         path[i].commands = cmds;
  79.         path[i].data = dat;
  80.         igraph[ig++] = fills[i % 3];
  81.         igraph[ig++] = path[i];
  82.     }
  83.     // everything is drawn with one function call
  84.     graphics.drawGraphicsData(igraph);
  85. }

I haven't spent much time with IGraphicsData. It's a very cool feature and I think its going to take me awhile to realize its full potential. Since I have to start somewhere I decided to write this snippet to show that it is rather fast. I also recalled reading some benchmark info for the new fp10 graphics stuff over at bytearray.org.... pretty nice info there...

This snippet is pretty optimized, there are a few areas (such as the recurring population of the cmds Vector) that could be optimized more but are left this way for SOME flexibility.

Also posted in Graphics, Vector, misc | Tagged , , | Leave a comment

QuickBox2D Groups

Actionscript:
  1. import com.actionsnippet.qbox.*;
  2.  
  3. [SWF (backgroundColor=0xAA0000, width=700, height=600, frameRate=60)]
  4.  
  5. var sim:QuickBox2D = new QuickBox2D(this);
  6.  
  7. sim.createStageWalls();
  8.  
  9. /**
  10. create a dancing pill
  11. */
  12. // all x and y coords are relative to the center of the group
  13. var partA:QuickObject = sim.addCircle({x:-1, y:0, radius:0.5, restitution:.9});
  14. var partB:QuickObject = sim.addCircle({x:1, y:0, radius:0.5, restitution:.9});
  15. var partC:QuickObject = sim.addBox({x:0, y:0, width:2, height:1});
  16. // all the parts are passed into the objects array
  17. // addGroup() groups the parts together into one rigid body
  18. var pill:QuickObject = sim.addGroup({objects:[partA, partB, partC], x:3, y:3, angle:0.3});
  19.  
  20. /**
  21. create another group
  22. */
  23. partA = sim.addCircle({x:0, y:0, radius:1});
  24. partB = sim.addBox({x:0, y:1, width:1, height:1, fillColor:0x666666});
  25. partC = sim.addBox({x:0, y:-1, width:1, height:1, fillColor:0x666666});
  26. sim.addGroup({objects:[partA, partB, partC], x:8, y:3, angle:0.3});
  27.  
  28. /**
  29. create two circles linked together by a stretchy joint
  30. */
  31. partA = sim.addCircle({x:15, y:3, fillColor:0x000000, anglularDamping:1});
  32. partB = sim.addCircle({x:17, y:3, fillColor:0xFFFFFF, anglularDamping:1});
  33. // if x1, y1, x2 and y2 properties are not set, the joint is automatically placed
  34. // at the b2Body's center
  35. sim.addJoint({a:partA.body, b:partB.body, frequencyHz:1});
  36.  
  37. sim.start();
  38. sim.mouseDrag();

You'll need QuickBox2D Alpha 106 to run this... This snippet demo's the addGroup() method, which allows for easy grouping of shapes. I updated the docs today to feature a simple explanation of how this works.


Have a look at the swf here...

Also posted in Box2D, QuickBox2D | Tagged , , | 3 Comments

QuickBox2D Polys

Actionscript:
  1. import com.actionsnippet.qbox.*;
  2.  
  3. [SWF(backgroundColor=0x000000, width=700, height=600)]
  4.  
  5. var sim:QuickBox2D = new QuickBox2D(this);
  6.  
  7. sim.setDefault({fillColor:0x003366, lineColor:0x2B80D5});
  8. sim.createStageWalls();
  9.  
  10. var i:int = 0;
  11. for (i= 0; i<10; i++){
  12.   sim.addCircle({x:5 + i, y:7, radius:0.3, linearDamping:1, angularDamping:1, fillColor:0x78B4C2, isBullet:true})
  13. }
  14.  
  15. for (i= 0; i<2; i++){
  16.     var poly:Array = [];
  17.     var r:Number = 3;
  18.     var step:Number = Math.PI / 6;
  19.     for (var t:Number = 0; t<=Math.PI; t+=step){
  20.         poly.push(r * Math.cos(t));
  21.         poly.push(r * Math.sin(t));
  22.     }
  23.     r = 2;
  24.     for (t = Math.PI; t>= -step; t-=step){
  25.         poly.push(r * Math.cos(t));
  26.         poly.push(r * Math.sin(t));
  27.     }
  28.     // using points instead of verts causes QuickBox2D to triangulate the polygon
  29.     // the wireframe boolean changes rendering style for polys
  30.     sim.addPoly({x:4 + i *7, y:16, points:poly, wireframe:Boolean(i), linearDamping:1.5, angularDamping:1});
  31. }
  32.  
  33. sim.start();
  34. sim.mouseDrag();

I just uploaded QuickBox2D Alpha 106 which includes a few bug fixes and support for compound shapes and easier polys. I used the algorithm from yesterdays post to significantly simplify the way QuickBox2D handles the description of polygons.

You'll need QuickBox2D Alpha 106 or greater, if you want to test this....


or just have a look at the demo here.

This triangulation is really better suited for 3D stuff - Box2D supports multiple convex polygons in one rigid body... this algorithm makes more shapes (triangles) than Box2D needs - I'll probably swap out the algorithm in the near future.

Tomorrow I'll be posting a demo about the way QuickBox2D simplifies compound shapes. I have yet to update the docs to include the new features of Alpha 106. That will happen along with tomorrows post.

Also posted in Box2D, QuickBox2D | Tagged , | 7 Comments