« Previous | Next »
Post-Flashbelt Experimentation
Published on Jul. 01, 2009
by Kyle
Flashbelt has come and gone for 2009, and again it was an experience that I feel lucky to have been a part of. It was great to spend 3 days with like-minded designers and developers; and to listen to presenters show where the past year has led them. Presenters demonstrated completed projects, experiments and the new tools they are using. Rather than repeating tidbits I picked up here and there, I want to show some things I have thrown together since Flashbelt. These are just some quick demos, for me they mainly serve as a form of notes to get familiar with some of the new features and also were thrown together as a quick ‘capabilities demo’ for the team.
Below are three demos and source code. These demos use some new features, I wrote these for use with the free Flex 4 SDK, which you can also use with Flash Builder 4 Beta, these classes are all very simple to convert for use with Flash CS4 instead.
Slide 1: Click on the photo and it shatters into pieces. This is a custom effect I built after some inspiration from Koen De Weggheleire’ s presentation “Play with Vectors.” For this effect I am drawing a 5×5 grid of rectangles and filling them with their respective pixel’s from the original source image. When the image is clicked the pieces have physics properties applied to propel them.
package com.hapticdata.fb2009
{
import com.hapticdata.phsyics.AngularVelocityVector;
import com.theflashblog.fp10.SimpleZSorter;
import flash.geom.Vector3D;
import flash.geom.Matrix3D;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Rectangle;
import flash.geom.Point;
import flash.geom.Matrix;
import flash.display.BitmapData;
import flash.display.Bitmap;
import flash.display.Stage;
import flash.display.Sprite;
/**
* Exploading picture,
* image is embedded split into a grid, the respective pixels are copied to the Sprite,
* and AngularVelocityVector is used for the animation
* @author kphillips
*/
public class ExplodingPicture extends Sprite
{
[Embed (source="../../../../eyes4.jpg")]
private var imgClass:Class;
public var bd:BitmapData;
public var columns:int = 10;
public var rows:int = 10;
public var gridWidth:int;
public var gridHeight:int;
public var container:Sprite;
public var items:Vector.;
public var avVectors:Vector.;
public var hasExploded:Boolean = false;
public var axis:Vector.;
public var _stage:Stage;
override public function get stage():Stage
{
return _stage;
}
public function ExplodingPicture(stage:Stage=null)
{
if(!stage)
{
stage = this.stage;
_stage = this.stage;
}
else
{
this._stage = stage;
}
axis = new Vector.();
axis[0] = Vector3D.X_AXIS;
axis[1] = Vector3D.Y_AXIS;
axis[2] = Vector3D.Z_AXIS;
avVectors = new Vector.();
addEventListener(Event.ENTER_FRAME,handleEnterFrame);
container = new Sprite();
container.x = stage.stageWidth*0.5;
container.y = stage.stageHeight*0.5;
addChild(container);
bd = (new imgClass() as Bitmap).bitmapData;
gridWidth = bd.width / columns;
gridHeight = bd.height / rows;
items = new Vector.();
for(var c:int=0;c < columns;c++)
{
for(var r:int=0;r < rows;r++)
{
var s:Sprite = new Sprite();
var m:Matrix = new Matrix();
var rectBD:BitmapData = new BitmapData(gridWidth,gridHeight);
rectBD.copyPixels(bd, new Rectangle(c*gridWidth,r*gridHeight,gridWidth,gridHeight), new Point(0,0));
s.graphics.beginBitmapFill(rectBD,m);
s.graphics.drawRect(0,0,gridWidth,gridHeight);
s.graphics.endFill();
s.addEventListener(MouseEvent.CLICK,handleMouseClick)
items.push(s);
container.addChild(s);
var sx:Number = (c*gridWidth) - (bd.width*0.5);
var sy:Number = (r*gridHeight) - (bd.height*0.5);
s.transform.matrix3D = new Matrix3D();
s.transform.matrix3D.appendTranslation(sx, sy, 0);
var av:AngularVelocityVector = new AngularVelocityVector();
av.vector = {x: s.x, y: s.y};
av.forces = {vx: 0, vy:Math.random()*-25,angle:Math.random()*360, wind: -1, gravity: 4, drag: 0.999};
avVectors.push(av);
}
}
}
private function handleEnterFrame(event:Event):void
{
if(hasExploded)
{
for(var i:uint=0;i < items.length;i++)
{
avVectors[i].step();
items[i].x = avVectors[i].x;
items[i].y = avVectors[i].y;
var rot:int = 4;
if(i&1)rot *= -1;
items[i].transform.matrix3D.appendRotation(rot, axis[i%axis.length]);
}
}
SimpleZSorter.sortClips(container);
}
private function handleMouseClick(event:MouseEvent):void
{
hasExploded = true;
(event.target as Sprite).transform.matrix3D.appendRotation(45,Vector3D.Z_AXIS);
}
}
}
The next 2 examples also were inspired by Koen's presentation. With Flash CS4 there is now a native 3d environment, using the Matrix3D class it simple to work in three dimensions without the use of a third-party library like Papervision3D or Away3D. I did however need to use SimpleZSorter, a great class I found on Lee Brimelow's The Flash Blog.
Slide 2: Accelerated Drawing using Vectors and 3D Transformations. This slide will draw 1000 squares in a 3d space, something that previously would've been very difficult for flash. Now using Vector (so much better than un-typed arrays), and some new drawing classes such as GraphicsPathCommand the drawing is very manageable on your systems resources.
package com.hapticdata.fb2009
{
import flash.display.BitmapData;
import flash.display.GraphicsBitmapFill;
import flash.display.GraphicsPath;
import flash.display.GraphicsPathCommand;
import flash.display.GraphicsPathWinding;
import flash.display.GraphicsSolidFill;
import flash.display.GraphicsStroke;
import flash.display.IGraphicsData;
import flash.display.LineScaleMode;
import flash.display.Sprite;
import flash.display.Stage;
import flash.events.Event;
import flash.geom.Matrix3D;
import flash.geom.Point;
import flash.geom.Vector3D;
/**
* Drawing3D, using the Vector class and GraphicsPathCommands to accelerate drawing
* @author kphillips
*/
public class Drawing3D extends Sprite
{
public var i:int = 0;
public var numShapes:int = 1000;
public var commands:Vector.;
public var coords:Vector.;
public var container:Sprite;
public var shape:Sprite;
public var _stage:Stage;
override public function get stage():Stage {
return _stage;
}
public function Drawing3D(stage:Stage = null)
{
if(!stage)
{
stage = this.stage;
_stage = this.stage;
}
else
{
this._stage = stage;
}
container = new Sprite();
container.x = stage.stageWidth * 0.5;
container.y = stage.stageHeight * 0.5;
addChild(container);
commands = new Vector.();
commands[0] = GraphicsPathCommand.MOVE_TO;
commands[1] = GraphicsPathCommand.LINE_TO;
commands[2] = GraphicsPathCommand.LINE_TO;
commands[3] = GraphicsPathCommand.LINE_TO;
commands[4] = GraphicsPathCommand.LINE_TO;
//
commands[5] = GraphicsPathCommand.MOVE_TO;
commands[6] = GraphicsPathCommand.LINE_TO;
commands[7] = GraphicsPathCommand.LINE_TO;
commands[8] = GraphicsPathCommand.LINE_TO;
commands[9] = GraphicsPathCommand.LINE_TO;
addEventListener(Event.ENTER_FRAME, handleEnterFrame);
}
private function handleEnterFrame(event:Event):void
{
if(i++ < numShapes)
{
//create shape
var shape:Sprite = new Sprite();
shape.transform.matrix3D = new Matrix3D();
shape.transform.matrix3D.appendTranslation(-stage.stageWidth * 0.5, -stage.stageHeight * 0.5, Math.random() * 50 - 25);
container.addChild(shape);
var pt:Point = new Point(Math.random() * stage.stageWidth, Math.random() * stage.stageHeight);
var width:int = Math.random() * 25 + 1
var height:int = Math.random() * 25 + 1;
coords = new Vector.();
//left x
coords[0] = pt.x - (width * 0.5);
//top y
coords[1] = pt.y - (height * 0.5);
//right x
coords[2] = pt.x + (width * 0.5);
coords[3] = coords[1];
coords[4] = coords[2];
//bottom-y
coords[5] = pt.y + (height * 0.5);
coords[6] = coords[0];
coords[7] = coords[5];
coords[8] = coords[0];
coords[9] = coords[1];
var drawingData:GraphicsPath = new GraphicsPath(commands, coords, GraphicsPathWinding.NON_ZERO);
var fillBitmap:GraphicsBitmapFill = new GraphicsBitmapFill(new BitmapData(width, height, true, Math.random() * 0xFFFFFF00));
var stroke:GraphicsStroke = new GraphicsStroke(1, true, LineScaleMode.NONE, "none", "round", 3, new GraphicsSolidFill(0xffffff, 1));
var graphicsData:Vector. = new Vector.();
//fill
graphicsData[0] = fillBitmap;
//stroke
graphicsData[1] = stroke;
//data
graphicsData[1] = drawingData; //i don't want a stroke
shape.transform.matrix3D.appendRotation(Math.random() * 360, Vector3D.Y_AXIS);
shape.transform.matrix3D.appendRotation(Math.random() * 360, Vector3D.X_AXIS);
shape.graphics.drawGraphicsData(graphicsData);
}
container.rotationY++;
}
}
}
Slide 3: Controlling an object's rotation in 3D There isn't much new here, I'm just trying to show simple control of the environment. You can see how we can implement 3D planes and rotation very simply, this could open up some doors for possible navigations in future projects without a large time investment.
package com.hapticdata.fb2009
{
import flash.text.TextFormat;
import flash.text.TextFieldAutoSize;
import flash.text.TextField;
import flash.display.Stage;
import flash.events.MouseEvent;
import flash.geom.Vector3D;
import com.theflashblog.fp10.SimpleZSorter;
import flash.geom.Matrix3D;
import flash.geom.Point;
import flash.events.Event;
import flash.display.Bitmap;
import flash.display.Sprite;
/**
* Rotating3D, an embedded object, rotating in a 3d environment
* @author kphillips
*/
public class Rotating3D extends Sprite
{
[Embed (source="../../../../tree.png")]
private var imgClass:Class;
public var original:Bitmap;
//circle properties
public var radius:int = 150;
public var center:Point;
public var numItems:int = 8;
public var rotY:Number=0;
public var rotZ:Number=0;
public var container:Sprite;
public var items:Vector.;
public var _stage:Stage;
override public function get stage():Stage
{
return _stage;
}
public function Rotating3D(stage:Stage=null)
{
if(!stage)
{
stage = this.stage;
_stage = this.stage;
}
else
{
this._stage = stage;
}
stage.addEventListener(MouseEvent.MOUSE_MOVE,handleMouseMove);
center = new Point(stage.stageWidth*0.5,stage.stageHeight*0.5);
var tF:TextField = new TextField();
tF.defaultTextFormat = new TextFormat("arial");
tF.autoSize = TextFieldAutoSize.LEFT;
tF.text = "move mouse to rotate";
tF.x = 10;
tF.y = 10;
addChild(tF);
container = new Sprite();
container.x = center.x;
container.y = center.y;
addChild(container);
container.addEventListener(MouseEvent.CLICK,handleClick);
original = new imgClass() as Bitmap;
items = new Vector.();
var radialStep:Number = 360 / numItems;
for(var i:uint=0;i < numItems;i++)
{
items[i] = new Bitmap(original.bitmapData.clone());
items[i].transform.matrix3D = new Matrix3D();
var rotZ:int =radialStep * i;
items[i].transform.matrix3D.appendTranslation(-items[i].width*0.5, -items[i].height*0.5, 0);
items[i].transform.matrix3D.appendRotation(rotZ,Vector3D.Y_AXIS);
container.addChild(items[i]);
}
//SimpleZSorter.sortClips(container);
//container.rotationX += 60;
//container.rotationX += 15;
addEventListener(Event.ENTER_FRAME,handleEnterFrame);
}
private function handleMouseMove(event:MouseEvent):void
{
var distX:Number = mouseX - center.x;
var distY:Number = mouseY - center.y;
rotY = distX / (stage.stageWidth*0.5);
rotZ = distY / (stage.stageHeight*0.5);
}
private function handleClick(event:MouseEvent):void
{
//move back in z-space every click
//if(event.target is Bitmap)
//{
event.target.transform.matrix3D.appendTranslation(0,0,10);
//}
}
private function handleEnterFrame(event:Event):void
{
container.rotationY+=(rotY*-2);
container.rotationZ+=(rotZ*-2);
SimpleZSorter.sortClips(container);
}
}
}
hd-fbexamples.zip (source files)
Leave a response
Trackback URL: Post-Flashbelt Experimentation.






Leave a Reply