Flash实用技巧1--基于时间的动画(as3.0)
发布时间:2012-11-30 发布: 分类:技术文档
种方法在一些游戏中比较常用。我们知道,帧和计时器动画都不能以特定的速率播放。一个
复杂的动画在一台又老又慢的电脑上运行可能要比最初设计的速度慢上许多。
到,使用基于时间的动画无论最终动画运行的帧频如何,都将获得可靠的速度。
每帧(pixels per frame)
时器动画中,当然,就应该是每次定时间隔移动 5 像素。
其中的一部分,因此这个速度值就要更大一些。如果某个物体的速度是每帧 10 像素,每秒
30 帧的速度运动,
档类中截取了一部分并进行了一些变化,见下面粗体部分(也可在 TimeBased.as 中找到)
package {
}
private function init():void {
}
private function onEnterFrame(event:Event):void {
var right:Number = stage.stageWidth;
var top:Number = 0;
var bottom:Number = stage.stageHeight;
if (ball.x + ball.radius > right) {
}
如上所描述,我改变了对速度的计算,让它们使用固定的值,而非随机值。然后我创建了一
个名为 time 的变量,让它等于 flash.utils.getTimer 函数的结果。getTimer 函数非常简单。
它返回影片已经运行了的毫秒数 —— 这就是它全部的工作。我们没有办法清除它,重启它,
改变它,等等。它只是一个计数器。
一次,将两个结果相减,我们就能知道确切的—— 毫秒 ——这两次调用之间经过了多少时
间。
除以 1,000,我们将得到以秒为单位的间隔时间,这是个以秒为单位的分数。由于我们的 vx
和 vy 现在是以像素每秒来计算的,因此可以让它们去乘以这个分数,这样就知道要对物体
移动多少了。同样,不要忘记重新设置 time 变量的值,以便让下一帧进行计算。
我们可以以任何帧频来发布这个影片,它仍然可以以同样的速度运动!通过修改
stage.frameRate 的值,试验一下高到 1,000 fps,低到 10 fps,你会看到小球的速度是相同
的。当然,较高的频率会让动画更加流畅,而较低的频率则会十分不连贯,但是速度是一致
的。
相似的技术应用在加速度或外力上,如重力,因为它们也是基于时间的。加速度肯定要比转
前要大很多,因为加速度被定义为速度对时间的变化率。例如,重力大约为 32 英尺/秒/
秒。
0.5 * 30 * 30。然后像这样将它加入:
在最后一个例子中加入 450 重力后测试一下。我们会看到它与帧动画中加入重力 0.5 的效
果是相同的。使用这种技术的一个技巧是将帧频设置得非常高,如 100。虽然没有机器能够
与真正的帧频相吻合,但是基于时间的动画将保证每个人看到的影片运行得都是最流畅的。
同质量物体的碰撞
发生碰撞时,我们实现起来可以更简单一些。基本原理是,两个物体沿着碰撞的线路交换它
们的速度。同时还要用坐标旋转来决定碰撞的线路,以及物体的速度,这样就摆脱了复杂的
动量守恒公式。来看看它是如何工作的,让我们回到文件 MultiBilliard2.as 中,将用它作为
下一个例子 SameMass.as 的基础。我就不再列出原先所有的代码了,因为它实在是一个很
大的文件。但是,我们要来看一下创建所有小球的 for 循环:
for(var i:uint = 0; i < numBalls; i++) {
var radius:Number = Math.random() * 50 + 20;
}
对于新的文件来说,要把粗体字的部分改为这一行:
让所有小球大小都相同,消除了质量的概念,相当于给它们相同的质量。
接下来,看一下 checkCollision 函数。请找到这一部分:
// 旋转 ball0 的速度
var vel0:Point = rotate(ball0.vx,
ball0.vy,
sin,
cos,
true);
// 旋转 ball1 的速度
var vel1:Point = rotate(ball1.vx,
ball1.vy,
sin,
cos,
true);
// 碰撞反应
var vxTotal:Number = vel0.x - vel1.x;
vel0.x = ((ball0.mass - ball1.mass) * vel0.x +
2 * ball1.mass * vel1.x) /
(ball0.mass + ball1.mass);
vel1.x = vxTotal + vel0.x;
这一部分找出了碰撞线路上的速度,根据物体的质量求出碰撞的结果。“碰撞反应”部分是
动量守恒的要素,这就是我们可以消除的部分。我们可以让 vel0 和 vel1 进行交换,就可
以很容易地替换它了。整个代码段如下:
// 旋转 ball0 的速度
var vel0:Point = rotate(ball0.vx,
ball0.vy,
sin,
cos,
true);
// 旋转 ball1 的速度
var vel1:Point = rotate(ball1.vx,
ball1.vy,
sin,
cos,
true);
// 交换两个速度
var temp:Point = vel0;
vel0 = vel1;
vel1 = temp;
这里甚至还可以再优化, 但是为了代码的清晰我就不做改变了。现在我们已经摆脱了一小块
儿数学问题,测试一下修改前与修改后的文件,所得的结果是相同的。