Away3D + Flint 3D Particles Demo
Away3D v4.0.9 + Flint 3D Particles Demo
@author flashisobar http://flashisobar.blogspot.com/
demo:
Skybox
Point/Directional light
Shadow
LightsHelper - applys lights to all materials
Loader3D - load 3D Object(awd file format)
Flint3D - fog/cloud effect
3D model by SolCommand http://www.solcommand.com/
Create cloud reference http://wonderfl.net/c/h9dR
Skybox map reference https://github.com/away3d/away3d-examples-fp11/
/**
* Copyright flashisobar ( http://wonderfl.net/user/flashisobar )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/lH6h
*/
package
{
import away3d.cameras.Camera3D;
import away3d.cameras.lenses.PerspectiveLens;
import away3d.containers.ObjectContainer3D;
import away3d.containers.Scene3D;
import away3d.containers.View3D;
import away3d.controllers.HoverController;
import away3d.debug.AwayStats;
import away3d.debug.Debug;
import away3d.debug.Trident;
import away3d.entities.Mesh;
import away3d.events.LoaderEvent;
import away3d.lights.DirectionalLight;
import away3d.lights.LightBase;
import away3d.lights.PointLight;
import away3d.loaders.Loader3D;
import away3d.loaders.parsers.Parsers;
import away3d.materials.ColorMaterial;
import away3d.materials.lightpickers.StaticLightPicker;
import away3d.materials.methods.DitheredShadowMapMethod;
import away3d.materials.methods.FilteredShadowMapMethod;
import away3d.materials.methods.FogMethod;
import away3d.primitives.PlaneGeometry;
import away3d.primitives.SkyBox;
import away3d.primitives.TorusGeometry;
import away3d.textures.BitmapCubeTexture;
import away3d.tools.helpers.LightsHelper;
import away3d.utils.Cast;
import flash.display.BitmapData;
import flash.display.Bitmap;
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.filters.DropShadowFilter;
import flash.geom.Vector3D;
import flash.net.URLLoaderDataFormat;
import flash.net.URLRequest;
import flash.system.LoaderContext;
import flash.system.Security;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.ui.Keyboard;
import flash.utils.getTimer;
import jp.progression.commands.lists.LoaderList;
import jp.progression.commands.net.LoadBitmapData;
import jp.progression.data.getResourceById;
import org.flintparticles.integration.away3d.v4.A3D4Renderer;
/**
* away3d v4.0.X test2
*
* @author flashisobar http://flashisobar.blogspot.com/
*
* Press SPACE to show fog effect
*
* demo:
* Point light
* Directional light
* Skybox
* Shadow
* LightsHelper - applys lights to all materials
* Loader3D - load 3D Object(awd file format)
* Flint3D - fog/cloud effect
*
* 3D model by SolCommand http://www.solcommand.com/
* Create cloud reference http://wonderfl.net/c/h9dR
* Skybox map reference https://github.com/away3d/away3d-examples-fp11/
*
*/
[SWF(width="465",height="465",frameRate="60",backgroundColor="0x0")]
public class Main extends Sprite
{
private const BASE_URL:String = "http://labs-baybow.rhcloud.com/";
private var scene:Scene3D;
private var camera:Camera3D;
private var view:View3D;
private var stats:AwayStats;
private var plight:PointLight;
private var dlight:DirectionalLight;
private var lightPicker:StaticLightPicker;
private var torustexture:ColorMaterial;
private var torus:Mesh;
private var cameraController:HoverController;
private var move:Boolean;
private var lastPanAngle:Number;
private var lastTiltAngle:Number;
private var lastMouseX:Number;
private var lastMouseY:Number;
// Environment map for skybox
private var arrSkyboxMap:Array = [
"snow_positive_x.jpg",
"snow_positive_y.jpg",
"snow_positive_z.jpg",
"snow_negative_x.jpg",
"snow_negative_y.jpg",
"snow_negative_z.jpg"
]
private var skybox:SkyBox;
private var sunLight:DirectionalLight;
private var _loader:Loader3D;
private var _objContainer:ObjectContainer3D;
private var emitter:EmitterSmoke;
private var particleContainer:ObjectContainer3D;
private var particleRenderer:A3D4Renderer;
private var isFog:Boolean = true;
private var _text:TextField;
///private var source:BitmapData = new BitmapData(465, 465, false, 0x000000);
public function Main():void
{
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
if (stage)
init();
else
addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
// entry point
Wonderfl.disable_capture();
Security.loadPolicyFile('http://labs-baybow.rhcloud.com/crossdomain.xml');
///addChild(new Bitmap(source));
// debug
//Debug.active = true;
initText();
initLoading();
//init3D();
//initText();
}
private function initLoading():void
{
trace("init");
var loaderlist:LoaderList = new LoaderList();
loaderlist.onStart = function():void {
trace("onStart");
}
loaderlist.onProgress = function():void {
trace("onProgress:", this.percent, "%", this.loaded, "/", this.total);
_text.text = "loading texture: "+ int(this.percent)+" %";
}
loaderlist.onComplete = function():void {
trace("onComplete");
_text.text = "loading 3D model";
Parsers.enableAllBundled();
_loader = new Loader3D();
_loader.scale(2);
_loader.addEventListener(LoaderEvent.RESOURCE_COMPLETE, onResourceComplete);
_loader.addEventListener(LoaderEvent.LOAD_ERROR, onLoadError);
_loader.load(new URLRequest(BASE_URL + 'assets/3d/ship.awd'));
}
for (var i:int = 0; i < arrSkyboxMap.length; i++)
{
loaderlist.addCommand(new LoadBitmapData(new URLRequest(BASE_URL + "assets/" +arrSkyboxMap[i]), { context: new LoaderContext(true), resId:"map" + i } ));
}
loaderlist.execute();
}
private function onResourceComplete(ev:LoaderEvent):void
{
_loader.removeEventListener(LoaderEvent.RESOURCE_COMPLETE, onResourceComplete);
_loader.removeEventListener(LoaderEvent.LOAD_ERROR, onLoadError);
init3D();
showHelp();
initListener();
}
private function showHelp():void
{
_text.text = "SPACE - switch fog\n";
_text.appendText("Mouse click and drag\n\n");
_text.appendText("3D model by SolCommand\n");
}
private function initListener():void
{
addEventListener(Event.ENTER_FRAME, _onEnterFrame);
stage.addEventListener(Event.RESIZE, onResize);
onAddedToStage();
onResize();
}
private function initText():void
{
_text = new TextField();
_text.defaultTextFormat = new TextFormat("Arial", 11, 0xFFFFFF);
_text.width = 240;
_text.height = 100;
_text.selectable = false;
_text.mouseEnabled = false;
_text.text = "loading texture: 0 %";
_text.filters = [new DropShadowFilter(1, 45, 0x0, 1, 0, 0)];
addChild(_text);
}
/*
* scene
* camera + controller
* view
* light
* 3D Object
* render
*/
private function init3D():void
{
scene = new Scene3D();
camera = new Camera3D();
camera.x = 0;
camera.y = 100;
camera.z = -1000;
camera.lookAt(new Vector3D());
cameraController = new HoverController(camera, null, 45, 20);
view = new View3D();
view.backgroundColor = 0x222233;
view.antiAlias = 4; // 2,4,16
view.scene = scene;
view.camera = camera;
addChild(view);
// light
// create a light for shadows that mimics the sun's position in the skybox
// 太陽光-方向性光源
sunLight = new DirectionalLight();
sunLight.castsShadows = true;
sunLight.direction = new Vector3D(-1, -1, -1);
sunLight.ambient = .1; // 環境
sunLight.diffuse = .7;
scene.addChild(sunLight);
// create a light for ambient effect that mimics the sky
// 環境光-無方向性點光源
plight = new PointLight();
plight.position = new Vector3D(0, 100, -1000);
plight.color = 0xFFFFFF;
plight.specular = .1; // 反射
plight.diffuse = .7; // 發散
plight.radius = 2000;
plight.fallOff = 2500;
scene.addChild(plight);
lightPicker = new StaticLightPicker([sunLight, plight]);
//var axis:Trident = new Trident(250, true);
//scene.addChild(axis);
// skybox
//var cubeTexture:BitmapCubeTexture = new BitmapCubeTexture(Cast.bitmapData(EnvPosX), Cast.bitmapData(EnvNegX), Cast.bitmapData(EnvPosY), Cast.bitmapData(EnvNegY), Cast.bitmapData(EnvPosZ), Cast.bitmapData(EnvNegZ))
var cubeTexture:BitmapCubeTexture = new BitmapCubeTexture(Cast.bitmapData(getResourceById("map0").data), Cast.bitmapData(getResourceById("map3").data), Cast.bitmapData(getResourceById("map1").data), Cast.bitmapData(getResourceById("map4").data), Cast.bitmapData(getResourceById("map2").data), Cast.bitmapData(getResourceById("map5").data))
skybox = new SkyBox(cubeTexture);
scene.addChild(skybox);
// floor
//var floor:WireframePlane = new WireframePlane(2000, 2000, 20, 20, 0x0F0F0F, 1,"xz");
var texture_floor:ColorMaterial = new ColorMaterial(0x333333, .8);
var floor:Mesh = new Mesh(new PlaneGeometry(2500, 2500, 20, 20), texture_floor);
// apply shadow effect
//texture_floor.shadowMethod = new DitheredShadowMapMethod(sunLight); // 陰影不這麼銳利
texture_floor.shadowMethod = new FilteredShadowMapMethod(sunLight); // 一般陰影
texture_floor.specular = 0; // 不要有反射
texture_floor.lightPicker = lightPicker;
floor.y = -500;
scene.addChild(floor);
// donut
var torusgeometry:TorusGeometry = new TorusGeometry(80, 60, 40, 20);
var texture2:ColorMaterial = new ColorMaterial(Math.random() * 0xFFFFFF, 1);
texture2.lightPicker = lightPicker;
torus = new Mesh(torusgeometry, texture2);
scene.addChild(torus);
// add 3D Object
_objContainer = new ObjectContainer3D();
scene.addChild(_objContainer);
_loader.x = 450;
_objContainer.addChild(_loader);
//scene.addChild(_loader);
// apply lights
var lights:Vector.<LightBase> = new Vector.<LightBase>(2);
lights[0] = sunLight;
lights[1] = plight;
LightsHelper.addStaticLightsToMaterials(_loader, lights);
// flint
emitter = new EmitterSmoke();
emitter.start();
// Create Particle Container
particleContainer = new ObjectContainer3D();
particleContainer.visible = isFog;
scene.addChild(particleContainer);
particleRenderer = new A3D4Renderer(particleContainer);
particleRenderer.addEmitter(emitter);
// stats
stats = new AwayStats(view);
stats.x = stage.stageWidth - stats.width;
addChild(stats);
}
private function onLoadError(ev:LoaderEvent):void
{
trace('Could not find', ev.url);
_loader.removeEventListener(LoaderEvent.RESOURCE_COMPLETE, onResourceComplete);
_loader.removeEventListener(LoaderEvent.LOAD_ERROR, onLoadError);
_loader = null;
}
private function onResize(event:Event = null):void
{
view.width = stage.stageWidth;
view.height = stage.stageHeight;
}
private function onAddedToStage(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
}
private function onKeyDown(e:KeyboardEvent):void
{
switch (e.keyCode) {
case Keyboard.SPACE:
isFog = !isFog;
particleContainer.visible = isFog;
break;
}
}
private function onMouseDown(event:MouseEvent):void
{
lastPanAngle = cameraController.panAngle;
lastTiltAngle = cameraController.tiltAngle;
lastMouseX = stage.mouseX;
lastMouseY = stage.mouseY;
move = true;
stage.addEventListener(Event.MOUSE_LEAVE, onStageMouseLeave);
}
private function onMouseUp(event:MouseEvent):void
{
move = false;
stage.removeEventListener(Event.MOUSE_LEAVE, onStageMouseLeave);
}
private function onStageMouseLeave(event:Event):void
{
move = false;
stage.removeEventListener(Event.MOUSE_LEAVE, onStageMouseLeave);
}
private function _onEnterFrame(e:Event):void
{
var msec:Number = getTimer();
if (move)
{
cameraController.panAngle = 0.3 * (stage.mouseX - lastMouseX) + lastPanAngle;
cameraController.tiltAngle = 0.3 * (stage.mouseY - lastMouseY) + lastTiltAngle;
}
plight.position = camera.position;
// update 3D object
torus.rotationZ += 1;
torus.y = (Math.sin(msec / 200) * 200);
_objContainer.rotationY += 1;
//_objContainer.z -= 1;
view.render();
///view.renderer.queueSnapshot(source);
}
}
}
import flash.display.Bitmap;
import flash.geom.Vector3D;
import org.flintparticles.common.actions.Age;
import org.flintparticles.common.actions.Fade;
import org.flintparticles.common.actions.ScaleImage;
import org.flintparticles.common.actions.TargetScale;
import org.flintparticles.common.counters.Steady;
import org.flintparticles.common.displayObjects.RadialDot;
import org.flintparticles.common.initializers.Lifetime;
import org.flintparticles.threeD.actions.DeathZone;
import org.flintparticles.threeD.actions.Move;
import org.flintparticles.threeD.actions.RandomDrift;
import org.flintparticles.threeD.emitters.Emitter3D;
import org.flintparticles.threeD.initializers.Position;
import org.flintparticles.threeD.initializers.Velocity;
import org.flintparticles.threeD.zones.BoxZone;
import org.flintparticles.threeD.actions.Friction;
class EmitterSmoke extends Emitter3D
{
public function EmitterSmoke()
{
counter = new Steady(10);
addInitializer(new Position(new BoxZone(100, 100, 1000, new Vector3D(1000, 0, 0))));
//addInitializer(new Lifetime(10));
addInitializer(new Velocity(new BoxZone(200, 20, 200, new Vector3D(-100, 0, 0)))); // 雲移動的方向速度
addInitializer(new A3D4DisplayObjects([
new Bitmap(new Materials().cloud1),
new Bitmap(new Materials().cloud2),
new Bitmap(new Materials().cloud3),
new Bitmap(new Materials().cloud4)],
null, true, 300));
//addAction(new Age());
addAction(new Move());
addAction(new ScaleImage(4, 10));
addAction(new Friction(0.9));
addAction(new Fade(0.7, 1.0));
addAction(new TargetScale(10));
addAction(new RandomDrift(50, 10, 50)); // 亂數飄移XYZ方向
addAction(new DeathZone(new BoxZone(2000, 1000, 2000), true));
}
}
import away3d.entities.Sprite3D;
//import away3d.materials.AnimatedBitmapMaterial;
import away3d.materials.MaterialBase;
import away3d.materials.TextureMaterial;
import away3d.textures.BitmapTexture;
import org.flintparticles.common.initializers.ImageInitializerBase;
import org.flintparticles.common.utils.WeightedArray;
import flash.display.BitmapData;
import flash.display.DisplayObject;
import flash.display.MovieClip;
import flash.geom.Matrix;
import flash.geom.Rectangle;
/**
* The A3D4DisplayObjects Initializer sets the DisplayObject to use to
* draw the particle in a 3D scene. It is used with the Away3D renderer when
* particles should be represented by one of a number of display objects.
*
* <p>The initializer creates an Away3D Sprite3D and a BitmapMaterial, with the display object
* as the image source for the material, for rendering the display
* object in an Away3D scene.</p>
*
* <p>This class includes an object pool for reusing objects when particles die.</p>
*/
class A3D4DisplayObjects extends ImageInitializerBase
{
private var _displayObjects:WeightedArray;
/**
* The constructor creates an A3D4DisplayObjects initializer for use by
* an emitter. To add an A3D4DisplayObjects to all particles created by
* an emitter, use the emitter's addInitializer method.
*
* @param displayObjects An array containing the DisplayObjects to use for
* each particle created by the emitter.
* @param weights The weighting to apply to each DisplayObject. If no weighting
* values are passed, the DisplayObjects are used with equal probability.
* @param usePool Indicates whether particles should be reused when a particle dies.
* @param fillPool Indicates how many particles to create immediately in the pool, to
* avoid creating them when the particle effect is running.
*
* @see org.flintparticles.common.emitters.Emitter#addInitializer()
*/
public function A3D4DisplayObjects( displayObjects:Array, weights:Array = null, usePool:Boolean = false, fillPool:uint = 0 )
{
super( usePool );
_displayObjects = new WeightedArray();
var len:int = displayObjects.length;
var i:int;
if( weights != null && weights.length == len )
{
for( i = 0; i < len; ++i )
{
addDisplayObject( displayObjects[i], weights[i] );
}
}
else
{
for( i = 0; i < len; ++i )
{
addDisplayObject( displayObjects[i], 1 );
}
}
if( fillPool > 0 )
{
this.fillPool( fillPool );
}
}
public function addDisplayObject( displayObject:DisplayObject, weight:Number = 1 ):void
{
_displayObjects.add( displayObject, weight );
if( _usePool )
{
clearPool();
}
}
public function removeDisplayObject( displayObject:DisplayObject ):void
{
_displayObjects.remove( displayObject );
if( _usePool )
{
clearPool();
}
}
/**
* Used internally, this method creates an image object for displaying the particle
* by creating a Sprite3D and using one of the display objects as its material.
*/
override public function createImage():Object
{
var displayObject:DisplayObject = _displayObjects.getRandomValue();
var material:MaterialBase;
if( displayObject is MovieClip )
{
//material = new AnimatedBitmapMaterial( MovieClip( displayObject ), true, true );
}
else
{
var bounds:Rectangle = displayObject.getBounds( displayObject );
var width:int = textureSize( bounds.width );
var height:int = textureSize( bounds.height );
var bitmapData:BitmapData = new BitmapData( width, height, true, 0x00FFFFFF );
var matrix:Matrix = displayObject.transform.matrix.clone();
matrix.translate( -bounds.left, -bounds.top );
matrix.scale( width / bounds.width, height / bounds.height );
bitmapData.draw( displayObject, matrix, displayObject.transform.colorTransform, null, null, true );
//material = new BitmapMaterial( bitmapData, true, true );
material = new TextureMaterial(new BitmapTexture(bitmapData));
material.smooth = true;
material.repeat = true;
}
return new Sprite3D( material, displayObject.width, displayObject.height );
}
private function textureSize( value:Number ):int
{
var val:int = Math.ceil( value );
var count:int = 0;
while( val )
{
count++;
val = val >>> 1;
}
return 1 << count + 1;
}
}
import flash.display.BitmapData;
import flash.geom.Rectangle;
class Materials
{
/**perlinNoiseに使うとまずいシード値(画像に穴があくかもしれない)*/
public const ERROR_SEEDS:Array = [346, 514, 1155, 1519, 1690, 1977, 2327, 2337, 2399, 2860, 2999, 3099, 4777, 4952, 5673, 6265, 7185, 7259, 7371, 7383, 7717, 7847, 8032, 8350, 8676, 8963, 8997, 9080, 9403, 9615, 9685];
public const CLOUD_SIZE:Rectangle = new Rectangle(0, 0, 200, 100);
public var cloud1:BitmapData;
public var cloud2:BitmapData;
public var cloud3:BitmapData;
public var cloud4:BitmapData;
public function Materials()
{
var ct:Number = (Math.random() < 0.3) ? Math.random() * 0.3 : Math.random() * 1.5;
cloud1 = Painter.createCloud(CLOUD_SIZE.width, CLOUD_SIZE.height, rndSeed(), ct, Color.cloudBase, Color.cloudLight, Color.cloudShadow);
ct = (Math.random() < 0.3) ? Math.random() * 0.3 : Math.random() * 1.5;
cloud2 = Painter.createCloud(CLOUD_SIZE.width, CLOUD_SIZE.height, rndSeed(), ct, Color.cloudBase, Color.cloudLight, Color.cloudShadow);
ct = (Math.random() < 0.3) ? Math.random() * 0.3 : Math.random() * 1.5;
cloud3 = Painter.createCloud(CLOUD_SIZE.width, CLOUD_SIZE.height, rndSeed(), ct, Color.cloudBase, Color.cloudLight, Color.cloudShadow);
ct = (Math.random() < 0.3) ? Math.random() * 0.3 : Math.random() * 1.5;
cloud4 = Painter.createCloud(CLOUD_SIZE.width, CLOUD_SIZE.height, rndSeed(), ct, Color.cloudBase, Color.cloudLight, Color.cloudShadow);
}
private function rndSeed():int
{
var seed:int = Math.random() * 10000 + 1;
if (ERROR_SEEDS.indexOf(seed) >= 0) seed++;
return seed;
}
}
import flash.display.BitmapData;
import flash.display.BlendMode;
import flash.display.Sprite;
import flash.filters.BevelFilter;
import flash.filters.ColorMatrixFilter;
import flash.filters.GlowFilter;
import flash.geom.Matrix;
import flash.geom.Point;
/**
* 色
*/
class Color
{
/**雲の色*/
static public var cloudBase:uint = 0xD7DDE5;
/**雲のハイライト色*/
static public var cloudLight:uint = 0xFFFFFF;
/**雲の影の色*/
static public var cloudShadow:uint = 0x6D8790;
}
class Painter
{
/**
* 雲画像生成
* @param width 幅
* @param height 高さ
* @param seed ランダムシード値
* @param contrast コントラスト0~
* @param color ベースの色
* @param light 明るい色
* @param shadow 暗い色
*/
static public function createCloud(width:int, height:int, seed:int, contrast:Number = 1, color:uint = 0xFFFFFF, light:uint = 0xFFFFFF, shadow:uint = 0xDDDDDD):BitmapData
{
var gradiation:Sprite = new Sprite();
var drawMatrix:Matrix = new Matrix();
drawMatrix.createGradientBox(width, height);
gradiation.graphics.beginGradientFill("radial", [0x000000, 0x000000], [0, 1], [0, 255], drawMatrix);
gradiation.graphics.drawRect(0, 0, width, height);
gradiation.graphics.endFill();
var alphaBmp:BitmapData = new BitmapData(width, height);
alphaBmp.perlinNoise(width / 3, height / 2.5, 5, seed, false, true, 1 | 2 | 4, true);
var zoom:Number = 1 + (contrast - 0.1) / (contrast + 0.9);
if (contrast < 0.1)
zoom = 1;
if (contrast > 2.0)
zoom = 2;
var ctMatrix:Array = [contrast + 1, 0, 0, 0, -128 * contrast, 0, contrast + 1, 0, 0, -128 * contrast, 0, 0, contrast + 1, 0, -128 * contrast, 0, 0, 0, 1, 0];
alphaBmp.draw(gradiation, new Matrix(zoom, 0, 0, zoom, -(zoom - 1) / 2 * width, -(zoom - 1) / 2 * height));
alphaBmp.applyFilter(alphaBmp, alphaBmp.rect, new Point(), new ColorMatrixFilter(ctMatrix));
var image:BitmapData = new BitmapData(width, height, true, 0xFF << 24 | color);
image.copyChannel(alphaBmp, alphaBmp.rect, new Point(), 4, 8);
image.applyFilter(image, image.rect, new Point(), new GlowFilter(light, 1, 4, 4, 1, 3, true));
var bevelSize:Number = Math.min(width, height) / 30;
image.applyFilter(image, image.rect, new Point(), new BevelFilter(bevelSize, 45, light, 1, shadow, 1, bevelSize / 5, bevelSize / 5, 1, 3));
var image2:BitmapData = new BitmapData(width, height, true, 0);
image2.draw(Painter.createGradientRect(width, height, [light, color, shadow], [1, 0.2, 1], null, 90), null, null, BlendMode.MULTIPLY);
image2.copyChannel(alphaBmp, alphaBmp.rect, new Point(), 4, 8);
image.draw(image2, null, null, BlendMode.MULTIPLY);
alphaBmp.dispose();
return image;
}
/**
* グラデーションスプライト生成
*/
static public function createGradientRect(width:Number, height:Number, colors:Array, alphas:Array, ratios:Array = null, rotation:Number = 0):Sprite
{
var i:int, rts:Array = new Array();
if (ratios == null)
for (i = 0; i < colors.length; i++)
rts.push(int(255 * i / (colors.length - 1)));
else
for (i = 0; i < ratios.length; i++)
rts[i] = Math.round(ratios[i] * 255);
var sp:Sprite = new Sprite();
var mtx:Matrix = new Matrix();
mtx.createGradientBox(width, height, Math.PI / 180 * rotation, 0, 0);
if (colors.length == 1 && alphas.length == 1)
sp.graphics.beginFill(colors[0], alphas[0]);
else
sp.graphics.beginGradientFill("linear", colors, alphas, rts, mtx);
sp.graphics.drawRect(0, 0, width, height);
sp.graphics.endFill();
return sp;
}
}