away3d 4.0加入特效系统后,做比较炫的特效已经不是什么难事,away3d官方已经基于内置的particle system做了几个挺炫的粒子特效,需要的可以查看github中实例源码。这个传送门特效且作为away3d 粒子系统练手的的另一个实例。
简单说下,这个特效由三个独立的部分组成,转动的符文圆盘、向上发射的半透明光及不断从符文盘向上浮动的颗粒。效果图如下:

废话不说,直接上代码解释。
首先,必须准备三个部分的纹理和材质了。分别是符文圆盘、光辉、浮动粒子的纹理,在本教程最后提供的源码里有相应的纹理。
[Embed(source="../assets/pan.png")]
public var panTexture:Class;
[Embed(source="../assets/light.png")]
public var lightTexture:Class;
[Embed(source="../assets/blueball.png")]
public var blueballTexture:Class;
材质拆分成五个部分,分别对应五种不同的粒子mesh。简单说为什么有五种,因为:1圆盘+3光辉+1浮动粒子串。粒子对应的五种material、mesh、animator等的声明如下,它们之间的关系我们将在后面代码解释。
//materials
private var matPan:TextureMaterial;
private var matLight1:TextureMaterial;
private var matLight2:TextureMaterial;
private var matLight3:TextureMaterial;
private var matBall:TextureMaterial;
//particle objects
private var particleAnimationSet1:ParticleAnimationSet;
private var particleAnimationSet2:ParticleAnimationSet;
private var particleAnimationSet3:ParticleAnimationSet;
private var particleAnimationSet4:ParticleAnimationSet;
private var particleAnimationSet5:ParticleAnimationSet;
private var particleGeometry1:ParticleGeometry;
private var particleGeometry2:ParticleGeometry;
private var particleGeometry3:ParticleGeometry;
private var particleGeometry4:ParticleGeometry;
private var particleGeometry5:ParticleGeometry;
// scene objects
private var particleMesh1:Mesh;
private var particleMesh2:Mesh;
private var particleMesh3:Mesh;
private var particleMesh4:Mesh;
private var particleMesh5:Mesh;
private var animator1:ParticleAnimator;
private var animator2:ParticleAnimator;
private var animator3:ParticleAnimator;
private var animator4:ParticleAnimator;
private var animator5:ParticleAnimator;
接着就是初始化引擎了,为了便于理解,采用跟官方一样的方法,顺便贴出代码。
//engine variables
private var scene:Scene3D;
private var camera:Camera3D;
private var view:View3D;
private var cameraController:HoverController;
//signature variables
private var Signature:Sprite;
private var SignatureBitmap:Bitmap;
//navigation variables
private var _move:Boolean = false;
private var _lastPanAngle:Number;
private var _lastTiltAngle:Number;
private var _lastMouseX:Number;
private var _lastMouseY:Number;
/**
* Initialise the engine
*/
private function initEngine():void
{
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
scene = new Scene3D();
camera = new Camera3D();
view = new View3D();
view.scene = scene;
view.camera = camera;
//setup controller to be used on the camera
cameraController = new HoverController(camera, null, 255, 50, 300, 5);
view.addSourceURL("srcview/index.html");
addChild(view);
//add signature
Signature = Sprite(new SignatureSwf());
SignatureBitmap = new Bitmap(new BitmapData(Signature.width, Signature.height, true, 0));
stage.quality = StageQuality.HIGH;
SignatureBitmap.bitmapData.draw(Signature);
stage.quality = StageQuality.LOW;
addChild(SignatureBitmap);
addChild(new AwayStats(view));
}
引擎准备完后就是进入主题了,开始制作各种粒子。away3d中的生成粒子有几个步骤:
1、定义粒子需要的几何体集合,比如该教程中传送门的转动圆盘需要1个plane, 浮动的粒子需要50个plane来表现;
2、根据几何体几何,生成粒子需要的ParticleGeometry;
3、根据ParticleGeometry、Material,生成粒子mesh;
4、定义particleAnimationSet。粒子中的动作节点分为局部静态动作、局部动态动作还有全局动作,一个particleAnimationSet可以添加以上多种类型的不同动作节点;进一步了解动作细节,点击查看官方文档。
5、根据particleAnimationSet定义ParticleAnimator,并把ParticleAnimator装到粒子mesh上。
6、设置粒子的start time,duration time, delay time及局部动作属性。
文字太抽象,下面是直观的代码:
/**
* 初始化粒子材质
*/
private function initMaterials():void
{
matPan = new TextureMaterial(Cast.bitmapTexture(panTexture));
matBall = new TextureMaterial(Cast.bitmapTexture(blueballTexture));
matLight1 = new TextureMaterial(Cast.bitmapTexture(lightTexture));
matLight2 = new TextureMaterial(Cast.bitmapTexture(lightTexture));
matLight3 = new TextureMaterial(Cast.bitmapTexture(lightTexture));
matPan.bothSides = true;
matPan.smooth = true;
matPan.repeat = true;
matPan.alphaBlending = true;
matPan.specularColor = 0xFF1161D9;
matPan.ambientColor = 0xFF1161D9;
matLight1.bothSides = true;
matLight1.smooth = true;
matLight1.alphaBlending = true;
matLight2.bothSides = true;
matLight2.smooth = true;
matLight2.alphaBlending = true;
matLight3.bothSides = true;
matLight3.smooth = true;
matLight3.alphaBlending = true;
matBall.bothSides = true;
matBall.repeat = true;
matBall.smooth = true;
matBall.alphaBlending = true;
}
/**
* 初始化粒子
*/
private function initParticles():void
{
// 设置所有粒子的particleGeometry
var ball:Geometry = new PlaneGeometry(3,3,1,1,false);
var light1:Geometry = new CylinderGeometry(50,30,200,16,1,false,false,true);
var light2:Geometry = new CylinderGeometry(55,30,180,16,1,false,false,true);
var light3:Geometry = new CylinderGeometry(60,30,160,16,1,false,false,true);
var pan:Geometry = new PlaneGeometry(65,65,1,1);
var ballGeoSet:Vector.<Geometry> = new Vector.<Geometry>();
var light1GeoSet:Vector.<Geometry> = new Vector.<Geometry>();
var light2GeoSet:Vector.<Geometry> = new Vector.<Geometry>();
var light3GeoSet:Vector.<Geometry> = new Vector.<Geometry>();
var panGeoSet:Vector.<Geometry> = new Vector.<Geometry>();
// particle ball
for (var i:int = 0; i < 40; i++) {
ballGeoSet.push(ball);
}
particleGeometry1 = ParticleGeometryHelper.generateGeometry(ballGeoSet);
particleAnimationSet1 = new ParticleAnimationSet(true, true, false);
particleAnimationSet1.addAnimation(new ParticleBillboardNode());
particleAnimationSet1.addAnimation(new ParticleVelocityNode(ParticlePropertiesMode.GLOBAL, new Vector3D(0,30,0)));
particleAnimationSet1.addAnimation(new ParticleColorNode(ParticlePropertiesMode.GLOBAL,true,true,false,false,new ColorTransform(), new ColorTransform(1,1,1,0)));
particleAnimationSet1.addAnimation(new ParticlePositionNode(ParticlePropertiesMode.LOCAL_STATIC));
particleAnimationSet1.addAnimation(new ParticleOscillatorNode(ParticlePropertiesMode.LOCAL_STATIC));
particleAnimationSet1.addAnimation(new ParticleVelocityNode(ParticlePropertiesMode.LOCAL_STATIC));
particleAnimationSet1.initParticleFunc = initBallParticleProperties;
// light 1
light1GeoSet.push(light1);
particleGeometry2 = ParticleGeometryHelper.generateGeometry(light1GeoSet);
particleAnimationSet2 = new ParticleAnimationSet(true, true, false);
particleAnimationSet2.addAnimation(new ParticlePositionNode(ParticlePropertiesMode.GLOBAL, new Vector3D(0,100,0)));
particleAnimationSet2.addAnimation(new ParticleRotationalVelocityNode(ParticlePropertiesMode.GLOBAL, new Vector3D(0,1,0,25)));
particleAnimationSet2.addAnimation(new ParticleColorNode(ParticlePropertiesMode.GLOBAL,true,true,false, false,new ColorTransform(1,1,1,0.2), new ColorTransform(1,1,1,0.2)));
particleAnimationSet2.initParticleFunc = initLightParticleProperties;
// light 2
light2GeoSet.push(light2);
particleGeometry3 = ParticleGeometryHelper.generateGeometry(light2GeoSet);
particleAnimationSet3 = new ParticleAnimationSet(true, true, false);
particleAnimationSet3.addAnimation(new ParticlePositionNode(ParticlePropertiesMode.GLOBAL, new Vector3D(0,90,0)));
particleAnimationSet3.addAnimation(new ParticleRotationalVelocityNode(ParticlePropertiesMode.GLOBAL, new Vector3D(0,1,0,25)));
particleAnimationSet3.addAnimation(new ParticleColorNode(ParticlePropertiesMode.GLOBAL,true,true,false, false,new ColorTransform(1,1,1,0.2), new ColorTransform(1,1,1,0.2)));
particleAnimationSet3.initParticleFunc = initLightParticleProperties;
// light 3
light3GeoSet.push(light3);
particleGeometry4 = ParticleGeometryHelper.generateGeometry(light3GeoSet);
particleAnimationSet4 = new ParticleAnimationSet(true, true, false);
particleAnimationSet4.addAnimation(new ParticlePositionNode(ParticlePropertiesMode.GLOBAL, new Vector3D(0,90,0)));
particleAnimationSet4.addAnimation(new ParticleRotationalVelocityNode(ParticlePropertiesMode.GLOBAL, new Vector3D(0,1,0,25)));
particleAnimationSet4.addAnimation(new ParticleColorNode(ParticlePropertiesMode.GLOBAL,true,true,false, false,new ColorTransform(1,1,1,0.2), new ColorTransform(1,1,1,0.2)));
particleAnimationSet4.initParticleFunc = initLightParticleProperties;
// pan
panGeoSet.push(pan);
particleGeometry5 = ParticleGeometryHelper.generateGeometry(panGeoSet);
particleAnimationSet5 = new ParticleAnimationSet(true, true, false);
particleAnimationSet5.addAnimation(new ParticleRotationalVelocityNode(ParticlePropertiesMode.GLOBAL, new Vector3D(0,1,0,8)));
particleAnimationSet5.initParticleFunc = initPanParticleProperties;
}
/**
* 初始化场景
*/
private function initObjects():void
{
particleMesh1 = new Mesh(particleGeometry1, matBall);
particleMesh2 = new Mesh(particleGeometry2, matLight1);
particleMesh3 = new Mesh(particleGeometry3, matLight2);
particleMesh4 = new Mesh(particleGeometry4, matLight3);
particleMesh5 = new Mesh(particleGeometry5, matPan);
scene.addChild(particleMesh1);
scene.addChild(particleMesh2);
scene.addChild(particleMesh3);
scene.addChild(particleMesh4);
scene.addChild(particleMesh5);
animator1 = new ParticleAnimator(particleAnimationSet1);
animator2 = new ParticleAnimator(particleAnimationSet2);
animator3 = new ParticleAnimator(particleAnimationSet3);
animator4 = new ParticleAnimator(particleAnimationSet4);
animator5 = new ParticleAnimator(particleAnimationSet5);
particleMesh1.animator = animator1;
particleMesh2.animator = animator2;
particleMesh3.animator = animator3;
particleMesh4.animator = animator4;
particleMesh5.animator = animator5;
animator1.start();
animator2.start();
animator3.start();
animator4.start();
animator5.start();
}
/**
* 初始化浮动粒子属性
*/
private function initBallParticleProperties(properties:ParticleProperties):void
{
properties.startTime = Math.random()*4.1;
properties.duration = 3;
var degree1:Number = Math.random() * Math.PI ;
var degree2:Number = Math.random() * Math.PI;
var r1:Number = Math.random()*15;
var r2:Number = Math.random()*20 +10;
properties[ParticlePositionNode.POSITION_VECTOR3D] = new Vector3D(r1*Math.sin(degree1), 0 , r1*Math.cos(degree1));
properties[ParticleOscillatorNode.OSCILLATOR_VECTOR3D] = new Vector3D(r2*Math.sin(degree2), 0 , r2*Math.cos(degree2), Math.random()*4+2);
properties[ParticleVelocityNode.VELOCITY_VECTOR3D] = new Vector3D(0,Math.random()*100,0);
}
/**
* 初始化光辉属性
*/
private function initLightParticleProperties(properties:ParticleProperties):void
{
properties.startTime = 1;
properties.duration = 10;
}
/**
* 初始化符文转盘属性
*/
private function initPanParticleProperties(properties:ParticleProperties):void
{
properties.startTime = 1;
properties.duration = 1;
}
猛击下载源码