I am building a teaching platform for teaching basic Physics.
From my experience in Flash development, I have met similar problems before.
The game time is not the same as real world time. In which case, for example, the distance covered by a projectile can be larger or smaller if the computer lags or for whatever reasons.
Here is a screenshot of the said platform. As shown in the screenshot, I am only developing a lesson for teaching the basic s = v * t relation.
Necessary background
The red line marks the position 69.06284 m, our target distance. The time 11.56087 s is a given value.
The user is supposed to input a speed, moving a projectile from 0 m to the right in order to reach the red line within the time given.
The green line marks the position of the projectile when time is up.
I can assure you that I input an accurate speed up to 5 decimal points so there is no human error in this case.
Ignore the yellow rectangle. It is just a UI element.
The screen is 800 pixels wide, and therefore 10 pixels represent 1 meter.
Way to solve the problem
I'm not sure what to do, quite frankly. But I heard from someone that variable time step represents real world time better. However, Farseer, being a physics simulation engine, should be used with fixed time step, isn't it?
Any advice will be greatly appreciated.
EDIT: here in the screenshot, the actual distance covered by the projectile is ~66.3 m, whereas the theoretical distance is 69.1 m. I also notice that if the target distance (currently 69.1 m) is smaller (red line moves a lot more to the left), the error is smaller.
How do I fire a projectile?
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);
}
In the Arrow class, I basically set up Farseer through a CreateBody method:
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);
}
How do I calculate the flight time of projectile?
May be you are curious about the _fireTime = g.SinceGameStart line. SinceGameStart is a getter of the variable _currTime in a GameTemplate. The value of _currTime is updated once every Update(gameTime) call. So if I want to know how long the projectile has been flying, I do this:
time = _currTime - projectile.FireTime