Skip to content

Tag Archives: vertors for flash

Flash向量-4-速度和加速度

2009-08-30

使用向量来移动

希望你在阅读本节之前,已经阅读了之前的基本章节。此刻,你应该已经知道什么是点,什么是向量,和如何计算向量的各种属性。并且你一直在等待能够亲自动手在一些真实的游戏中使用向量。让我们开始研究下如何使用向量来移动物体。

在这个例子中,红色的点就是我们的对象。通过方向键,你可以改变运动向量的x,y分量。

首先,我们定义一个对象:

myOb={};
myOb.p0={x:100, y:150};
myOb.vx=3;
myOb.vy=1;

对象的起点是x=100,y=150,移动向量的值是vx=3,vy=1。对象的新位置是向量的终点p1,它是在函数updateVector中进行计算的。如果你已经不记得如何查找p1的值,可以在Flash向量-基础知识章节中查找。

在MovieClip正确的放置了以后,我们会把终点p1作为在drawAll 函数中再一次计算位置时的起点。

每次按下方向键,x,y的分量就会增或者减。函数getKeys和releaseKeys处理这一逻辑。主函数runMe在每一帧都会执行,并且它会调用updateVector和drawAll函数来计算新位置并对mc进行定位。并且在这个例子中,你会发现,当对象移出舞台的时候,会重新出现到舞台的另外一边。

记住在进行计算的过程中,永远不要使用MovieClip的_x,_y属性,它应该是在计算过程完成以后,最后一步讲MovieClip放置到正确的位置。

帧还是时间
我们看下函数updateVector是如何找到结束点p1的新坐标的:

var thisTime=getTimer();
var time=(thisTime-v.lastTime)/100;
v.p1={};
v.p1.x=v.p0.x+v.vx*time;
v.p1.y=v.p0.y+v.vy*time;
v.lastTime=thisTime;

Flash是基于帧的程序,它会尽量以帧频的速度来执行所有的动画和脚本。在enterframe里面来处理所有的计算是很常见的,但这事实上并不是很好的方式。假设你写的代码是每一帧让对象的x坐标增加1。如果你将帧频设置为20,那么代码在每一帧里面会执行20次,从而使得对象每一帧移动20的像素。

你大概就是这样想的吧。但事实上,没有flash可以准确的按照帧频来执行。帧频只是flash想达到的最大值,但是通常都做不到。在浏览器中运行的flash比较吃力,因为浏览器本身占用一些cpu,有些计算机本身就比较慢,人们也可能有其他的程序在运行,所有的这些原因都会导致帧频下降20-25%。

“真的是这样吗?”,你可能在怀疑。它还在运行啊,坐标也会计算,MovieClip的位置也会改变的啊。是的,但是你已经失去了对你的游戏的控制了。你无法确保在一段时间之后,MovieClip位置在哪里,它的运动速度如何。如果你的flash是设计成用来测试人们的反应速度的,如果帧频下降50%,那么低帧频的人玩就比正常帧频下玩的人有巨大的优势。这是flash游戏的一种常见作弊方法,你可以很容易的降低帧频,并取得游戏胜利。

解决的办法是不要将计算基于帧数,而是实际的时间。在基于帧的游戏里面,声明速度vx=3意味着MovieClip每次能够执行的时候都会移动3个像素。在基于时间的游戏里面声明速度vx=3意味着MovieClip每秒钟移动3个像素。在基于时间的游戏里面,帧速的下降不会导致不可预知的结果,你仍然可以准确的知道MovieClip在哪里,不论是1秒钟之后,10秒钟之后或者1个小时之后。较慢的帧速在基于时间的影片里面会影响移动的平滑,对象在舞台上被绘制的次数,在每秒钟内会减少,从而导致“跳帧”,但是每一次绘制的时候,它将绘制到准确的位置。

我们使用getTimer函数来计算时间:

var thisTime=getTimer();
var time=(thisTime-v.lastTime)/100;

getTimer函数返回影片从开始到现在的毫秒数。在运动计算的时候,我们需要知道距离上一次计算的时间,所以我们用当前的时间减去上一次的时间。并且因为时间是用毫秒来计算的,我们需要将它除以100来得到秒。当然,你也可以使用 像素/毫秒 作为速度向量的单位,但是注意得出的值将非常的小。

终点的新坐标要根据逝去的时间来计算:

v.p1.x=v.p0.x+v.vx*time;

让我们来试一下到底对不对。加入我们的MovieClip在x=150,y=10的位置,速度为vx=1,如果帧速设置为20,时间间隔的变化,不管是5毫秒还是50毫秒。例如,假设是5毫秒,意味着每次移动的距离为v.p1.x=v.p0.x+0.05,1秒钟内移动20次,移动距离20*0.05=1 像素。也恰恰符合速度v1。再看看假设时间间隔50的情况,MovieClip每秒钟会在舞台上绘制2次,最后的位置是2*0.5=1像素。

你可以下载fla源文件。

加速度

就像速度向量能随着时间改变物体的位置一样,加速度向量可以随着时间改变物体的速度。

我们先将物体的加速度设置为0:

myOb.ax=0;
myOb.ay=0;

之后,当方向键被按下的时候,我们就改变加速度向量的x,y分量。在update函数里,我们会把加速度向量,添加到速度向量。使用加速度的时候要小心,如果你不限制速度的话,它会不断的增加下去。

v.vx=v.vx+v.ax;
v.vy=v.vy+v.ay;

同样要注意,要想完全停止物体的移动,我们不仅要将速度向量设置为0,还应该将加速度设置为0,否则物体是不会停下来的。

你可以下载fla源文件。

Flash向量-3-加法和投影

2009-08-30

基础。处理多个向量。
1个单独的向量,在很多的时候,让你觉得已经足够的智能和强大,去应付这个世界上的各种问题。然而事实上,你很少只需要1个向量,通常,你需要使用2个,3个甚至更多的向量。所以管理多个向量是非常重要的,否则它们会脱离你的控制,要知道和一个失控的向量战斗不是一件好玩的事情。

首先,多数情况下,有多个向量影响物体。一个例子就是重力:当物体本身在移动(用一个向量表示),而重力会把物体往下拉。重力和其他的力一样,可以用一个向量来表示。此时就有2个向量,你需要找到2个向量的综合效果,以确定物体到底该怎么移动。为了将2个向量加起来,你需要把他们的分量加起来:

resultv={};
resultv.vx=v1.vx+v2.vx;
resultv.vy=v1.vy+v2.vy;

如果你有更多的向量,你可以用同样的办法,把它们都加起来。

向量的投影。

有时候我们非常需要知道2个向量的方向关系,他们到底是把我们的物体往同一个方向牵引,还是一东一西呢。

dp = v1.vx*v2.vx + v1.vy*v2.vy;

我们将2个向量的x分量相乘,y分量相乘,然后在相加。得到结果dp,称为“向量v1和向量v2的点乘”。dp并不是一个向量,而是一个数字,如果是正数,那么2个向量的方向是相同的(夹角小于90度),如果是负数,那么2个向量的方向是相反的(夹角大于90度)。

下面说下2个向量的投影问题。将向量在其他任意的坐标系(向量v2和它的法线构成了一个坐标系)里面进行转换是非常有用的,这样投影的分量就可以单独变化。计算v1在v2上的投影的办法是:

proj.vx=dp*v2.dx;
proj.vy=dp*v2.dy;

向量的投影也是一个向量。我们先计算出2个向量的点乘,再乘以向量v2的归一化向量,就得到了投影。

以下是我制作的一个关于投影向量的例子。你可以四处拖动那些点,以观察投影分量的变化:

黑线是向量v1,蓝线是向量v2以及它的法线,绿线和红线分别是v1在v2和v2的法线上的投影。你可以下载fla源文件。

Flash向量-2-长度和法线

2009-08-30

基础。向量有什么?

对于每个向量来说,它已经拥有2个点和x,y方向分量,这似乎足以让它感到满足和快乐,但是,它还有更多有用的属性哦。每个向量都有长度,长度其实是向量的起点与终点之间的距离。因为我们已经知道向量的x,y方向的分量,我们可以很容易的计算出它的长度:

v.len=Math.sqrt(v.vx*v.vx+v.vy*v.vy);

这其实就是勾股定理【中国称为勾股定理,于公元前1000年发现。国外称为毕达哥拉斯定理,于公元前500年发现。】x分量的平方,加y分量的平方,再取平方根。

使用向量的一个好处是,你不需要使用角度或者sin等复杂的三角函数。但是,我知道很多人是喜欢角度的,我们需要能将向量转化成 角度/长度 的形式。幸运的是,这个操作还不是很麻烦:
(是的,到目前为止,所有的东西还不是很麻烦)

angle=Math.atan2(v.vy, v.vx)

你可能知道,flash比较喜欢用弧度来衡量角的大小,所以如果你想让影片剪辑总是朝着运动矢量的方向前进,您需要将弧度(radians )转换成度(degrees)。

angledeg=angle*180/Math.PI;

有时候,你知道角度和长度,要通过这些来计算向量,你可能不知道怎么办。不用担心,你很快就可以学会,它实际上不是非常的复杂(注意:这次我没有用“简单”这个词):

v.vx=v.len*Math.cos(angle);
v.vy=v.len*Math.sin(angle);

基础。什么是向量的归一化。
【注:原作者虽然用英文写作,但把normal这个单词,理解为“正常”,这是应该是不对的,在数学中,称为“归一化”。】
每个向量都可以被归一化,长度为1的向量,称为归一化向量。

v.dx=v.vx/v.len;
v.dy=v.vy/v.len;

将x,y分量除以向量的长度,我们得到了单位向量。和普通的向量一样,归一化的向量也可以分解为x和y方向的分量。单位向量的长度为1,这一点你可以测试一下。真的,你可以用勾股定理来计算dx,dy对应的向量长度。如果你懒于测试,而直接相信我说的,那当然更好。归一化的向量只告诉了我们方向信息,而不包含距离信息。就好比当你跟人家说:“地铁站往这走”,这句话包含了方向信息,但是没有包含有多远的信息。

做除法的时候一定要小心,不要除以0。向量的长度可以为0,而且为0的时候仍然是一个向量,但是没有办法归一化,所以向量做归一化操作时,一定要检查向量的长度是否为0。在flash中,除以0,返回的将是“Infinity”。

向量有“法线”。法线是指与向量垂直的向量。如果你还记得角度的话,那么法线就是将向量旋转90度。因为向量是有方向的,所以法线就会有2条,分别称为左法线和右法线。假如你起身站起来(我知道其实你现在正坐着在阅读文章,你可能想坐下来,但偶尔站起来一下有利于身体健康),你面向的方向有一个向量。然后,你向2边展开双手,此时你的左右手就好比左右法线。

右法线和左法线这样计算:

v.rx = -v.vy;
v.ry = v.vx;
v.lx = v.vy;
v.ly = -v.vx;

最后,我制作了一个小的flash,你可以到处拖动那个点,然后观察向量的变化。

黑色是向量,蓝色是单位向量,绿色是右法线,红色是左法线。你可以下载fla源文件。

Flash向量-1-点和向量

2009-08-29

基础。向量从哪儿来?

如果您曾经试着开发过一些游戏,那么很可能你已经尝试过放置和移动舞台上的MovieClip。那么您肯定知道每个影片剪辑有2个坐标:x和y。因此,可以这样来定义舞台上的每一个点:

p={x:10, y:5};

非常好,仅仅用这一行代码,我们就声明并且创建了一个对象“p”,而且,我们还赋予了它2个属性,“x”和“y”。现在你就可以根据需要,随时访问它的属性,如:

p.x
p.y

之后,就会得到,点对象p的x属性为10,y属性为5。然后,你就可以构建一个MovieClip,并把MovieClip放置到这个坐标。当然,您不一定要构建并放置MovieClip,即便没有MovieClip,所有的数学逻辑仍然可以正常工作,我们只是用MovieClip来说明问题罢了。不过,通常在真正的游戏中,还是得有点东西在舞台上移动的,否则会是一个编码非常好,但玩起来很沉闷的游戏。

一定要注意:Flash使用的Y坐标方向是反的,在大多数人的宇宙观里面,Y坐标的正方向是抬头向上,但Flash偏偏喜欢低头向下:)

之前,我们已经创建了1个点对象,我们可以看到它可以在舞台上。现在,是时候做点有难度的东西了,我们创建2个点对象:

p0={x:10, y:5};
p1={x:12, y:6};

或许你还没有发现,其实你已经构建了你的第一个向量。不要觉得不好意思哦,对于任何人来说,他们都可能在不知不觉中构建了向量。向量,正如你所看到的,可以用2个点来构建。点p0称为起点,点p1称为终点。正如我们所感知的一样,向量是有方向的,向量p0->p1和向量p1->p0是不一样的,它们很相似,他们有同样的长度和同样的点,但是它们的方向相反。这样,一个形式比较良好的向量声明方式就光荣诞生了:

v={
p0:{x:10, y:5},
p1:{x:12, y:6}
};

我们可以用图来表示这个向量和它的点:

现在,你可能在想:“这太容易了”,你也可能在想:“这咖啡的口味很奇怪哦”,但我们还没有结束呢。矢量也可以用起点和方向分量来表示。也许你会想:“等等,终点呢,不要把它忘了哦~”,放心,我们待会儿会需要它的。那么现在,不用终点,我们如何来声明向量呢?

v={
p0:{x:10, y:5},
vx:2,
vy:1
};

看起来有点眼熟吧,他的确和我们先前构建的向量是一摸一样的。起点相同,x方向的分量是2,y方向的分量是1。他的意义是:“从点(10,5)出发,向右走2步,向下走1步”,不要不相信哦,他结束的位置就是p1。事实上,向量的终点,可以根据它的起点和x,y方向的分量计算得出:

v.p1={};
v.p1.x=v.p0.x+v.vx;
v.p1.y=v.p0.y+v.vy;

如果你用的起点和终点的形式来表示向量,也可以这样来计算出x方向和y方向的分量:

v.vx=v.p1.x-v.p0.x;
v.vy=v.p1.y-v.p0.y;

从现在开始,每当谈及向量,我们就会想到它有2个点p0和p1,每个点都有x,y坐标,而向量有x,y分量。

如果你用起点和向量来表示物体的移动,这时候,向量就被赋予了不同的称谓,常见的有:“速率”,“速度”,“运动”,“位移”。不要让这些名字给迷惑了,他们只不过是在x,y方向上移动物体而已。