Advertisement

Very Simple Flight Model Help.

Started by March 27, 2002 10:19 AM
5 comments, last by Hybrid 22 years, 10 months ago
Firstly, I should explain what I am aiming for. I am trying make an arcade checkpoint racing game using airplanes. However, they are more like futuristic ''wipeout'' craft and don''t require all the in-depth aerodynamic physics. I am not intending to model gravity or things like lift. They need to have complete freedom of movement and the control method will be similar to flight simulators. As it is arcade, there will be an accelerator (on/off) and a brake (on/off), no variable thrust/throttle. The ship must be able to ''slide'' round corners however, so the ship''s velocity must be independent from the ships orientation. The problem however is the fact I have never done this sort of motion/handling before and am not sure of the correct way to implement it. I have read up a lot on flight dynamics and modelling, but all use different methods and techniques and some are way too complex for this simple handling. So, I think I am nearly there but I need any pointers from any people who have done this stuff before. This is what I have so far... D3DXVECTOR3 shipPosition; D3DXVECTOR3 shipPreviousPosition; D3DXVECTOR3 shipVelocity; float scalarVelocity; // Do I need this??? D3DXQUATERNION shipOrientation; D3DXQUATERNION shipPreviousOrientation; bool acceleratorOn; bool brakeOn; Now if anyone can tell me if this is wrong or not ideal that would be of great help. Is there anything that should be added for my flight model? One of the main things I am having problems with is the maths involved in altering the velocity based on the currentVelocity and shipOrientation. The thing is I don''t think I can simply add a little velocityVector to the current velocity as the velocity will just increase everytime. This is the area I am really stuck on implementing. How would some of you guys store/calculate the velocity of the ship? I know there are people out there that can help. So please do, I''d really appreciate it. Thanks in advance. --- Hybrid ---
Someone must be able to help me? Please...

How would you guys calculate the velocity using quaternions etc. Do I have to use acceleration, which I have read on some flight model sites.

I beg for help!!!
Advertisement
I can give a few hints that may help.

Since you''re not basing this thing on real physics, one approach is to set the orientation of the craft entirely using the game controller or AI system. The shipOrientation remains constant as long as the controller is centered, but if you hold the game controller in one direction, then keep incrementing shipOrientation. The benefit to this approach is you do not have to deal with rotational physics or velocities at all. Just positional physics/velocities, which makes things pretty much trivial.

It probably makes sense for you to implement a "particle" style system, which uses very simple physics to deal with the thrust/accelerator. It does use the standard laws of physics (Newton''s 2nd law of motion) that essentially leads to:

1) acceleration changes velocity
2) velocity changes position

You could add in a simple lift model and gravity to this if you wanted, but you certainly don''t have to.

Actually, the sample code below is an easy way to do it:


  D3DXVECTOR3 shipPosition;D3DXVECTOR3 Ship_X_Dir;float shipSpeed;float fixed_acceleration = 1.;  // acceleration due to thrustfloat fixed_deceleration = -1.; // deceleration due to brakingbool acceleratorOn = false;bool brakeOn = false;// compute the "time step" - the amount of time that passed// since the last update. You could calculate this using timers// or use an average, or use a fixed delta_time. Experiment// until it looks the way you want.delta_time = time_at_this_frame - time_at_previous_frame;// compute the speed of the ship, based on a fixed accelerator// and fixed brakeshipSpeed = 0.0;if (acceleratorOn){  shipSpeed += (fixed_acceleration * delta_time);}if (brakeOn){  shipSpeed -= (fixed_deceleration * delta_time);// NOTE: shipSpeed required to be >= 0 since car-like braking // cannot cause ship to go in reverse. REMOVE this line if you // want to treat braking as exactly like a negative thrust (more// like an airplane or space craft), since a negative thrust can // make the ship accelerate backwards.  if (shipSpeed < 0.) shipSpeed = 0.;}// update the ship position. Note that shipSpeed * Ship_X_Dir is// equal to the velocity.shipPosition += (shipSpeed * Ship_X_Dir) * delta_time;  


So that''s a very simple way to do it. It uses what''s known as explicit Euler integration, which should work fine for your case. The "fixed_acceleration" is just a number that you pick to represent the acceleration that your fixed thrust/accelerator causes. The "fixed_deceleration" represents the deceleration/braking caused by your fixed on/off brake. The Ship_X_Dir is the direction of the craft, front-to-back. You can get this from your quaternion. Its required so that the acceleration/braking are applied in the proper direction.

I''m using shipSpeed (a scalar) instead of shipVelocity (a vector) to make it easier to deal with braking. My logic assumes that acceleration/thrust is always in the positive X direction (towards the front of the ship no matter what orientation) and braking is always towards the rear of the ship (negative X direction). Braking, which I interpret to be like a car brake and not a negative thrust, cannot cause the ship to accelerate backwards. It can only slow the ship to zero speed. So there is some extra logic to deal with this. If you really want your brake to be negative thrust, simply remove that logic.

Note that shipSpeed * Ship_X_Dir is basically the same as your shipVelocity, and it is this product that I use to update position.

I''m assuming you want your acceleration and braking to be along the direction of the ship orientation, which I''ve called Ship_X_Dir. If you want these to act in a different direction, just replace Ship_X_Dir with the desired direction. The logic above doesn''t quite work if you want acceleration/thrust and braking to be in different directions. You could modify the logic to be something like:


  D3DXVECTOR3 Thrust_Dir;D3DXVECTOR3 Braking_Dir;shipSpeed = 0.0;if (acceleratorOn){  shipSpeed = (fixed_acceleration * delta_time);  shipPosition += (shipSpeed * Thrust_Dir) * delta_time;}if (brakeOn){  shipSpeed = (fixed_deceleration * delta_time);  shipPosition += (shipSpeed * Braking_Dir) * delta_time;}  


Hope this helps!

Graham Rhodes
Senior Scientist
Applied Research Associates, Inc.
Graham Rhodes Moderator, Math & Physics forum @ gamedev.net
Thanks for the reply, it certainly gave me new ideas. I''ve been looking over the code you wrote but am still not quite sure it will be able to create the effect I am after - in particular the ''sliding'' of the ship around corners.

This is a typical situation and will hopefully help me explain the effect I am after.

Imagine the ship is flying through the air in a straight line. It has accelerated up to its maximum speed, say 100 mph. I then let go of the accelerator and the ship continues to go in the straight line but starts to slow down gradually over time due to a simple constant decelleration (air resistance?). During this time, I can turn the ship 90 degrees and yet the ship still moves along the same straight line, due to the velocity being unaltered and independent of the ships orientation. However, while the ship is at 90 degrees I then put on the accelerator and it will slowly alter the velocity from the original straight line to the new 90 degree heading. So basically it has inertia, and it will look like the craft will ''slide'' around the corners. I don''t want it so that you just turn the craft, press accelerate and it goes in that direction. I am after the inertia effect - but it''s implementing it that is really confusing me and getting me stuck.

Forgive me if I am wrong about this, but I can''t see how your code will be able to achieve this effect as the ship''s velocity is stored as a separate float, I think that this particular effect requires a vector who''s magnitude is in effect the ship''s speed. That vector can then be altered based on the new orientation - possibly by adding another vector to it??? I''ve never done anything like this before so I may be completely wrong???

Maybe the effect I am after isn''t so simple after all?

Thanks for your help, your answer is exactly the kind I was hoping for, so I really, really appreciate it. Thanks again.
Hi,

You're correct that my first code will not handle the sliding case you mention. My second code is closer, since it allows deceleration/braking to occur in an entirely different direction than thrust, but its still not quite right since I didn't give you a proper way to model drag-like braking.

What you need to do is treat thrust exactly as I did above, but treat the braking force like a viscous drag that is proportional to the velocity. Lets rework the formulation just a bit. I'm going to be working with forces here, rather than just acceleration rates.

Please forgive me, I do not really know the Visual Basic or Dark Basic syntax, so I've written this C++ style!


    D3DXVECTOR3 shipPosition;D3DXVECTOR3 dragForce;D3DXVECTOR3 thrustForce;D3DXVECTOR3 totalForce;D3DXVECTOR3 shipAcceleration;D3DXVECTOR3 shipVelocity;// amount of force (lbs or Newton's) possible with the thruster.// experiment with the value to get the look you want.float thrustMagnitude = 1.;// mass of the ship (slugs or kilograms). experiment with the// number to get the look you want.float shipMass = 1.;// a drag coefficient that scales velocity into a drag force.// again, experiment with the value.float dragCoefficient = 1.;dragForce = 0;   // zero out all the termsthrustForce = 0; // zero out all the termsif (acceleratorOn){  thrustForce = thrustMagnitude * Ship_X_Dir;}if (brakeOn){  dragForce = -shipVelocity * dragCoefficient;}totalForce = thrustForce + dragForce;shipAcceleration = totalForce / shipMass;// integrate to get new velocity. this again is// simple/explicit Euler integrationshipVelocity += shipAcceleration * delta_time;// integrate to get new position this again is// simple/explicit Euler integrationshipPosition += shipVelocity * delta_time;    


You obviously can simplify that code quite a bit, but I wanted to write everything out so you see how things are related. acceleration = force/mass is exactly F = ma, Newton's second law. A = dv/dt is integrated to give the new velocity, shipVelocity. And v = ds/dt is integrated to give the new position. In that order. You do not need to store two copies of velocity or position, so you can discard your shipPreviousPosition variable (as long as you continue to use the simple Euler integration that I've presented).

In a realistic world, with this scenerio where the drag force is proportional to velocity, the braking is always on , and so you don't need the brakeOn flag. However, if you wanted to represent something like air brakes that can be deployed, you may want to keep track of two different drag_coefficients. One that is smaller for the case where the air brakes are stowed, and another one that is larger for the case where the air brakes are deployed.

You'll notice that without the accelerator, the drag force (and therefore acceleration) is reduced in magnitude every frame until the ship comes to rest. There is a potential instability, which I mention at the end.

There is a more realistic drag model, but its a bit more expensive to calculate and may not be that beneficial for somewhat low-speed movement. If your ships can travel at higher speeds, this more realistic drag may make things look better if you can afford the extra calculation. In this model you still have a drag coefficient, but its magnitude will be different (probably smaller) and drag is calculated like:

dragForce = -shipVelocity * DotProduct(shipVelocity, shipVelocity) * drag_coefficient/ Magnitude(shipVelocity); 

Basically, in this case drag still acts along the opposite of the direction of ship velocity [ which is shipVelocity/Magnitude(shipVelocity) ], but the magnitude of drag is the square of the velocity magnitude (speed2 = dotproduct(v,v) = magnitude(v)2) times drag coefficient. This is the drag model used for the preliminary design of real aircraft, and also the one that is used in many flight simulators. (The thing flight simulators do that you may not need to do is to vary the drag coefficient depending on the orientation of the ship with respect to the local wind direction. That is the aerodynamic model that you wanted to avoid. And I think you can easily skip that to get the look and feel you want.)

I want to warn you about something. The drag force in my pseudo-code above is actually sort of like a linear spring, with velocity being like the displacement term in Hooke's Law (F = kx), and drag_coefficient being the stiffness term (k). There is a limitation with simple Euler integration. It actually is unstable for problems that include springs. You may not have a real problem with it since the integration of position and velocity are decoupled. But if you see strange behavior where the system starts to oscillate once the ship is nearly stopped, this could be due to the inherent instability of simple Euler integration. There are more sophisticated ways to integrate, but see how this works first.

Graham Rhodes
Senior Scientist
Applied Research Associates, Inc.

[edited by - grhodes_at_work on March 28, 2002 4:45:39 PM]
Graham Rhodes Moderator, Math & Physics forum @ gamedev.net
Thanks for taking the time to explain all that. It''s certainly helped me get to grips with all the processes involved in implementing it. Going through your code in my head, it certainly seems that it''ll provide the motion I am aiming for.

I think I will have two drag coefficients as you mentioned, so I can allow the player to brake in the game, and possibly I''ll try the more advanced drag formula to see which suits my game the best.

Now all I''ve got to do is get the AI to use this system and test out the results.

Thanks again!
Advertisement
Good luck, and post a reply when you have it working!

Graham Rhodes
Senior Scientist
Applied Research Associates, Inc.
Graham Rhodes Moderator, Math & Physics forum @ gamedev.net

This topic is closed to new replies.

Advertisement