[ADC文章]使用ActionScript 3制作以3D方式移动的星星[转载自InfoQ]
本文转载自InfoQ,原文地址是: http://www.infoq.com/cn/vendorcontent/show.action?vcr=838
本教程演示了如何基于Adobe Flash Player 10及Adobe Flash CS4专业版的三维功能,并使用ActionScript3构建用户可控的3D动画。
Flash Player 10中新增的3D支持为你完成了许多3D相关的工作,并且它能和2D特性等功能集成使用。这些3D特性和2D中的对应物比较类似,因此在为游戏和动画添加3D功能的时候,你可能会有似曾相识的感觉——即便某些金属和可视化模型你是第一次遇见。
在这个3D教程中,我会向你展示如何来创建一系列以3D方式移动的星星,以及如何让它们响应用户输入。如图1(点击播放这个动画,调整滑动条以观察效果)。
图1. 3D场景中的星星(点击播放这个动画,调整滚动条以观察效果)
要求
你需要以下软件和文件来完成这个向导:
Flash Player 10或更新版本
Flash CS4 专业版
示例文件
- 3dmovingstars.zip (ZIP, 1.1 MB)
必要知识
你需要对Adobe Flash的制作界面,使用符号及鼠标交互方式有基本的了解。对3D功能的作用有所了解也是有帮助的。你应该对Mariko Ogawa的文章《探索Flash新增的3D功能》中讨论的话题较为熟悉。本教程结尾处有关于Flash中3D功能的更多信息。
创建场景及星星
Flash Player 10的3D功能可以让你设置3D的属性,并让播放器来做其余的计算。这让你可以为游戏或SWF内容添加3D效果,而不需要事先进行数学计算。本教程会使用 ActionScript来修改星星,但是在此之前你需要创建一个场景,并向库中添加图像元素。
-
创建一个新的动画,并提供一个600 × 320的场景,并将背景设置成黑色(如图2)。

图2. 设置场景的尺寸和背景色
-
在场景的左上角创建三个滑动条:打开Components窗口(选择Window > Components)并将Slider组件拖至场景中。创建三个滑动条之后,将它们命名为angleSpeedSlider,zSpeedSlider和radiusSlider,并各指定一个标签(如图3)。

图3. 用户控件:滑动条组建和它们的标签文字
-
使用PolyStar工具在场景中创建一颗星星:点击Rectangle Tool并保持,然后在子菜单中选择PlyStar工具。在Tool Setting中设置样式为星型,边数为5,点的大小为0.48(如图4),这样便生成了一个由点与点之间的直线所组成的星星。

图4. 设置PolyStar工具中的选项
- 设置Stroke为2 pt White并将Fill设为Blue。在绘图时按住Shift键,这样可以让星星按照水平对齐。完成之后,将Width设为150。
-
将对象转为MovieClip符号(选择Modify > Convert to Symbol),输入名称为Star,并将限制点放在中间(如图5)。选择“导出为ActionScript”(如果你找不到它们,那么请选择“高级”按钮)。如果系统提示说没有找到这个类的定义,可以忽略这个警告信息。让Flash使用自动生成的类型。

图5. 转化为符号并导出为ActionScript
- 删除场景中的星星,你可以使用ActionScript向场景中添加星星。
- 添加一个播放/暂停按钮来启动和停止星星的移动。从Components面板中选择一个PlayPauseButton至左下角。在属性中将它的实例名设为playpause。在我的示例中,我将x设为3,y设为282,并将宽和高设为34。
使用ActionScript进行3D操作
现在库中已经存在了这些元素,你可以使用ActionScript来操作这些内容,它们会向用户方向移动:
- 在第一帧的Actions面板中输入下列代码
- //显示的星星数量
- //最上方的星星至底部的可视距离(所有的y值都相同)
- //星星之间的z距离(任意值)
- //第一个星星的初始Z值,因此最上方的星星的z等于0
- //星星离开视图时的Z值(通过视觉估计)
- //计时器的延迟数(毫秒)。30毫秒等于每秒大约33.3帧。
- //星星面向用户的速度
- //创建一个包含所有星星的数组
- //为性能考虑,这些变量定义在变量外部:
- //表示星星深度的局部变量
- //用于操作星星的局部变量
- var currentStar:Star;
- //默认情况下,星星消失在场景的中间。在现在的示例中,我们将其移动至顶部附近,这样我们便
- //可以“俯视”这些星星。
- root.transform.perspectiveProjection.projectionCenter =
- //创建星星的循环
- //从最远的星星开始创建并进行定位
- {
- //创建一个新的星星
- currentStar = new Star();
- //所有星星的x和y坐标都相同:视图中间靠上
- currentStar.x = (stage.stageWidth/2);
- currentStar.y = stage.stageHeight - ORIGINAL_YBORDER;
- //设置深度,即z值,这表示它与用户之间的距离
- currentStar.z = starDepth;
- //设置对象的alpha值,这样越远的星星显得越模糊
- ((INITIAL_STAR_DEPTH - starDepth) /
- (INITIAL_STAR_DEPTH - MINIMUM_STAR_DEPTH) * 0.8));
- //将星星加入数组
- stars.push(currentStar);
- //将星星加入场景之中
- addChild(currentStar);
- //跟新下一个星星的起始深度,让它显得更近一些
- starDepth -= ZDISTANCE;
- }
- 你需要使用Timer来移动星星。或者你可以使用ENTER_FRAME事件,这样你可以调整点击的帧频,动画会相应与之统一。每次计时器到点之后,星星便向用户靠拢。你可以使用如下代码在Actions面板中创建定时器及处理程序:
- //创建一个定时器,间隔为30毫秒,这大约是每秒33.3帧。
- //这个函数在每次计时器到点时执行
- {
- //循环遍历数组中所有星星
- for (var i=0; i < NUMBER_OF_STARS; i++)
- {
- //使用局部变量访问星星
- currentStar = stars[i];
- //减少其z值,让星星开起来更近一些
- currentStar.z -= zSpeed;
- //如果z值比最小的星星深度还要小,那么我们知道它已经“经过”了,于是它便可以放到队列
- //末尾,于是我们设置其z值,并将其放到显示列表的第一位(如果z值小于零,说明星星已经
- //“很接近了”,但还是有可能在屏幕上)。
- if (currentStar.z < MINIMUM_STAR_DEPTH)
- {
- //设置到队列的尾部,离用户最远
- currentStar.z = INITIAL_STAR_DEPTH;
- //将星星移动至第一位(即显示列表的最后)
- setChildIndex(currentStar,0);
- }
- //设置对象的alpha值,于是越远的星星显得越模糊
- (INITIAL_STAR_DEPTH - MINIMUM_STAR_DEPTH) * 0.8));
- }
- }
- //响应播放/暂停按钮的事件来开启或关闭计时器
- {
- if (actionTimer.running)
- {
- actionTimer.stop();
- playpause.play_mc.visible = true;
- playpause.pause_mc.visible = false;
- } else
- {
- actionTimer.start();
- playpause.play_mc.visible = false;
- playpause.pause_mc.visible = true;
- }
- }
- 选择Control > Test Movie并点击播放按钮来测试动画。你现在可以看到星星笔直朝用户移动。你可以从Moving-Stars-1.fla文件来浏览到目前为止的功能。
添加用户交互
现在我们来处理控制星星动画的用户输入,它们控制星星的水平震动及移动速度:
- 使用角度和半径输入来控制星星向用户移动时的左右位置。把这些代码添加到星星的创建循环中,以此配置滑动条的初始值及变量范围。
- //配置滑动条
- angleSpeedSlider.value = 10;
- angleSpeedSlider.minimum = 1;
- angleSpeedSlider.maximum = 30;
- zSpeedSlider.value = zSpeed;
- zSpeedSlider.minimum = 1;
- zSpeedSlider.maximum = 30;
- radiusSlider.value = 7;
- radiusSlider.minimum = 1;
- radiusSlider.maximum = 20;
- //设置每个星星的初始角度(稍后增加)
- //每个星星之间的角度差距
- //角度变化的速度
- //移动半径
- //用于存放星星角度的数组,与存放星星的数组相对应
- 你同样需要改变星星的创建循环,以此设置和跟踪其水平位置。在创建星星时,根据滑动条的位置设置x值。将以下这行设置x值得代码:
- currentStar.x = (stage.stageWidth / 2);
替换这句为:
- 在星星创建循环的末尾,添加以下几行代码来保存及增加角度
- //将星星的角度保存起来,每个星星和它的角度可以通过相同的数组下标来联系起来
- angles.push(angle);
- //更新下一个星星的角度
- angle += ANGLEDIFFERENCE;
- 此时星星的创建循环应该是这样:
- //创建星星的循环
- //从最远的星星开始创建并进行定位
- {
- //创建一个新的星星
- currentStar = new Star();
- //所有星星的x和y坐标都相同:视图中间靠上
- currentStar.y = stage.stageHeight - ORIGINAL_YBORDER;
- //设置深度,即z值,这表示它与用户之间的距离
- currentStar.z = starDepth;
- //设置对象的alpha值,这样越远的星星显得越模糊
- (INITIAL_STAR_DEPTH - MINIMUM_STAR_DEPTH) * 0.8));
- //将星星加入数组
- stars.push(currentStar);
- //将星星加入场景之中
- addChild(currentStar);
- //跟新下一个星星的起始深度,让它显得更近一些
- starDepth -= ZDISTANCE;
- //将星星的角度保存起来,每个星星和它的角度可以通过相同的数组下标来联系起来
- angles.push(angle);
- //跟新下一个星星的角度
- angle += ANGLEDIFFERENCE;
- }
- 改变计时器函数的几个地方,将滑动条的值用于z方向的速度,并以此计算新的x值。新的计时器函数为:
- //这个函数在每次计时器到点时执行
- {
- //首先从滑动条中获得动态速度
- angleSpeed =angleSpeedSlider.value*0.01;
- zSpeed = zSpeedSlider.value;
- radius = radiusSlider.value * 20;
- //循环遍历数组中所有星星
- for (var i=0; i < NUMBER_OF_STARS; i++)
- {
- //使用局部变量访问星星
- currentStar = stars[i];
- //获取星星的角度
- angle = angles[i];
- //减少其z值,让星星开起来更近一些
- currentStar.z -= zSpeed;
- //如果z值比最小的星星深度还要小,那么我们知道它已经“经过”了,于是它便可以放到队列
- //末尾,于是我们设置其z值,并将其放到显示列表的第一位(如果z值小于零,说明星星已经
- //“很接近了”,但还是有可能在屏幕上)。
- if (currentStar.z < MINIMUM_STAR_DEPTH)
- {
- //设置到队列的尾部,离用户最远
- currentStar.z = INITIAL_STAR_DEPTH;
- //根据前一个星星的角度设置下一个的角度
- if (i != NUMBER_OF_STARS - 1)
- {
- //根据角度之差来设置前一个星星
- angle = angles[i+1] - ANGLEDIFFERENCE;
- }
- else
- {
- //angles[0]已经增加了,因此在这个if块之后也要减去刚添加的angleSpeed,
- //以此来维护angledifference。
- angle = angles[0] - ANGLEDIFFERENCE - angleSpeed;
- }
- //将星星移动至第一位(即显示列表的最后)
- setChildIndex(currentStar,0);
- }
- //增加并保存星星的新位置
- angle += angleSpeed;
- angles[i] = angle;
- //计算星星的新x值
- //设置对象的alpha值,于是越远的星星显得越模糊
- (INITIAL_STAR_DEPTH - MINIMUM_STAR_DEPTH) * 0.8));
- }
- }
现在你让用户可以控制星星的速度及摆动幅度了。示例文件Moving-Stars-2.fla展示了用户可控制的星星移动。
额外功能:增加转动
你可以同时进行多种变化,2D或3D均可。添加z轴的旋转和2D的做法相同。你可以把以下代码添加至星星的创建循环中(假设是五角星):
//设置旋转,每个星星都比其它的略有旋转
currentStar.rotationZ = i*360/(NUMBER_OF_STARS*5);
根据i变量进行旋转可以让每个星星看上比前一个有一些转动,以下代码可以让星星慢慢地顺时针旋转:
//慢慢的顺时针旋转
currentStar.rotationZ += 2;
完成了!示例文件Moving-Stars-3.fla中包含了最终的版本。作为额外的功能,你可以让用户来控制旋转,使用一个滑动条的值来代替上一行中的“2”。
总结
本教程基于计时器函数使用了显示对象及动画对象的z属性。作为另一篇关于Flash和ActionScript 3中3D功能的教程,请参考我的另一篇文章:使用ActionScript 3开发Flash的3D视图控制器。
你也可以参考以下讨论3D功能的在线文档:
- 创建和编辑艺术品:3D动画(使用Flash CS4专业版)
- 使用三维功能(Flash中的ActionScript 3编程)
关于作者
Rodney Smith在Adobe Systems工作了6年,领导Adobe在线应用更新技术及电子商务传输引擎创建。他是Flex和Flash平台技术的忠实拥护者,在加入Adobe之前,他涉及的领域有流媒体,移动设备及搜索。他的兴趣包括软件安全和用户界面设计。

.gif)
.gif)




.gif)
发表新评论