Latest snippets

QuickBox2D Unicycler

import com.actionsnippet.qbox.*;
import Box2D.Common.Math.*;
import Box2D.Dynamics.Joints.*;
[SWF (backgroundColor=0x000000, width=700, height=600, frameRate=60)]
var sim:QuickBox2D = new QuickBox2D(this, {debug:false,gravityY:10, renderJoints:false});
sim.setDefault({fillColor:0xCC0000,lineAlpha:0});
sim.createStageWalls();

for (var i:int = 0; i<20; i++){
	sim.addCircle({x:1+i * 0.8, y:1, radius:0.1+Math.random()*0.1, restitution:0.3});
}

sim.setDefault({fillColor:0xEFEFEF, fillAlpha:0.5, lineColor:0xFFFFFF, groupIndex:-2});
var ancA:QuickObject = sim.addCircle({x:20, y:12, radius:0.5, density:0, skin:"none"});
var ancB:QuickObject = sim.addCircle({x:20, y:2, radius:0.5, density:0, skin:"none"});
var head:QuickObject = sim.addCircle({x:0, y:-0.6, radius:0.5});
var neck:QuickObject = sim.addBox({x:0, y:1, width:0.5, height:2});
var spindle:QuickObject = sim.addBox({x:0, y:3, width:0.1, height:2})
spindle.userData.visible = false;
var top:QuickObject = sim.addGroup({objects:[head, neck, spindle], x:10, y:5, fixedRotation:true});
var upperLegA:QuickObject = sim.addBox({x:10, y:7.5, width:0.25, height:1.5});
var lowerLegA:QuickObject = sim.addBox({x:10, y:9, width:0.25, height:1.5});
var wheel:QuickObject = sim.addCircle({x:10, y:9, radius:1});
var upperLegB:QuickObject = sim.addBox({x:10, y:7.5, width:0.25, height:1.5});
var lowerLegB:QuickObject = sim.addBox({x:10, y:9, width:0.25, height:1.5});
var upperArmA:QuickObject = sim.addBox({x:10.7, y:5.25, width:1.5, height:0.25});
var lowerArmA:QuickObject = sim.addBox({x:11.8, y:5.25, width:1.2, height:0.25});
var upperArmB:QuickObject = sim.addBox({x:9.5, y:5.25, width:1.5, height:0.25});
var lowerArmB:QuickObject = sim.addBox({x:8.4, y:5.25, width:1.2, height:0.25});
var anchor:b2Vec2 = new b2Vec2();
function connect(a:QuickObject, b:QuickObject, lower:Number, upper:Number, offX:Number=0, offY:Number = 0):QuickObject{
	 var min:Number = Math.min(a.y, b.y);
     var max:Number = Math.max(a.y, b.y);
     anchor.y = min + (max - min) * 0.5 + offY;
     min = Math.min(a.x, b.x);
     max = Math.max(a.x, b.x);
     anchor.x = min + (max - min) * 0.5 + offX;
	 return sim.addJoint({type:"revolute", a:a.body, b:b.body, x1:anchor.x, y1:anchor.y, lowerAngle:lower, upperAngle:upper});
}
sim.addJoint({type:"revolute", a:wheel.body, b:top.body, x1:wheel.x, y1:wheel.y});
sim.addJoint({type:"revolute", a:lowerLegA.body, b:wheel.body, x1:lowerLegA.x, y1:lowerLegA.y + 0.7});
sim.setDefault({enableLimit:true});
connect(top, upperArmA, 0, 3, -.3, .1);
connect(upperArmA, lowerArmA, -2.5, -1, 0, 0);
connect(top, upperArmB, -3, 0, .3, .1);
connect(upperArmB, lowerArmB, -2.5, -1, 0, 0);
sim.addJoint({type:"distance", a:lowerArmA.body, b:ancA.body, frequencyHz:0.3});
sim.addJoint({type:"distance", a:lowerArmB.body, b:ancB.body, frequencyHz:0.3});
sim.setDefault({enableLimit:true});
connect(top, upperLegA, -6.28, 6, 0, 0.8);
connect(upperLegA, lowerLegA, .1, 6);
wheel.angle = Math.PI;
connect(top, upperLegB, -6.28, 6, 0, 0.8);
connect(upperLegB, lowerLegB, .1, 6);
sim.setDefault({enableLimit:false, type:"revolute"});
sim.addJoint({a:lowerLegB.body, b:wheel.body, x1:lowerLegB.x, y1:lowerLegB.y + 0.7});

sim.start();
sim.mouseDrag();

var sd:Number = 5, s:Number = 0, t:Number = 0;
addEventListener(Event.ENTER_FRAME, function():void{
	top.angle = Math.cos(t += 0.05) * 0.2;
    if (top.x > 19) sd = -5
	if (top.x < 5) sd = 5;
	s += (sd - s) / 8;
	wheel.body.SetAngularVelocity(s);
});

This chunk of code uses QuickBox2D to create a simple looking character riding a unicycle…

Have a look at the swf…

QuickBox2D Floating Walker

import com.actionsnippet.qbox.*;
import Box2D.Common.Math.*;
import Box2D.Dynamics.Joints.*;

[SWF (backgroundColor=0x000000, width=700, height=600, frameRate=60)]

var sim:QuickBox2D = new QuickBox2D(this, {gravityY:.2});

sim.setDefault({fillColor:0xEFEFEF, fillAlpha:0.5, lineColor:0xFFFFFF});

sim.createStageWalls();

for (var i:int = 0; i<20; i++){
	sim.addCircle({x:1+i, y:1, radius:0.2, restitution:1});
}

var head:QuickObject = sim.addCircle({x:0, y:0, radius:0.5});
var neck:QuickObject = sim.addBox({x:0, y:1, width:0.5, height:2});
var top:QuickObject = sim.addGroup({objects:[head, neck], x:10, y:5, fixedRotation:true});

var upperLegA:QuickObject = sim.addBox({x:10, y:7.5, width:0.25, height:1.5,groupIndex:-2});
var lowerLegA:QuickObject = sim.addBox({x:10, y:9, width:0.25, height:1.5,groupIndex:-2});

var upperLegB:QuickObject = sim.addBox({x:10, y:7.5, width:0.25, height:1.5,groupIndex:-2});
var lowerLegB:QuickObject = sim.addBox({x:10, y:9, width:0.25, height:1.5,groupIndex:-2});

var anchor:b2Vec2 = new b2Vec2();
function connect(a:QuickObject, b:QuickObject, lower:Number, upper:Number, offX:Number=0, offY:Number = 0):QuickObject{
	 var min:Number = Math.min(a.y, b.y);
     var max:Number = Math.max(a.y, b.y);
     anchor.y = min + (max - min) * 0.5 + offY;
     min = Math.min(a.x, b.x);
     max = Math.max(a.x, b.x);
     anchor.x = min + (max - min) * 0.5 + offX;
	 return sim.addJoint({a:a.body, b:b.body, x1:anchor.x, y1:anchor.y, lowerAngle:lower, upperAngle:upper});
}

sim.setDefault({type:"revolute", collideConnected:false, enableLimit:true, enableMotor:true, maxMotorTorque:250, lineColor:0xFFFFFF});

var upperLegAJoint:QuickObject = connect(top, upperLegA, -1, 1, 0, 0.8);
var upperLegBJoint:QuickObject = connect(top, upperLegB, -1, 1, 0, 0.8);

var lowerLegAJoint:QuickObject = connect(upperLegA, lowerLegA, -1, 1);
var lowerLegBJoint:QuickObject = connect(upperLegB, lowerLegB, -1, 1);

sim.start();
sim.mouseDrag();
 

var j:b2RevoluteJoint;
var t:Number = -Math.PI * 0.5;
addEventListener(Event.ENTER_FRAME, onLoop);
function onLoop(evt:Event):void {
	
	var s1:Number = 1*Math.sin(t);
	var s2:Number = 1*Math.sin(t+Math.PI);
	t+= 0.05;
	
	top.body.SetAngularVelocity(s1 * 0.25);
	
	j =  upperLegAJoint.joint as b2RevoluteJoint;
    j.SetMotorSpeed(s1);
	
	j =  upperLegBJoint.joint as b2RevoluteJoint;
    j.SetMotorSpeed(s2);
	 
	j = lowerLegAJoint.joint as b2RevoluteJoint;
	j.SetMotorSpeed(-s2);
	
	j = lowerLegBJoint.joint as b2RevoluteJoint;
	j.SetMotorSpeed(-s1);
}

Experimenting with primitive robot designs… this was just an improvised design – it looks like it may make sense to break out a pencil and some paper – or my wacom… to get something interesting…


Have a look at the swf…


QuickBox2D Prismatic Joint

import com.actionsnippet.qbox.*;
import Box2D.Common.Math.*;

[SWF (backgroundColor=0x000000, width=700, height=600, frameRate=60)]

var sim:QuickBox2D = new QuickBox2D(this);

sim.setDefault({fillColor:0xCCCCCC, lineColor:0x3355AA});

sim.createStageWalls();

var box:QuickObject = sim.addBox({x:10, y:10, density:0});
var circle:QuickObject = sim.addCircle({x:10, y:13});

sim.addJoint({type:"prismatic", a:box.body, b:circle.body, axis:new b2Vec2(1, 0), upperTranslation:3, lowerTranslation:-3, enableLimit:true, motorSpeed:10, maxMotorForce:10, enableMotor:true});

sim.start();
sim.mouseDrag();

Simple prismatic joint demo. Prismatic joints are odd, it took me awhile to realize how to use them and what they can be used for… Plan on using them in the creation of some Box2D machines in the near futrure…

Check out the swf

QuickBox2D Gear Joint

import com.actionsnippet.qbox.*;
import Box2D.Common.Math.*;

[SWF (backgroundColor=0x000000, width=700, height=600)]

var sim:QuickBox2D = new QuickBox2D(this,{gravityY:10});

sim.setDefault({fillColor:0x113366, fillAlpha:0.8, lineColor:0x3355AA});
sim.createStageWalls();

var boxA:QuickObject = sim.addBox({x:10, y:8, width:4, height:0.5, density:10});
var boxB:QuickObject = sim.addBox({x:5, y:5, density:10});
boxB.body.SetLinearVelocity(new b2Vec2(5, 0));
 
var rev1:QuickObject = sim.addJoint({type:"revolute", a:sim.w.GetGroundBody(), b:boxA.body, anchor:boxA.body.GetWorldCenter()})
			
var rev2:QuickObject = sim.addJoint({type:"prismatic", a:sim.w.GetGroundBody(), axis:new b2Vec2(1, 0), b:boxB.body, anchor:boxB.body.GetWorldCenter()})
																					 
sim.addJoint({type:"gear", a:boxA.body, b:boxB.body, joint1:rev1.joint, joint2:rev2.joint});
			 
sim.start();
sim.mouseDrag();

Simple gear joint demo – meant to serve as a reference for QuickBox2D…


Have a look at the swf…

QuickBox2D Connect to GroundBody

import com.actionsnippet.qbox.*;

[SWF (backgroundColor=0x000000, width=700, height=600)]

var sim:QuickBox2D = new QuickBox2D(this);

sim.setDefault({fillColor:0x113366, fillAlpha:0.8, lineColor:0x3355AA});

sim.createStageWalls();

var boxA:QuickObject = sim.addBox({x:10, y:8, width:4, height:0.5, angularDamping:1});
var boxB:QuickObject = sim.addBox({x:7, y:8, width:3, height:0.25, angle:-.5, angularDamping:1});
var boxC:QuickObject = sim.addBox({x:12, y:2, width:2, height:1});

var rev:QuickObject = sim.addJoint({type:"revolute", a:boxA.body, b:sim.w.GetGroundBody()});
// add a red dot to boxA
with (boxA.userData.graphics) lineStyle(), beginFill(0xFF0000), drawCircle(0,0,2);

var rev2:QuickObject = sim.addJoint({type:"revolute", a:boxB.body, b:sim.w.GetGroundBody()});
with (boxB.userData.graphics) lineStyle(), beginFill(0xFF0000), drawCircle(0,0,2);

sim.start();
sim.mouseDrag();

In order to use gear joints (covered in tomorrows post) you’ll need to know how to connect to the ground body…

Check out the swf…

QuickBox2D Revolute Walker

import com.actionsnippet.qbox.*;
import Box2D.Dynamics.Joints.*;

[SWF (backgroundColor=0x222222, width=700, height=600)]

var sim:QuickBox2D = new QuickBox2D(this);
 
sim.setDefault({fillColor:0x000000, lineColor:0xCCCCCC});
sim.createStageWalls();

var legA:QuickObject = sim.addBox({x:5, y:11, width:2, height:0.2,groupIndex:-2});
var three:QuickObject = sim.addBox({x:6.8 + 1.8, y:11, width:2, height:0.2,groupIndex:-2});
var legB:QuickObject = sim.addBox({x:6.8, y:11, width:2, height:0.5,groupIndex:-2});
sim.setDefault({type:"revolute"});

var anchorX:Number = legA.x + (legB.x - legA.x) / 2;
var anchorY:Number = legA.y;
var revJointA:QuickObject = sim.addJoint({a:legA.body, b:legB.body, x1:anchorX, y1:anchorY,enableMotor:true, maxMotorTorque:80});

anchorX = legB.x + (three.x - legB.x) / 2;

var revJointB:QuickObject = sim.addJoint({a:legB.body, b:three.body, x1:anchorX, y1:anchorY, enableMotor:true, maxMotorTorque:80});

setWalkDir(6);
addEventListener(Event.ENTER_FRAME, onLoop);
function onLoop(evt:Event):void {
  if (legB.x < 4){
	setWalkDir(6);  
  }else if (legB.x > 19){
	setWalkDir(-6);  
  }
}
function setWalkDir(dir:Number):void{
	var j:b2RevoluteJoint;
	j = revJointA.joint as b2RevoluteJoint
	j.SetMotorSpeed(dir);
	j = revJointB.joint as b2RevoluteJoint
	j.SetMotorSpeed(dir * -1);
}

sim.start();
sim.mouseDrag();

This demo is a bit more complex than the last two – mostly because it makes use of motors…


Have a look at the swf…

QuickBox2D Pulley Joint

import com.actionsnippet.qbox.*;
import Box2D.Common.Math.*;

[SWF (backgroundColor=0x000000, width=700, height=600)]

var sim:QuickBox2D = new QuickBox2D(this);

sim.setDefault({fillColor:0x113366, fillAlpha:0.8, lineColor:0x3355AA});

sim.createStageWalls();

var boxA:QuickObject = sim.addBox({x:10, y:8, fixedRotation:true});
var boxB:QuickObject = sim.addBox({x:14, y:8, width:2,  fixedRotation:true});

sim.addJoint({type:"pulley", a:boxA.body, b:boxB.body, groundAnchor1:new b2Vec2(boxA.x, 2), groundAnchor2:new b2Vec2(boxB.x, 2)});

sim.start();
sim.mouseDrag();

QuickBox2D pulley joint demo. This post is really meant to serve as part of the docs so it may seem a bit boring in its simplicity…

Have a look at the swf…

ActionSnippet Auto-Post

I’m going out of town for a week or so – the site will be on auto-post (QuickBox2D joint demos in the pipeline)… so apologies if your comments aren’t approved in a timely fashion.

QuickBox2D Revolute Ragdoll

import com.actionsnippet.qbox.*;
import Box2D.Common.Math.*;

[SWF (backgroundColor=0x000000, width=700, height=600, frameRate=60)]

var sim:QuickBox2D = new QuickBox2D(this,{debug:false, frim:true, gravityY:1});

sim.setDefault({fillColor:0x113366, fillAlpha:0.8, lineColor:0x3355AA});

sim.createStageWalls();

var circle:QuickObject = sim.addCircle({x:10, y:10, radius:3});
var head:QuickObject = sim.addCircle({x:5, y:5, radius:0.5});
var torsoA:QuickObject = sim.addBox({x:5, y:6, width:1.5, height:0.8})
var torsoB:QuickObject = sim.addBox({x:5, y:6.5, width:1.25, height:0.8})
var torsoC:QuickObject = sim.addBox({x:5, y:7, width:1.0, height:0.8})
var pelvis:QuickObject = sim.addBox({x:5, y:7.5, width:1.0, height:0.8})
var leftLegA:QuickObject = sim.addBox({x:4.75, y:8.5, width:0.4, height:1.75});
var leftLegB:QuickObject = sim.addBox({x:4.75, y:9.75, width:0.4, height:1.5});
var rightLegA:QuickObject = sim.addBox({x:5.29, y:8.5, width:0.4, height:1.75});
var rightLegB:QuickObject = sim.addBox({x:5.29, y:9.75, width:0.4, height:1.5});
var leftArmA:QuickObject = sim.addBox({x:3.6, y:5.8, width:1.3, height:0.35});
var leftArmB:QuickObject = sim.addBox({x:2.5, y:5.8, width:1.25, height:0.35});
var rightArmA:QuickObject = sim.addBox({x:6.4, y:5.8, width:1.3, height:0.35});
var rightArmB:QuickObject = sim.addBox({x:7.5, y:5.8, width:1.25, height:0.35});

torsoA.body.SetLinearVelocity(new b2Vec2(0, 50));

var anchor:b2Vec2 = new b2Vec2();
function connect(a:QuickObject, b:QuickObject, lower:Number, upper:Number, offX:Number=0, offY:Number = 0):QuickObject{
	 var min:Number = Math.min(a.y, b.y);
     var max:Number = Math.max(a.y, b.y);
     anchor.y = min + (max - min) * 0.5 + offY;
     min = Math.min(a.x, b.x);
     max = Math.max(a.x, b.x);
     anchor.x = min + (max - min) * 0.5 + offX;
	return sim.addJoint({a:a.body, b:b.body, x1:anchor.x, y1:anchor.y, lowerAngle:lower, upperAngle:upper});
}

sim.setDefault({type:"revolute", collideConnected:false, enableLimit:true, lineColor:0xFFFFFF});

connect(head, torsoA, -.2, .2);
connect(torsoA, torsoB,-.2, .2);
connect(torsoC, torsoB,-.2, .2);
connect(torsoC, pelvis,-.2, .2);

connect(pelvis, leftLegA, -1, 1, 0, -0.5);
connect(leftLegA, leftLegB, -1, 1);

connect(pelvis, rightLegA, -1, 1, 0, -0.5);
connect(rightLegA, rightLegB, -1, 1);

connect(torsoA, leftArmA, -2, 1);
connect(leftArmA, leftArmB, -2, 1);

connect(torsoA, rightArmA, -1, 2)
connect(rightArmA, rightArmB, -1, 2)

sim.start();
sim.mouseDrag();
 

QuickBox2D alpha 108 is finally finished and different types of joints are now possible. I’ll be auto-posting joint demos over the next few days for each type of Box2D joint. Box2D joints are pretty confusing, I struggled a bit to decide on a good way to handle them in QuickBox2D, any suggestions are welcome.


Have a look at the swf:

Interesting Texture #3

var canvas:BitmapData = new BitmapData(1500,1000,false, 0x000000);
addChild(new Bitmap(canvas));
scaleX = scaleY = .5;

var w:int = canvas.width;
var w10:int = w * 80;
var convert:Number = Math.PI/180;
var size:int = canvas.width * canvas.height;
for (var i:int = 0; i<size; i++){
	var xp:int = i % w;
	var yp:int = int(i / w);
	var xp2:int = xp * 2;
	var c1:int = (255/8) * (Math.cos(xp2 * convert) - Math.sin(yp*(xp2 + 500)/w10));
	if (c1 < 0) c1 = 256 - c1;
	c1 = (c1 << 2 | c1) ;
	canvas.setPixel(xp, yp, c1 <<15 | c1 <<9 | c1 );
}
var m:Matrix = new Matrix();
m.scale(1,-1);
m.translate(0,canvas.height);
var clone:BitmapData = canvas.clone();
canvas.draw(clone, m, null, BlendMode.SUBTRACT);
clone.draw(canvas);
clone.applyFilter(clone, clone.rect, new Point(0,0), new BlurFilter(10,10,1));
canvas.draw(clone, null, null, BlendMode.ADD);
var gray:ColorMatrixFilter = new ColorMatrixFilter([1, 0.55, 0.55, 0,0,0.55, 0.9, 0.55, 0,0,0.55, 0.55, 0.550,0, 0,0,0,1,0]);
canvas.applyFilter(canvas, canvas.rect, new Point(0,0), gray);

Soon I’ll work on a real-time variation. For now, here is one more still…