Starling实现的3D云彩效果
Starling本身是一个2D框架,不过引入一些3D计算,就可以实现简单的3D效果。这次我们要演示的是一个3D云彩效果,您就像一个战斗机飞行员,驾驶爱机在空中腾云驾雾,享受在云层中急速穿梭的感觉。因为只是简单的引入了Z轴排序,效果看起来还有不少瑕疵,期待3D高手不吝赐教,继续优化一下这个效果:)
示意图:
演示地址: http://www.todoair.com/demo/cover/CloudDemo.html
附上源代码:
package cloud
{
import flash.display.Bitmap;
import flash.geom.Point;
import flash.geom.Rectangle;
import starling.display.BlendMode;
import starling.display.Image;
import starling.display.QuadBatch;
import starling.display.Sprite;
import starling.events.Event;
import starling.events.Touch;
import starling.events.TouchEvent;
import starling.events.TouchPhase;
import starling.textures.Texture;
import starling.textures.TextureAtlas;
import test.pf.PageFlipContainer;
/**
* Starling实现的3D云彩效果
* @author shaorui
*/
public class Game extends Sprite
{
/**云彩的素材图片*/
[Embed(source="../assets/cloud10.png")]
protected const cloudImgClass:Class;
/**承载纹理用*/
protected var img:Image;
/**用批次处理来显示*/
private var quadBatch:QuadBatch;
/**存储云朵信息*/
private var imgArr:Vector.<CloudItem>;
/**创建多少个云朵*/
private var imgCount:int = 300;
/**屏幕宽度*/
private var screenWidth:Number = 960;
/**屏幕高度*/
private var screenHeight:Number = 640;
/**缩放的阈值*/
private var focal:Number=250;
/**屏幕可见区域*/
private var stageRect:Rectangle;
/**@private*/
private var vpX:Number;
/**@private*/
private var vpY:Number;
/**@private*/
public function Game()
{
super();
addEventListener(Event.ADDED_TO_STAGE,initGame);
}
/**初始化*/
private function initGame(...args):void
{
removeEventListener(Event.ADDED_TO_STAGE,initGame);
//计算Z轴用
vpX=stage.stageWidth/2;
vpY=stage.stageHeight/2;
stageRect = new Rectangle(0,0,stage.stageWidth,stage.stageHeight);
centerPoint = new Point(screenWidth/2,screenHeight/4*3);
//设置蓝天颜色
stage.color = 0x0008a7;
//创建一个注册点在中心的图片
img = Image.fromBitmap(new cloudImgClass(),false);
img.pivotX = img.width/2;
img.pivotY = img.height/2;
//批次用于渲染
quadBatch = new QuadBatch();
addChild(quadBatch);
//用数组存储云朵属性
imgArr = new Vector.<CloudItem>();
for (var i:int = 0; i < imgCount; i++)
{
var item:CloudItem = new CloudItem();
item.rotation = Math.random()*Math.PI;
setAShape(item);
imgArr.push(item);
}
addEventListener(Event.ENTER_FRAME,enterFrameHandler);
addEventListener(TouchEvent.TOUCH,onTouchHandler);
}
/**重置位置*/
private function setAShape(shape:CloudItem):void
{
shape.scale = 0.001;
shape.startX=screenWidth*2*Math.random()-screenWidth;
shape.startY=screenHeight/2+screenHeight/2*Math.random()-100;
shape.x = shape.startX;
shape.y = shape.startY;
shape.zpos = Math.random()*800+400;
}
/**Z排序*/
private function sortArray():void
{
imgArr.sort(zSortFunction);
}
/**排序方法*/
private function zSortFunction(a:CloudItem,b:CloudItem):Number
{
if(a.zpos > b.zpos)
return -1;
else if(a.zpos < b.zpos)
return 1;
else
return 0;
}
/**判断一个对象是否已经不在屏幕区域*/
private function shapeAvisible(shape:CloudItem):Boolean
{
var shapeRect:Rectangle = shape.getBounds(this);
return shapeRect.intersects(stageRect);
}
/**每帧调用*/
private function enterFrameHandler(event:Event=null):void
{
quadBatch.reset();
var xpos:Number;
var ypos:Number;
var item:CloudItem;
for (var i:int = 0; i < imgCount; i++)
{
item = imgArr[i];
//reset properties
item.zpos-=4;
var x1:Number = screenWidth-item.startX*2;
var y1:Number = screenHeight/2-item.startY;
if (item.zpos>-focal && shapeAvisible(item))
{
xpos=centerPoint.x-vpX-x1;//x维度
ypos=centerPoint.y-vpY-y1;//y维度
item.scale=focal/(focal+item.zpos);//缩放产生近大远小,取值在0-1之间;
item.x=vpX+xpos*item.scale;
item.y=vpY+ypos*item.scale;
}
else
{
setAShape(item);
}
}
//每次进行Z排序
sortArray();
for (i = 0; i < imgCount; i++)
{
item = imgArr[i];
img.x = item.x;
img.y = item.y;
img.scaleX = img.scaleY = item.scale;
img.rotation = item.rotation;
quadBatch.addImage(img);
}
}
/**@private*/
private var centerPoint:Point;
/**触碰处理*/
private function onTouchHandler(event:TouchEvent):void
{
var touch:Touch = event.getTouch(this);
if(touch == null)
return;
if(touch.phase == TouchPhase.HOVER)
{
centerPoint.x = touch.globalX/4+screenWidth/8;
centerPoint.y = touch.globalY/4+screenHeight/8+280;
}
}
}
}
import flash.geom.Rectangle;
import starling.display.DisplayObject;
/**
* 存储云朵属性的类
* @author shaorui
*/
class CloudItem
{
private var itemWidth:Number = 256;
private var itemHeight:Number = 256;
public var startX:Number;
public var startY:Number;
public var zpos:Number=0;
public var x:Number = 0;
public var y:Number = 0;
public var scale:Number = 1;
public var rotation:Number = 0;
public function getBounds(targetSpace:DisplayObject):Rectangle
{
var w:Number = itemWidth*scale;
var h:Number = itemHeight*scale;
var rect:Rectangle = new Rectangle(x-w/2,y-h/2,w/2,h/2);
return rect;
}
}
类中引用的图片下载:
原文链接 : Starling实现的3D云彩效果
浙公网安备 33010602011771号