翻译文章,原文看这里
该文章中的一些信息将会帮助你模拟一些跳跃和移动。
这个文档的目的是理解自然中的物理现象并将他们应用到你的游戏当中。这不会给你的程序有什么最优化的方案,因为这是你的事情!但是你可以理解这到底是怎么回事。
基本概念
为了保证我所讲的东西的一致性,有一些关键的术语我需要定义一下:
距离:运动的总的长度。
位移:起始点和终点的差值。
速率:移动的距离除以移动时间。
速度:运动的方向和运动的速率。
加速度:移动的速度除以移动的时间。
注意:位移,速度,和加速度是都是向量。(具有方向和大小的量)。
缩写:
a:加速度
M:质量
s:位移
s0:初始点。
t:时间
v:速度
v0:初始速度
单位:
m:米(长度单位)
m/s:米每秒(速度单位)
m/s^2:米每秒的平方(加速度单位)
N:牛顿(重力单位)
s:秒(时间单位)
概念:
想象一下一个太空船以1000m/s的速度穿越太空。它深陷一个没有任何东西的星际空间中。有什么力作用于它呢?回答是:什么都没有!
它会永远以1000m/s的速度飞行下去。
对象改变速度的唯一原因是有力作用于它。你会问那是什么力呢?是一个外部的推力或者拉力。力也是一个向量。它具有大小和方向。现在就有一个重力作用于你:它拉动你到地球的中心。
同样的,一个对象改变了位置就是因为它具有一些速度。
假设上帝之手开始推动那个飞船,有一个力施加到了飞船上,任何力的施加都会引发加速度。速度开始增长。如果上帝没有停止推动,不久飞船将会飞行的越来越快。
瞧!我只是想让我的人物跳跃
假设现在我们有一个跳跃人物Joe,Joe的初始位置是在一个地面或者一个平台上。用户按键后,Joe应该跳到空中。对于Joe,你需要明白三件事情:他的位置,速度和加速度。
开始,他的位置在地面上,一旦按键被触发,我们给Joe一个向上的很快的速度。然后每一帧/秒/通过一个相反的数值更新他向上的速度。
decrease是一个方向向下的加速度。它的水平的方向是没有影响的。所以当Joe在空中的时候,你可以改变它的前后移动。
注意:在实际生活中,当我们跳跃的时候是有可能前后移动的。但是我发现允许前后移动的游戏在跳跃的时候却不能前后移动了,只能竖直的跳跃,这样的游戏是不尊重实际的。
什么情况下我们才能够加入加速度呢?在地球上,Joe的垂直方向的加速度是9.81m/s^2。不幸的是米/秒的单位对于电脑来说是没有意义的。加速度是由你的游戏的帧更新来决定的。最好的方法就是来推测它。
以下为实现的伪代码:
Joe.pos.y = 0; (Or wherever floor is) Joe.vel.y = 0; Joe.accel = 10; Joe.jumping = NO; Loop If (jump key is pressed) { Joe.vel.y = 100; Joe.jumping = YES; } if (Joe.jumping == YES) /* Move Joe if we are jumping */ { Joe.vel.y = Joe.vel.y - Joe.accel Joe.pos.y = Joe.pos.y + Joe.vel.y } if (Joe.pos.y <= 0) /* Check to see if Joe has hit floor */ { Joe.vel.y = 0; Joe.jumping = NO; } End Loop |
第一次按跳跃键,Joe将会突然的跳离地面。
随着逐渐的升高,Joe开始因为速度的逐渐的损耗而慢下来。Joe最终会停止上升,开始下降。它会下降的越来越快直到到达地面。
Joe在Y方向上的速度和位置在每次循环的结尾出现,如下面的数据:
Loop0 : Joe.vel.y = 0 Joe.pos.y = 0 Loop1 : Joe.vel.y = 100 Joe.pos.y = 100 Loop2 : Joe.vel.y = 90 Joe.pos.y = 190 Loop3 : Joe.vel.y = 80 Joe.pos.y = 270 Loop4 : Joe.vel.y = 70 Joe.pos.y = 340 Loop5 : Joe.vel.y = 60 Joe.pos.y = 400 Loop6 : Joe.vel.y = 50 Joe.pos.y = 450 Loop7 : Joe.vel.y = 40 Joe.pos.y = 490 Loop8 : Joe.vel.y = 30 Joe.pos.y = 520 Loop9 : Joe.vel.y = 20 Joe.pos.y = 540 Loop10: Joe.vel.y = 10 Joe.pos.y = 550 Loop11: Joe.vel.y = 0 Joe.pos.y = 550 Loop12: Joe.vel.y = -10 Joe.pos.y = 540 Loop13: Joe.vel.y = -20 Joe.pos.y = 520 Loop14: Joe.vel.y = -30 Joe.pos.y = 490 Loop15: Joe.vel.y = -40 Joe.pos.y = 450 Loop16: Joe.vel.y = -50 Joe.pos.y = 400 Loop17: Joe.vel.y = -60 Joe.pos.y = 340 Loop18: Joe.vel.y = -70 Joe.pos.y = 270 Loop19: Joe.vel.y = -80 Joe.pos.y = 190 Loop20: Joe.vel.y = -90 Joe.pos.y = 100 Loop21: Joe.vel.y =-100 Joe.pos.y = 0 |
注意,Joe碰到地面的速度是很快的,如果Joe没有碰到地面,或者是地面消失了(例如:他跳离了平台),Joe将会下降的非常快。
我们需要给他一个限制速度。这就是Joe所能够下落的最快速度。在实际中,这可能是空气的阻力来影响:
Joe.pos.y = 0; (Or wherever floor is) Joe.vel.y = 0; Joe.accel = 10; Joe.jumping = NO; Loop if (jump key is pressed) { Joe.vel.y = 100; Joe.jumping = YES; } if (Joe.jumping == YES) /* Move Joe if we are jumping */ { if (Joe.vel.y > -100) /* Limit Joe's velocity to -100 */ { Joe.vel.y = Joe.vel.y - Joe.accel Joe.pos.y = Joe.pos.y + Joe.vel.y } } if (Joe.pos.y <= 0) /* Check to see if Joe has hit floor */ { Joe.vel.y = 0; Joe.jumping = NO; } End Loop |
添加到循环当中不会降低Joe的速度。它始终以<-100的速度下降。
其他的方向
对于上面的例子已经很好了,但是对于一个好的人物来讲不只是会上下跳跃。还能够在跳跃的时候来回的走。因为x和y的值在加速度产生的时候是不受约束的,所以当你解决了Joe的y方向上的速度,你也可以移动他的x方向。
现在看来Joe是沿着一个他在真实世界中的路径行走。对于3D空间来讲,他的处理方式同y方向上都是一致的。
装备太空人
运动学应用的另一个例子是星际类型的游戏。你在一个原点的环境中飞行,但是能够向任何的方向冲刺。
在这里,重力没有体现出来,那我们用什么来代替呢?我们使用飞船的冲刺作为加速度。我们可以把加速度的向量分解到x和y方向上,然后再利用上面的方法来制作。
以下是伪代码:
pos.x = 0; pos.y = 0; vel.x = 0; vel.y = 0; acc.x = 0; acc.y = 0; Loop if (thrust key pressed) { resolve_direction_vector; acc.x = scale_x * 10; acc.y = scale_y * 10; } vel.x = vel.x + acc.x; vel.y = vel.y + acc.y; pos.x = pos.x + vel.x; pos.y = pos.y + vel.y; End Loop |