By Zevan | September 8, 2009
Actionscript:
-
[SWF(width=600, height=600, frameRate=30)]
-
var sw:Number = stage.stageWidth;
-
var sh:Number = stage.stageHeight;
-
-
var s:Shape = Shape(addChild(new Shape()));
-
-
var scale:Number = 1;
-
var scaleDest:Number = 1;
-
var down:Boolean = false;
-
var dx:Number = 0, dy:Number = 0, time:Number = 0;
-
-
buttonMode = true;
-
-
addInstructions();
-
vectorTexture();
-
-
stage.addEventListener(MouseEvent.MOUSE_DOWN, onDown);
-
stage.addEventListener(MouseEvent.MOUSE_UP, onUp);
-
addEventListener(Event.ENTER_FRAME, onLoop);
-
-
function addInstructions():void{
-
var instruct:Sprite = Sprite(addChild(new Sprite()));
-
with (instruct.graphics) beginFill(0x666666), drawRect(0,0,270, 30);
-
instruct.x = instruct.y = 20;
-
var txt:TextField = TextField(instruct.addChild(new TextField()));
-
txt.defaultTextFormat = new TextFormat("Verdana", 11);
-
txt.x = txt.y = 5;
-
txt.selectable = false;
-
with (txt) textColor = 0xFFFFFF, autoSize = "left", text = "Click and hold to zoom, move mouse to pan";
-
}
-
-
function vectorTexture():void{
-
var cols:Vector.<uint> = Vector.<uint>([0xFFFFFF, 0x000000]);
-
var rnd:Vector.<Number> = new Vector.<Number>(6, true);
-
-
for(var i:int = 0 ; i<50; i++){
-
with(s.graphics){
-
lineStyle(Math.random() * 50 + 2, cols[int(Math.random()*cols.length)]);
-
drawCircle(Math.random() * sw, Math.random() * sh, 10 + Math.random() * Math.random() * 400);
-
}
-
}
-
s.graphics.lineStyle(20, 0xCCCCCC);
-
s.graphics.drawRect(0, 0,sw, sh);
-
}
-
-
function onDown(evt:MouseEvent):void{ down = true; }
-
function onUp(evt:MouseEvent):void{ down = false; }
-
function onLoop(evt:Event):void {
-
if (down){
-
scaleDest *= 1.05;
-
time = 0;
-
}else{
-
time++;
-
// zoom out after 30 iterations
-
if (time == 30){
-
scaleDest = 1;
-
}
-
}
-
scale += (scaleDest - scale) / 4;
-
if (scale> 10) scale = scaleDest = 10;
-
-
dx += (mouseX - dx) / 4;
-
dy += (mouseY - dy) / 4;
-
if (dx <0) dx = 0;
-
if (dy <0) dy = 0;
-
if (dx> sw) dx = sw;
-
if (dy> sh) dy = sh;
-
-
// matrix zoom/pan
-
var m:Matrix = s.transform.matrix;
-
m.identity();
-
m.translate(-dx,-dy);
-
m.scale(scale, scale);
-
m.translate(dx,dy);
-
s.transform.matrix = m;
-
}
I haven't been by the computer much these last two weeks - been traveling. Going back to nyc tomorrow so I'll go back to posting once a day.
This snippet uses a transformation matrix to zoom in and pan a Sprite instance. For demo purposes I filled the sprite with a few circles - but you'd likely be using this with a vector image of a map, a floor plan or some other graphic that warrants zooming and panning.
Back around flash 7 (I think) before the Matrix class was introduced we used to have to use MovieClip nesting to achieve this effect.
Have a look at the swf...
![](http://actionsnippet.com/wp-content/zoompan.gif)
By Zevan | September 6, 2009
Actionscript:
-
[SWF(backgroundColor=0x222222, width=500, height=500)]
-
var hsw:Number = stage.stageWidth / 2;
-
var hsh:Number = stage.stageHeight / 2;
-
var pointNum:int = 800
-
var points3D:Vector.<Number> = new Vector.<Number>();
-
var points3Dout:Vector.<Number> = new Vector.<Number>();
-
var points2D:Vector.<Number> = new Vector.<Number>();
-
var uvts:Vector.<Number> = new Vector.<Number>();
-
var sorted:Array = [];
-
var pnt:Point = new Point();
-
var m:Matrix3D = new Matrix3D();
-
var v:Vector3D = new Vector3D();
-
for (var i:int = 0; i<pointNum; i++){
-
v.y = i * 0.7 - 300
-
var t =Math.random()*6.28;
-
v.x = 200 * Math.cos(i * 2 * Math.PI / 180);
-
v.z = 200 * Math.sin(i * 2 * Math.PI / 180);
-
v = m.transformVector(v);
-
points3D.push(v.x, v.y, v.z);
-
points2D.push(0,0);
-
uvts.push(0,0,0);
-
sorted.push(new Vector3D());
-
}
-
points3D.fixed = true;
-
points2D.fixed = true;
-
uvts.fixed = true;
-
var p:PerspectiveProjection = new PerspectiveProjection();
-
var proj:Matrix3D = p.toMatrix3D();
-
var dx:Number = 0, dy:Number = 0;
-
addEventListener(Event.ENTER_FRAME, onLoop);
-
function onLoop(evt:Event):void {
-
var i:int, j:int;
-
dx += (mouseX - dx) / 4;
-
dy += (mouseY - dy) / 4;
-
m.identity();
-
m.appendRotation(getTimer() / 4, Vector3D.Y_AXIS);
-
m.transformVectors(points3D, points3Dout);
-
-
m.identity();
-
m.appendRotation(dx, Vector3D.Z_AXIS);
-
m.appendRotation(dy, Vector3D.X_AXIS);
-
m.appendTranslation(0, 0, 1000);
-
m.append(proj);
-
Utils3D.projectVectors(m, points3Dout, points2D, uvts);
-
for (i = 0, j = 0; i<points2D.length; i+=2, j++){
-
sorted[j].x = points2D[i] + hsw;
-
sorted[j].y = points2D[i + 1] + hsh;
-
sorted[j].z = uvts[j * 3 + 2];
-
}
-
sorted.sortOn("z", Array.NUMERIC);
-
graphics.clear();
-
for(i = 0; i<sorted.length; i++){
-
var zpos:Number = sorted[i].z * 10000;
-
var c:int = zpos * 14;
-
graphics.beginFill(c <<16 | c <<8 | c);
-
graphics.drawCircle(sorted[i].x, sorted[i].y, zpos);
-
graphics.endFill();
-
}
-
}
A variation on some recent posts... this snippet draws a rotating spring made up of 800 particles...
Have a look at the swf...
![](http://actionsnippet.com/wp-content/dist_spring.jpg)
By Zevan | September 5, 2009
Actionscript:
-
import com.actionsnippet.qbox.*;
-
import Box2D.Common.Math.*;
-
import Box2D.Collision.Shapes.*;
-
-
[SWF(width = 600, height = 600, backgroundColor = 0x000000, frameRate=60)]
-
-
var sim:QuickBox2D = new QuickBox2D(this);
-
-
sim.setDefault({fillColor:0x990000, lineColor:0xFFCC00});
-
sim.createStageWalls();
-
-
var shapeTypes:Array = ["circle", "box", "poly"];
-
var pnts:Array = [-1, 0, -0.5, -1, 0.5, -1, 1, 0, 0,0.5, -1, 0];
-
var poly:Array=[];
-
for (var i:int = 0; i<20; i++){
-
var xp:Number = 3 + Math.random()*15;
-
var yp:Number = 3 + Math.random()*15;
-
var w:Number = 0.2 + Math.random() * 2;
-
var h:Number = 0.2 + Math.random() * 2;
-
var r:Number = 0.2 + Math.random();
-
var ang:Number = Math.random() * Math.PI * 2;
-
var index:Number = int(Math.random()*shapeTypes.length);
-
var s:Number = 0.3 + Math.random()*0.7;
-
for (var j:int = 0; j<pnts.length; j++){
-
poly[j] = pnts[j] * s;
-
}
-
sim.setDefault({fillColor:int(Math.random()*255) <<16, lineColor:0xFFCC00});
-
sim.create(shapeTypes[index], {x:xp, y:yp, width:w, height:h, angle:ang, radius:r, points:poly, wireframe:false})
-
}
-
-
sim.start();
-
sim.mouseDrag();
Was showing someone QuickBox2D today and created this demo after showing them a few other posts. After writing this, I realized I hadn't posted about the QuickBox2D.create() method. Which is what addBox(), addRect(), addJoint() etc.. use internally. It takes a string for the type of QuickObject you'd like to create along with the standard params Object. Note that depending on the QuickObject type certain params will simply be ignored - for example radius is ignored when the type is "box" etc...
Have a look at the swf...
![](http://actionsnippet.com/wp-content/create_method.jpg)
By Zevan | September 4, 2009
Actionscript:
-
import com.actionsnippet.qbox.*;
-
import Box2D.Common.Math.*;
-
import Box2D.Collision.Shapes.*;
-
-
[SWF(width = 800, height = 600, backgroundColor = 0x000000)]
-
-
var sim:QuickBox2D = new QuickBox2D(this);
-
-
sim.createStageWalls();
-
-
var boxNum:int = 8;
-
var boxes:Array = [];
-
var xp:Number, yp:Number, w:Number;
-
for (var i:int = 0; i<boxNum; i++){
-
xp = 3 + Math.random() * 10;
-
yp = 4 + i * 2;
-
w = 2 + Math.random() * 3;
-
boxes.push(sim.addBox({x: xp, y: yp, width: w, height: 0.5, density:0, groupIndex:-1, fillColor:0xFF6532}));
-
}
-
-
var char:QuickObject = sim.addBox({x:2, y:18, width:1, height:2, allowSleep:false, groupIndex:-1, fillColor:0x0099CC});
-
-
sim.start();
-
-
var charVel:b2Vec2;
-
var charVelAng:Number;
-
-
addEventListener(Event.ENTER_FRAME, onLoop);
-
function onLoop(evt:Event):void {
-
-
charVel = char.body.GetLinearVelocity();
-
charVelAng = char.body.GetAngularVelocity();
-
var filter:b2FilterData;
-
-
if (key[Keyboard.RIGHT]){
-
charVel.x += 1
-
char.body.SetLinearVelocity(charVel);
-
charVelAng += 1;
-
char.body.SetAngularVelocity(charVelAng);
-
}
-
if (key[Keyboard.LEFT]){
-
charVel.x -=1;
-
char.body.SetLinearVelocity(charVel);
-
charVelAng -= 1;
-
char.body.SetAngularVelocity(charVelAng);
-
}
-
if (key[Keyboard.UP] && sim.w.GetContactCount()> 0){
-
charVel.y = -10;
-
trace(charVel.y);
-
char.body.SetLinearVelocity(charVel);
-
charVelAng *= 0.8;
-
char.body.SetAngularVelocity(charVelAng);
-
}
-
for (var i:int = 0; i<boxes.length; i++){
-
var rect:Rectangle = char.userData.getRect(this);
-
if (rect.bottom / 30 <boxes[i].y){
-
filter = boxes[i].shape.GetFilterData();
-
filter.groupIndex = 1;
-
boxes[i].shape.SetFilterData(filter);
-
}else{
-
filter = boxes[i].shape.GetFilterData();
-
if (filter.groupIndex != -1){
-
filter.groupIndex = -1;
-
boxes[i].shape.SetFilterData(filter);
-
}
-
}
-
}
-
}
-
-
var key:Object = new Object();
-
stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyPressed);
-
stage.addEventListener(KeyboardEvent.KEY_UP, onKeyReleased);
-
function onKeyPressed(evt:KeyboardEvent):void{ key[evt.keyCode] = true; }
-
function onKeyReleased(evt:KeyboardEvent):void{ key[evt.keyCode] = false; }
NOTE: This requires the QuickBox2D mini-library
This snippet shows how to use groupIndex to create simple platforms for a character to jump on. A few people have asked me about this so I figured I'd post about it. It works by altering the groupIndex of each platform based on the characters position - if the character is below a platform, both the character and the platform have groupIndex -1 (meaning they will not collide). As soon as the character is above a platform, the platforms groupIndex is set to 1 (allowing the character to walk on the platform despite having just passed through it.
Have a look at the swf...
![](http://actionsnippet.com/wp-content/groupindex_platforms.jpg)
It's also worth noting that I'm using b2World.GetContactCount() to make sure it's ok to jump... if there were more going on in the demo you'd need to check a specific contact point(s), but since the only collision that could happen involves the character this works nicely...