我正在搭建一个教授基础物理的教学平台。
根据我在 Flash 开发方面的经验,我之前也遇到过类似的问题。
游戏时间与现实世界时间不同。在这种情况下,例如,如果计算机滞后或出于其他原因,弹丸所覆盖的距离可能会更大或更小。
这是该平台的屏幕截图。如屏幕截图所示,我只是在开发一个课程来教授基本的 s = v * t 关系。
必要的背景
红线标记位置 69.06284 m,即我们的目标距离。时间 11.56087 秒是给定值。
用户应该输入一个速度,将弹丸从 0 m 向右移动,以便在给定的时间内到达红线。
当时间到时,绿线标记弹丸的位置。
我可以向您保证,我输入了精确到小数点后 5 位的速度,因此在这种情况下不会出现人为错误。
忽略黄色矩形。它只是一个 UI 元素。
屏幕宽 800 像素,因此 10 像素代表 1 米。
解决问题的方法
坦率地说,我不确定该怎么做。但我从某人那里听说可变时间步更能代表真实世界的时间。但是,Farseer 作为物理模拟引擎,应该是固定时间步长使用的吧?
任何建议将不胜感激。
编辑:在屏幕截图中,弹丸覆盖的实际距离约为 66.3 m,而理论距离为 69.1 m。我还注意到,如果目标距离(当前为 69.1 m)更小(红线向左移动更多),则误差更小。
如何发射弹丸?
public override void ShootProjectile(Vector2 start, float angle, float speed) {
GameTemplate g = Game as GameTemplate;
Arrow a = new Arrow(Game, start, this);
a.Initialize();
a.Restitution = 0f;
a.Friction = 0f;
a.LinearVelocity = new Vector2(speed, 0);
Console.WriteLine("Speed: "+a.LinearVelocity.X);
_fireTime = g.SinceGameStarts;
//Console.WriteLine("Fire time: "+_fireTime);
_projectiles.Add(a);
}
在Arrow类中,我基本上是通过一个CreateBody方法来设置Farseer的:
protected override void CreateBody() {
GameTemplate g = Game as GameTemplate;
Vector2 positionInMeters = _initPos / g.MeterInPixels;
float width = 30f / g.MeterInPixels;
float height = 40f / g.MeterInPixels;
_body = BodyFactory.CreateRectangle(g.GameWorld.World, width, height, 1f, positionInMeters);
_body.BodyType = BodyType.Dynamic;
_origin = new Vector2(15f, 40f);
}
如何计算弹丸的飞行时间?
可能您对 _fireTime = g.SinceGameStart 行感到好奇。因为GameStart 是GameTemplate 中变量_currTime 的getter。_currTime 的值在每次 Update(gameTime) 调用时更新一次。所以如果我想知道弹丸飞行了多长时间,我这样做:
time = _currTime - projectile.FireTime