Flash 与分布学构想:球体曲面分布
??????????? 我们在制作3D的时候,你是否经常会看到一些图片围绕成一个球体点进行分布,这些分布的方式呈现为球体形状,在这里我将它称作球体曲面分布。这种分布的情况,是依赖一个很常用的球体模型来制作。它涉及到一些关于几何的知识点,只要我们掌握到这种公式就能够创造一种比较好的球体效果。 ??????????? 关于球体的公式,我查询了一些资料,发现这个公式并不唯一的。 ??????????? 例如:?球体上的一点坐标:M(x,y,z)这个点记录了球体上的一个坐标信息。 ???????????????????????? ?x=r*sin(a)*cos(b)(a 为纬度,b为经度 r为球体半径) ????????????????????????? y=r*sin(a) sin(b) ????????????????????????? z=r*cos(a) ? ??????????? 同样可以转变另外一种情况,它的坐标式参数方程为?? ???????????????????????? ??x=r*cos(a)*cos(b)(a 为纬度,b为经度 r为球体半径) ????????????????????????? y=r*cos(a) sin(b) ????????????????????????? z=r*sin(a) 关于这个公式推导也是比较容易的,这些可以查询高等数学的几何介绍。 ??? 有了这个公式后,制作flash 球体效果就容易多了。我们可以借助这个球面的参数方程制作一种3D球效果。注意到一点,数学上的模型和flash 里面是坐标系是不一样的,因此在使用的时候需要注意。 ??? flash 当中 x 和 y 和z? 跟这个模型的显示 不一样,在这里我们只需要简单处理,将数学上是y的数值对应为 flash 当中z数值,z 数值对应为flash 当中y数值即可。x不变。接下来就是代码时候。 ? ?????? ?? ? ? package { import flash.display.Sprite; import flash.events.Event; import flash.filters.*; public class Main extends Sprite { private var container:DisplayContainer3D; private var radius:Number = 600;//半径 private var n:int = 6; //定义6个图片 private var perPhi:Number = Math.PI / (n + 1); public function Main():void { init(); } private function init():void { container=new DisplayContainer3D(); addChild(container); container.filters=[new GlowFilter(0xffffff)]; container.x = stage.stageWidth / 2; container.y = stage.stageHeight / 2; container.z = 1200;//注意 尝试设置这个Z值可以和半径产生一定关系 creatImage(); addEventListener(Event.ENTER_FRAME,onStartMotion); } private function onStartMotion(event:Event):void { container.rotationY += 0.2; container.sortZ(); } private function creatImage():void { for (var i:int=1; i<=n; i++) { var phi:Number = perPhi * i; for (var j:int=0; j<10; j++) { var theta:Number = j * Math.PI * 2 / 10; //建立球体公式 var px:Number = radius * Math.sin(phi) * Math.cos(theta); var py:Number = radius * Math.cos(phi); var pz:Number = radius * Math.sin(phi) * Math.sin(theta); var image:Image=new Image(); image.x = px; image.y = py; image.z = pz; image.rotationX = phi * 180 / Math.PI - 90; image.rotationY = - theta * 180 / Math.PI - 270; container.addList(image); } } } } } import flash.display.Sprite; import flash.filters.*; class Image extends Sprite { public function Image() { this.graphics.lineStyle(8,0xffffff); this.graphics.beginFill(0x000000); this.graphics.drawRect( -50,-60,100,120); this.graphics.endFill(); this.filters=[new GlowFilter(0xffffff)]; } }// this.filters=[new ]
//3d 容器类,用于z轴处理深度排序 package { import flash.display.*; import flash.geom.*; public class DisplayContainer3D extends Sprite { private var list:Array = []; public function DisplayContainer3D() { } public function addList(obj:*):void { list.push(obj); addChild(obj); } public function get Arraylist():Array { return list; } public function sortZ():void { list.sort(depthSort); for (var i:int=0; i<list.length; i++) { var myimage:* = list[i]; this.setChildIndex(myimage,i); } } private function depthSort(objA:DisplayObject,objB:DisplayObject):int { var posA:Vector3D = objA.transform.matrix3D.position; posA = this.transform.matrix3D.deltaTransformVector(posA); var posB:Vector3D = objB.transform.matrix3D.position; posB = this.transform.matrix3D.deltaTransformVector(posB); return posB.z-posA.z; } } }
?最后,加载外部一些图片,结合这种分布来进行图片处理,贴上这个最后效果图。看起来也挺不错的。除了旋转这种效果之外,交互的动作还是有很多。如拖放一个球体3D旋转,这种玩法比较有意思,可是flash cs类库当中 并没有提供封装好的摄影机,因此对这种单靠递增rotationY来取得球体效果还是不是很理想的。 好吧,一个简单的效果,只要我们记住这个公式实现这种3D球 还是很容易,不过这种求取分布位置的算法并不唯一,而还有很多种,日后会记录在这里。方便后来者使用。我相信只要善用这些分布技术,做flash的效果还是很容易上手,而除了游戏之外,这种交互多媒体还是挺好玩的。 ? ? ?加载图片。 package { import flash.display.Sprite; import flash.events.*; import flash.display.Loader; import flash.net.URLRequest; import flash.display.Bitmap; public class QueueLoader extends EventDispatcher { private var loaderMap:Array = []; private var current:int=0;//当前数目 private var _arrayList:Array=[]; private var _loadinfo:String;//加载进度信息 private var total:int;//总数 public static const LOAD_COMPLETE:String="load_complete"; public static const LOAD_PROGRESS:String="load_progress"; public function QueueLoader() { } //添加图片 public function addImage(path:String):void { var loader:Loader=new Loader(); loader.contentLoaderInfo.addEventListener(Event.COMPLETE,onComplete); loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR,onError); var data:Object = {loader:loader,path:path}; loaderMap.push(data); total++; } public function start():void { next(); } //下一张图片 private function next():void { if (loaderMap.length > 0) { var data:Object = loaderMap.shift(); data["loader"].load(new URLRequest(data["path"])); } } private function onComplete(event:Event):void { event.currentTarget.removeEventListener(Event.COMPLETE,onComplete); event.currentTarget.removeEventListener(IOErrorEvent.IO_ERROR,onError); var bitmap:Bitmap = event.currentTarget.content as Bitmap; _arrayList.push(bitmap); current++; this.dispatchEvent(new Event(QueueLoader.LOAD_PROGRESS)); if(current==total) { this.dispatchEvent(new Event(QueueLoader.LOAD_COMPLETE)); } next(); } public function get arrayList():Array { return _arrayList; } public function get loadingInfo():String { return current+"/"+total; } private function onError(event:IOErrorEvent):void { trace("错误了"); } } } ? 其中的图片,需要自己进行设置 定义 6x10的图片(可以看作二维数组。) ? package { import flash.display.Sprite; import flash.events.Event; import flash.filters.*; import flash.display.Bitmap; public class Main extends Sprite { private var container:DisplayContainer3D; private var radius:Number = 600;//半径 private var n:int = 6; //定义6个图片 private var perPhi:Number = Math.PI / (n + 1); private var loader:QueueLoader=new QueueLoader(); public function Main():void { init(); } private function init():void { for(var i:int=0;i<60;i++) { loader.addImage("images/"+(i+1)+".jpg"); } loader.addEventListener(QueueLoader.LOAD_COMPLETE,onLoadComplete); loader.addEventListener(QueueLoader.LOAD_PROGRESS,onLoadProgress); loader.start(); container=new DisplayContainer3D(); addChild(container); container.x = stage.stageWidth / 2; container.y = stage.stageHeight / 2; container.z = 1200;//注意 尝试设置这个Z值可以和半径产生一定关系 addEventListener(Event.ENTER_FRAME,onStartMotion); } private function onLoadComplete(event:Event):void { loader.removeEventListener(QueueLoader.LOAD_COMPLETE,onLoadComplete); loader.removeEventListener(QueueLoader.LOAD_PROGRESS,onLoadProgress); creatImage(loader.arrayList); removeChild(loadingTxt); loadingTxt=null; } private function onLoadProgress(event:Event):void { loadingTxt.text=loader.loadingInfo; } private function onStartMotion(event:Event):void { container.rotationY += 0.2; container.sortZ(); } private function creatImage(array:Array):void { var k:int=0; for (var i:int=1; i<=n; i++) { var phi:Number = perPhi * i; for (var j:int=0; j<10; j++) { var theta:Number = j * Math.PI * 2 / 10; //建立球体公式 var px:Number = radius * Math.sin(phi) * Math.cos(theta); var py:Number = radius * Math.cos(phi); var pz:Number = radius * Math.sin(phi) * Math.sin(theta); var image:PhotoCantainer=new PhotoCantainer(array[k]); image.x = px; image.y = py; image.z = pz; image.rotationX = phi * 180 / Math.PI - 90; image.rotationY = - theta * 180 / Math.PI - 270; container.addList(image); k++; } } } } } import flash.display.Sprite; import flash.display.Bitmap; import flash.filters.DropShadowFilter; //图片容器 internal class PhotoCantainer extends Sprite { public function PhotoCantainer(bitmap:Bitmap) { addChild(bitmap); bitmap.x = - bitmap.width / 2; bitmap.y = - bitmap.height / 2; drawBase(bitmap.width,bitmap.height); } //绘制白色底 private function drawBase(w:Number,h:Number):void { this.graphics.beginFill(0xffffff); this.graphics.drawRect(-w/2-5,-h/2-5,w+10,h+10); this.graphics.endFill(); this.filters = [new DropShadowFilter(3,45,0.5)]; } } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |