标签:
PS:此篇为转文,原文链接:http://www.cnblogs.com/yjmyzz/archive/2010/05/08/1730697.html
三维坐标系:右手法则坐标系
三维透视基本规则:
物体坐标在Z轴上越大(越远),则看起来越小,如果距离足够远,则物体消失于屏幕上的某个特定点(“消失点”)
技术上的主要处理:动态调整物体的scaleX与scaleY(同时因物体大小改变后,相应的x,y坐标值通常也会改变,所以x,y坐标也要做相应调整以符合透视规则),基本公式如下:
scale = fl/(fl+z)
package { import flash.display.Sprite; import flash.events.Event; import flash.events.KeyboardEvent; import flash.events.MouseEvent; import flash.ui.Keyboard; public class Base3D extends Sprite { public function Base3D() { var ball:Ball = new Ball(); addChild(ball); //观察点 相对于 消失点的坐标 var xPos:Number = 0; var yPos:Number = 0; var zPos:Number = 0; var fl:Number = 250;//焦距 //消失点 var vpX:Number = stage.stageWidth/2; var vpY:Number = stage.stageHeight/2; addEventListener(Event.ENTER_FRAME, EnterFrameHandler); stage.addEventListener(KeyboardEvent.KEY_DOWN, KeyDownHandler); stage.addEventListener(MouseEvent.MOUSE_WHEEL,MouseWheelHandler); //鼠标滚轮事件(注:必须让stage获取焦点时-即用鼠标在动画上点击一下,该事件才会触发,另外还要注意:嵌入网页时,浏览器也会响应鼠标滚轮) function MouseWheelHandler(e:MouseEvent):void { zPos += (e.delta*5); } function EnterFrameHandler(event:Event):void { if (zPos > -fl) { ball.visible = true; xPos = mouseX-vpX; yPos = mouseY-vpY; var scale:Number = fl / (fl + zPos); ball.scaleX = ball.scaleY = scale; ball.x = vpX+xPos*scale; ball.y = vpY+yPos*scale; } else ball.visible = false; //辅助线 graphics.clear(); graphics.lineStyle(1, 0XCCCCCC); graphics.moveTo(vpX, vpY); graphics.lineTo(vpX, ball.y); graphics.moveTo(vpX, vpY); graphics.lineTo(ball.x, vpY); graphics.lineStyle(1,0X000FF, 0.5); graphics.moveTo(vpX, vpY); graphics.lineTo(ball.x, ball.y); graphics.lineStyle(1,0XFF0000, 0.5); graphics.moveTo(ball.x, ball.y); graphics.lineTo(mouseX, mouseY); } function KeyDownHandler(e:KeyboardEvent):void { if (e.keyCode == Keyboard.UP) zPos += 50; else if (e.keyCode == Keyboard.DOWN) zPos -= 50; } } } }
此例中,"鼠标位置"充当"观察点"(即"人眼"位置),键盘↑↓键可调整小球在Z轴上的位置。移动鼠标,通过辅助线观察变化。
package { 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.ui.Keyboard; public class Base3D extends Sprite { private var ball:Ball; //相当于消失点的坐标 private var xpos:Number=0; private var ypos:Number=0; private var zpos:Number=0; //x,y,z三轴上的速度分量 private var vx:Number=0; private var vy:Number=0; private var vz:Number=0; private var friction:Number = 0.98; private var fl:Number=250; //消失点 private var vpX:Number = stage.stageWidth/2; private var vpY:Number = stage.stageHeight/2; public function Base3D() { init(); } private function init():void { stage.align = StageAlign.TOP_LEFT; stage.scaleMode = StageScaleMode.NO_SCALE; ball = new Ball(20); addChild(ball); addEventListener(Event.ENTER_FRAME, EnterFrameHandler); stage.addEventListener(KeyboardEvent.KEY_DOWN, KeyDownHandler); } private function EnterFrameHandler(event:Event):void { vpX = stage.stageWidth/2; vpY = stage.stageHeight/2; xpos += vx; ypos += vy; zpos += vz; vx *= friction; vy *= friction; vz *= friction; if (zpos>-fl) { var scale:Number = fl / (fl + zpos); ball.scaleX=ball.scaleY=scale; ball.x=vpX+xpos*scale; ball.y=vpY+ypos*scale; ball.visible=true; } else { ball.visible=false; } //辅助线 graphics.clear(); graphics.lineStyle(1,0xefefef); graphics.moveTo(0,stage.stageHeight/2); graphics.lineTo(stage.stageWidth,stage.stageHeight/2); graphics.lineTo(stage.stageWidth-15,stage.stageHeight/2-8); graphics.moveTo(stage.stageWidth,stage.stageHeight/2); graphics.lineTo(stage.stageWidth-15,stage.stageHeight/2+8); graphics.moveTo(stage.stageWidth/2,0); graphics.lineTo(stage.stageWidth/2,stage.stageHeight); graphics.lineTo(stage.stageWidth/2-8,stage.stageHeight-15); graphics.moveTo(stage.stageWidth/2,stage.stageHeight); graphics.lineTo(stage.stageWidth/2+8,stage.stageHeight-15); graphics.lineStyle(1,0xdadada); graphics.moveTo(vpX,vpY); graphics.lineTo(ball.x,ball.y); } private function KeyDownHandler(e:KeyboardEvent):void { switch (e.keyCode) { case Keyboard.UP : vy -= 10; break; case Keyboard.DOWN : vy += 10; break; case Keyboard.LEFT : vx -= 10; break; case Keyboard.RIGHT : vx += 10; break; case Keyboard.SHIFT : vz += 5; break; case Keyboard.CONTROL : vz -= 5; break; default : break; } } } }
此例中,↑↓←→控制x,y轴方向速度,shift/ctrl控制z轴速度
package { 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.ui.Keyboard; public class Base3D extends Sprite { private var ball:Ball; private var xpos:Number=0; private var ypos:Number=0; private var zpos:Number=0; private var vx:Number = Math.random()*12-6; private var vy:Number = Math.random()*12-6; private var vz:Number = Math.random()*12-6; private var fl:Number = 250; //消失点 private var vpX:Number = stage.stageWidth/2; private var vpY:Number = stage.stageHeight/2; //相对于消失点的六个边界面(上,下,左,右,前,后) private var top:Number = -100; private var bottom:Number = 100; private var left:Number = -100; private var right:Number = 100; private var front:Number = 100; private var back:Number = -100; public function Base3D() { init(); } private function init():void { stage.align = StageAlign.TOP_LEFT; stage.scaleMode = StageScaleMode.NO_SCALE; ball = new Ball(15); addChild(ball); addEventListener(Event.ENTER_FRAME, EnterFrameHandler); } private function EnterFrameHandler(event:Event):void { vpX = stage.stageWidth/2; vpY = stage.stageHeight/2; xpos += vx; ypos += vy; zpos += vz; var radius:Number = ball.getRadius(); //左右边界 if (xpos+radius > right) { xpos = right-radius; vx *= -1; } else if (xpos - radius < left) { xpos = left+radius; vx *= -1; } //上下边界 if (ypos+radius > bottom) { ypos = bottom-radius; vy *= -1; } else if (ypos - radius < top) { ypos = top+radius; vy *= -1; } //前后边界 if (zpos+radius > front) { zpos = front-radius; vz *= -1; } else if (zpos - radius < back) { zpos = back+radius; vz *= -1; } //换算成平面二维坐标及缩放比率 if (zpos > -fl) { var scale:Number = fl / (fl + zpos); ball.scaleX=ball.scaleY=scale; ball.x=vpX+xpos*scale; ball.y=vpY+ypos*scale; ball.visible = true; } else ball.visible=false; //辅助线 graphics.clear(); graphics.lineStyle(1,0xccccff); graphics.moveTo(0,stage.stageHeight/2); graphics.lineTo(stage.stageWidth,stage.stageHeight/2); graphics.lineTo(stage.stageWidth-15,stage.stageHeight/2-8); graphics.moveTo(stage.stageWidth,stage.stageHeight/2); graphics.lineTo(stage.stageWidth-15,stage.stageHeight/2+8); graphics.moveTo(0,stage.stageHeight); graphics.lineTo(stage.stageWidth,0); graphics.lineTo(stage.stageWidth-15,2); graphics.moveTo(stage.stageWidth,0); graphics.lineTo(stage.stageWidth-6,13); graphics.moveTo(stage.stageWidth/2,0); graphics.lineTo(stage.stageWidth/2,stage.stageHeight); graphics.lineTo(stage.stageWidth/2-8,stage.stageHeight-15); graphics.moveTo(stage.stageWidth/2,stage.stageHeight); graphics.lineTo(stage.stageWidth/2+8,stage.stageHeight-15); graphics.lineStyle(1,0xffccff); graphics.moveTo(vpX,vpY); graphics.lineTo(ball.x,ball.y); } } }
标签:
原文地址:http://www.cnblogs.com/cangyu/p/4701131.html