第十五章我们介绍了 3D,但只是将物体置于 3D 空间中,设置大小与位置。物体实际
上还是 2D 的。这就像老的 3D 游戏中,我们可以绕着某个物体或人物走,这些对象会转
过来面对我们。这些物体或人物并不是真正的会转过来 —— 只是看上去是这样的,因为它
们都是 2D 物体,那是我们看到它唯一的一个视角。
填充以及立体图形。学习完本章,大家就可以任意在三维空间中创建各种形状,并对它们执
行移动和旋转。
创建点和线条
是没有维度并且不可见的。开始时,我们还将使用 Ball3D 类,给一个非常小的半径,只要
能看到点在哪就够了。这样,只需要再创建几条线将这些小球连起来就行了。相当简单。我
们前面做过这样的例子,不过这次要在小球上添加透视,将它们放入 3D 空间。
行旋转(如前一章最后所讲的一样)然后在点间绘制一些线条。代码与上一章的 RotateXY.as
文件几乎相同。主要的区别在 onEnterFrame 的最后一块儿,从第一个点循环绘制线条到剩
下所有的点。同时,我还删除了 sortZ 方法,因为在这里有没有都一样。以下是 Lines3D1.as
的全部代码。
运行结果如图 16-1 所示。
点。第一个尝试非常简单。只要在创建时将每个 Ball3D 实例的半径设置为 0 即可,如下:
运行结果如图 16-2 所示。
图 16-2 3D 线条,点不可见
及 visible 对于一个看不到的点来说完全没有用的。没有可见的或可缩放的对象。根据这条
线索,更深层地思考认识一下这个继承自 Sprite 类的一般类,现在它实际上只是五个变量
的容器:xpos, ypos, zpos, x, y。实在有些过分。一个影片有许多功能——发送事件,绘图,
容纳其它 sprite 影片等等 —— 并且占用了大量资源。如此使用一个 sprite 影片就像开着
坦克到市区里捡一块面包。
实上, 如果再将透视和坐标旋转再放入这个类中,比单纯只存储几个属性更有意义。
先生们,现在我把这个 Point3D 类送与各位:
package {
public function Point3D(x:Number=0, y:Number=0, z:Number=0) {
}
public function setVanishingPoint(vpX:Number, vpY:Number):void {
}
public function setCenter(cX:Number,cY:Number,cZ:Number=0):void {
}
public function get screenX():Number {
}
public function get screenY():Number {
}
public function rotateX(angleX:Number):void {
}
性 进 行 设 置 。 类 中 包 涵 了 一 个 默 认 的 fl 属 性 以 及 用 于 存 放 消 失 点 的 属 性 , 可通过setVanishingPoint() 方法进行设置。使用三种旋转方法,可以绕着某一轴的中心点进行旋转。
还可以用 setCenter 方法改变中心点。大家马上会看到这些应用。最后,它还可以为我们处
理所有的透视。当我们已经旋转或设置了点的位置时,只需要用 screenX 和 screenY 即可
获得透视的点在屏幕上的位置。
图 16-3 3D 空间中的正方形坐标
简单的办法就是让所有的点在某个轴上的位置都相同(这里我选择了 z 轴),还要定义正方
形的其它两个轴(x 和 y 轴)。以下代码将代替循环随机创建的点:
points[0] = new Point3D(-100, -100, 100);
points[1] = new Point3D( 100, -100, 100);
points[2] = new Point3D( 100, 100, 100);
points[3] = new Point3D(-100, 100, 100);
我们还要手动设置每个点的消失点。在循环中做是再简单不过的了:
for (var i:uint = 0; i < numPoints; i++) {
}
因为现在有四个点,我们将不得不把 numPoints 改为 4。剩下的代码还可以正常工作,但
是我们还要多做一步:绘制一条连接最后一个点与第一个点的线,用于将图形封闭。以下是
全部代码,可见 Square3D.as(运行结果如图 16-4 所示):
图 16-4 3D 旋转正方形
都预先将所有的这些点在方格纸上标出(如图 16-5 所示) ,用来帮助作图。
图 16-5 使用方格纸标出所有的点
points[0] = new Point3D(-150, -250, 100);
points[1] = new Point3D( 150, -250, 100);
points[2] = new Point3D( 150, -150, 100);
points[3] = new Point3D( -50, -150, 100);
points[4] = new Point3D( -50, -50, 100);
points[5] = new Point3D( 50, -50, 100);
points[6] = new Point3D( 50, 50, 100);
points[7] = new Point3D( -50, 50, 100);
points[8] = new Point3D( -50, 150, 100);
points[9] = new Point3D( 150, 150, 100);
points[10] = new Point3D( 150, 250, 100);
points[11] = new Point3D(-150, 250, 100);
这样就完成了 SpinningE.as 中的旋转字母 E 的效果,运行结果如图 16-6 所示。不要忘记
将 numPoints 改为 12。稍后我们要使用 points.length 让这个值可以动态改变。
图 16-6 3D 旋转字母 E
3D 例子一样会发生倒置。您也许首先会想到增加所有点的 z 值,但这实际上会让效果变
得更糟。例如,假设将 z 设为 500。旋转的时候,z 将从 500 到 -500,甚至会让有些点
运动到观察点更往后的位置,会让事情更糟糕。不过我们可以使用 setCenter 方法将所有点
向 z 轴推移,如下:
for (var i:uint = 0; i < numPoints; i++) {
}
打开 Point3D 类,我们会看到 scale 的计算方法为:
这样就将整个系统推移了 200 像素,包括旋转系统。原来 z 的值保持不变,只是因为计算
透视的值更高了,那么所有物体都将呈现在观察着的前面。试用其它的值进行替换,观察运
动效果。稍后,我们会让这个图形在其它的轴上也能运动起来。
(如果要转载请注明出处http://blog.sina.com.cn/jooi,谢谢)