最近导师布置了一个任务:做一个与刚体运动有关的赛车类小游戏。
遂开始翻看《Foundation AS3.0 Animation》
草草阅览了一下,发现无非还是那些物理公式。
很快写了一个小程序来进行测试。
首先想到,可以把汽车看成一个整体,阻力简单处理为摩擦力。
那么,需要用到以下的物理知识:
汽车发动机功率恒定 P = F * v
牛顿力学公式 a = F / m
动摩擦力始终与物体运动方向相反汽车最终可以保持恒定的速度 v_max = P / f ,其中f为阻力
之后就牵扯到了阻力问题,假设除了地面给的摩擦力之外没有其它阻力,则 f = miu * m * g,其中miu为摩擦系数
做用户键盘输入的处理时,想起了很久以前玩的一个匿名作者做出来的不入流的小游戏。在这个小游戏中,用户每按一次键就可以让物体动一次,结果导致按键快的就跑得快,非常影响游戏平衡性。
于是,在这里我采取了一种经典模式——监听 KEY_DOWN 和 KEY_UP 事件,在 KEY_DOWN 时设置对应标记位,在 KEY_UP 时取消标志位,在 onEnterFrame 时根据标志位的不同给予相应处理。
这种置标记位后处理的模式有一个明显的好处:用户的连续快速多次按键不会对游戏产生影响。
当用户按下"↑"、"←"、"→"键的时候,汽车发动机将提供牵引力,使其速度发生改变。
对用户按"↓"键的处理,我一开始犯了一个小错误:为汽车发动机提供了一个与运动方向相反的力。这就导致当汽车静止的时候用户按下这个键,汽车将会发生很囧的往复颤抖。之后突然顿悟(果然是很久没碰物理了,脑袋都钝了)——刹车的原理应该是提高摩擦力… 于是,当downKey标志位为true时,简单增大摩擦力就可以了…
于是,onEnterFrame逻辑大概是这样子的:
1、如果速度不为0的话,计算摩擦力(如果用户按了刹车键,摩擦系数将增大)
2、判断用户按键方向(左,左前,前,右前,右),计算牵引力的角度rad
3、计算牵引力,即
F_x = Math.cos(rad) * P / |v|
F_y = Math.sin(rad) * P / |v|
4、计算合力,计算加速度
5、根据加速度改变速度
6、根据速度改变汽车的位置
使用这样的逻辑在用户体验上还是有很大的问题的,主要表现在:
1、用户的向左向右的操作在汽车上反应得很慢,因为其直接影响的是汽车的加速度而不是速度。这种迟滞性在拐弯时特别明显,非常损伤用户体验。
2、用户在汽车静止时按下左、右键,汽车会有剧烈抖动(rotation有剧烈改变)。
针对问题2,在逻辑中加入静止拐弯逻辑即可。
针对问题1,看来是需要分析一下汽车的运动过程了:如果把汽车看做一个整体的话,拐弯过程显然会失实。但如果不看成一个整体的话,需要考虑的各种力都很多,设计和计算都有可能相当复杂,计算过程可能会占用大量CPU资源。
因此考虑将运动过程简化:
用户按下"→"、"←"键的时候,只改变物体的朝向;
用户按下"↑"键的时候,汽车提供在运动方向上的牵引力;
用户按下"↓”键的时候,阻力增大.
由于此种运动处理已然事实,加入过多物理计算会显得纠缠不清,故考虑简化参量,将原先设置的物体质量等一系列物理参数全部修改掉。取出对所谓“力”等一系列“物理量”的考虑,直接以加速度为参量进行计算。之前的计算中由于存在非物体运动方向上的力,因此需要用二维矢量来计算。修改逻辑后,平面中不存在非rotation方向的外力了,因此我们可以将其简化为一维浮点数。
根据上述思路,onEnterFrame逻辑更改为:
1、总加速度置0。
2、如果速度不为0的话,将摩擦力产生的负加速度累加至总加速度(要考虑用户有没有按下"↓”)。
3、如果用户按下"↑",则将运动方向牵引力产生的加速度累加至总加速度。
4、如果用户按下了"→"、"←",适当调整物体的rotation
5、根据加速度改变速度
6、根据速度和rotation改变汽车的位置
其中,阻力是与速度成正相关的,至于具体公式这个尚需推敲。
简单起见,认为阻力与速度成正比。
各种参数都需要仔细斟酌,经过数次调优,最终的程序代码如下:
package {
import flash.display.Shape;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.KeyboardEvent;
public class RaceCar extends Sprite
{
public var v:Number;
public function RaceCar()
{
super();
var theShape:Shape = new Shape();
theShape.graphics.beginFill(0x000000);
theShape.graphics.moveTo(40,0);
theShape.graphics.lineTo(-40,20);
theShape.graphics.lineTo(-40,-20);
theShape.graphics.lineTo(40,0);
theShape.graphics.endFill();
addChild(theShape);
v = 0;
}
}
public class MotionTest extends Sprite
{
private var raceCar:RaceCar;
private var bg:Shape;
private var upKey:Boolean;
private var downKey:Boolean;
private var leftKey:Boolean;
private var rightKey:Boolean;
private const a_f_mul:Number = 0.1;
private const a_F:Number = 3;
public function MotionTest()
{
bg = new Shape();
bg.graphics.beginFill(0xffffff);
bg.graphics.drawRect(0,0,800,600);
bg.graphics.endFill();
addChild(bg);
raceCar = new RaceCar();
raceCar.x = 400;
raceCar.y = 300;
addChild(raceCar);
stage.addEventListener(KeyboardEvent.KEY_DOWN,onKeyDown);
stage.addEventListener(KeyboardEvent.KEY_UP,onKeyUp);
stage.addEventListener(Event.ENTER_FRAME,onEnterFrame);
}
private function onKeyDown(e:KeyboardEvent):void
{
switch(e.keyCode)
{
case 38:
upKey = true;
break;
case 40:
downKey = true;
break;
case 37:
leftKey = true;
break;
case 39:
rightKey = true;
break;
}
}
private function onKeyUp(e:KeyboardEvent):void
{
switch(e.keyCode)
{
case 38:
upKey = false;
break;
case 40:
downKey = false;
break;
case 37:
leftKey = false;
break;
case 39:
rightKey = false;
break;
}
}
private function onEnterFrame(e:Event):void
{
var a_sum:Number = 0;
if(raceCar.v != 0)
{
a_sum -= (downKey)? a_f_mul * raceCar.v * 10 : a_f_mul * raceCar.v;
}
if(upKey) a_sum += a_F;
if(leftKey && !rightKey) raceCar.rotation -= 80 / (10 + raceCar.v) ;
if(rightKey && !leftKey) raceCar.rotation += 80 / (10 + raceCar.v) ;
raceCar.v += a_sum;
if(raceCar.v < 0.1) raceCar.v = 0;
var rad:Number = raceCar.rotation * Math.PI / 180;
raceCar.x += raceCar.v * Math.cos(rad);
raceCar.y += raceCar.v * Math.sin(rad);
if(raceCar.x > 800) raceCar.x -= 800;
if(raceCar.x < 0) raceCar.x += 800;
if(raceCar.y > 600) raceCar.y -= 600;
if(raceCar.y < 0) raceCar.y += 600;
}
}
}
分享到:
相关推荐
在编程领域,模拟物体运动状态是一项常见的任务,特别是在游戏开发、物理模拟软件和科学计算中。这个压缩包文件包含了多个与物体运动模型相关的图形界面(GUI)和源代码,主要涉及圆周运动、匀速直线运动、阶跃运动...
这个压缩包文件的标题和描述暗示了其中包含的资源与目标检测技术相关,特别是针对运动物体的检测。这可能是为了帮助开发者或者研究人员理解如何通过编程实现这一功能,并且提供了实际可运行的代码和示例视频。 在...
基于双目视觉的运动物体检测系统研究
从这些文件中,学习者可以探索和研究如何在Flash中创建和控制小物体的运动,包括但不限于以下知识点: 1. **ActionScript编程**:Flash中的动画可以通过ActionScript进行编程控制,这是一门基于ECMAScript的脚本...
2. **光流分析**:光流是描述图像序列中像素运动的估计量,可以提供物体运动的信息。通过计算相邻帧间的光流,可以识别出运动物体。光流法通常基于亮度恒定假设和空间一致性假设,如Lucas-Kanade方法。 3. **帧间差...
4. **后处理**:去除噪声,例如通过膨胀、腐蚀等形态学操作连接小的运动区域。 5. **结果可视化**:将运动物体用特定颜色标记在原始视频帧上,然后显示或保存结果。 理解并掌握这些概念和技术对于进行实际的运动...
Aforge.NET是一个开源框架,专为C#开发者设计,提供了丰富的计算机视觉和图像处理功能,包括运动物体识别。这个库的出现,使得开发者无需深入理解底层算法,就能在C#项目中实现复杂的图像分析和处理任务。Aforge库...
基于视频的运动物体检测与提取方法研究,硕士生论文,代码实现
此外,研究还提出了一种无需重新标定即可在摄像头运动的情况下实现运动物体测距的算法。为了实现运动物体的辨识与跟踪,采用了自适应背景建模法与CamShift算法。 #### 关键技术与方法 1. **双目视觉系统**:双目...
总的来说,这是一个专门解决运动物体追击问题的软件,通过GUI界面提供了一种直观、易于操作的方式来分析和预测物体间的追击行为,对于学习、教学和研究这类问题非常有帮助。用户可以利用这个工具进行各种假设和实验...
本项目"运动物体检测_C#运动_lungsa3n_运动物体检测_"是使用C#编程语言实现的,旨在帮助开发者和研究人员理解并应用这项技术。C#是一种广泛用于开发Windows平台应用程序的面向对象的编程语言,它提供了丰富的库和API...
在计算机视觉领域,物体运动检测是一项关键任务,用于识别视频序列中的动态对象。混合高斯模型(GMM,Gaussian Mixture Model)是这一领域的常用技术之一,它结合了高斯分布的灵活性和概率建模的优势,能有效地处理...
### 基于OpenCV的运动物体跟踪系统的设计与实现 #### 一、引言 在计算机视觉领域中,运动物体的跟踪是一项重要的技术,它不仅对于智能视频监控至关重要,还在基于目标的视频编码、人机交互以及自主导航等多个方面...
物体的平抛运动是物理学中的一个基础概念,主要研究在重力作用下,物体被水平抛出后的运动轨迹和状态。这种运动模式广泛应用于各种实际情境,如体育比赛中的投掷项目、航空航天中的发射过程等。平抛运动是匀加速直线...