Game Development Community

Wheels on flying vehicles

by Jeff Wilkinson · in Torque Game Engine · 06/03/2004 (8:43 pm) · 15 replies

Most likely this has been asked a thousand times before but I cant find it when I do a search.

Would I be able to just add the wheel nodes to flying vehicles for wheels and then what would I have to do after that just add some script or would it be more in depth into the core code?

#1
06/04/2004 (4:20 am)
LoL try creating a class that is a child of both flying and wheeled vehicles andchange/trash whatever you need
#2
06/04/2004 (9:51 pm)
I have done this... sort of. You have to modify the code. Its probably a better idea to add flying physics to the wheeled vehicles, since the flying vehicles dont fall correctly and the wheels are quite complicated.

Basically what I did was cut out the code for horizontal and vertical 'bite' forces from the flyingvehicle::updateforces method and pasted it into the wheeledvehicle::updateforces method. I modified it so that as you drove faster, more and more of the 'bite' force was applied. Also I added a bunch of script properties for the various flight forces.

...Theres a bit more to it than that but thats where you start. I never got it to work 100% but i got planes that could take off and land pretty well. I lost interest cause the vehicles are so messed up in general.
#3
06/05/2004 (6:02 am)
@Eric, would you share this flying wheeled vehicle code ?

I'm currently developing a plane and take off and land would be very nice.

TIA

Bruno
#4
06/05/2004 (9:29 am)
Ok this is gonna be a monster. Its been a while so i'm not sure if this works with the head.

Part I: add some new properties to the wheeled vehicle.

First add the new properties to our Datablock:
In WheeledVehicle.h, in struct WheeledVehicleData: public VehicleData, under the lines:
>F32 maxWheelSpeed; // Engine torque is scale based on wheel speed
>F32 engineTorque; // Engine force controlled through throttle
>F32 engineBrake; // Break force applied when throttle is 0
>F32 brakeTorque; // Force used when brakeing

Add these:
//FWAR additions for more general vehicles
F32 forwardThrust;
F32 reverseThrust;
F32 lift;
F32 maxFowardVel;
F32 maxReverseVel;	
F32 horizontalSurfaceForce;
F32 verticalSurfaceForce;
F32 rollForce;
F32 yawForce;
F32 pitchForce;
F32 rotationalDrag;
F32 stallSpeed;				//point at which flight stuff stops working

Now connect them to the script system:
in WheeledVehicle.cc, in the function WheeledVehicleData::initPersistFields()
add these lines:
addField("forwardThrust", TypeF32, Offset(forwardThrust, WheeledVehicleData));
addField("reverseThrust", TypeF32, Offset(reverseThrust, WheeledVehicleData));
addField("lift", TypeF32, Offset(lift, WheeledVehicleData));
addField("maxFowardVel", TypeF32, Offset(maxFowardVel, WheeledVehicleData));
addField("maxReverseVel", TypeF32, Offset(maxReverseVel, WheeledVehicleData));
addField("horizontalSurfaceForce", TypeF32, Offset(horizontalSurfaceForce, WheeledVehicleData));
addField("verticalSurfaceForce", TypeF32, Offset(verticalSurfaceForce, WheeledVehicleData));
addField("rollForce", TypeF32, Offset(rollForce, WheeledVehicleData)); //hmm
addField("yawForce", TypeF32, Offset(yawForce, WheeledVehicleData));
addField("pitchForce", TypeF32, Offset(pitchForce, WheeledVehicleData));
addField("rotationalDrag", TypeF32, Offset(rotationalDrag, WheeledVehicleData));
addField("stallSpeed", TypeF32, Offset(stallSpeed, WheeledVehicleData));
#5
06/05/2004 (9:36 am)
Part II: change the code to handle our new properties

in WheeledVehicle.cc, in the function WheeledVehicle::updateForces()
above the line:
>// Sum up spring and wheel torque forces

add all this:

///////////////////////////
  //FWAR force additions...//
  ///////////////////////////
  const MatrixF& mat = getTransform();
	Point3F dir;
	mat.getColumn(1,&dir);
	Point3F forwardVel;

	//fowardvel = projection of linear velocity onto foward vector
	forwardVel = (mDot(dir, mRigid.state.linVelocity)/mDot(dir, dir)) * dir;
	F32 forwardLen = mSqrt(forwardVel.x*forwardVel.x + forwardVel.y*forwardVel.y + forwardVel.z*forwardVel.z);

  if(mThrottle > 0 && forwardLen < mDataBlock->maxFowardVel)
	mRigid.state.force += by * mThrottle * mDataBlock->forwardThrust;
  if(mThrottle < 0 && forwardLen < mDataBlock->maxReverseVel)
	mRigid.state.force += by * mThrottle * mDataBlock->reverseThrust;

	
	mRigid.state.force += bz * mClamp(forwardLen * mDataBlock->lift, 0, 4000);

	// Steering
	Point2F steering;
	steering.x = mSteering.x / mDataBlock->maxSteeringAngle;
	steering.x *= mFabs(steering.x);
	steering.y = mSteering.y / mDataBlock->maxSteeringAngle;
	steering.y *= mFabs(steering.y);
	mRigid.state.torque -= bx * steering.y * mClampF((forwardLen-mDataBlock->stallSpeed)/mDataBlock->maxFowardVel,0,1) * mDataBlock->pitchForce;
	mRigid.state.torque -= bz * steering.x * mClampF((forwardLen-mDataBlock->stallSpeed)/mDataBlock->maxFowardVel,0,1) * mDataBlock->yawForce;

	
	// Roll
	mRigid.state.torque += by * mDelta.move.x * mClampF((forwardLen-mDataBlock->stallSpeed)/mDataBlock->maxFowardVel,0,1) * mDataBlock->rollForce;
	//F32 ar = 15 * mDot(bx,Point3F(0,0,1));
	//ar -= 100 * mDot(bx, mRigid.state.linVelocity);
	//mRigid.state.torque += by * ar;

	// Damping "surfaces"
	F32 speed = mSqrt(mRigid.state.linVelocity.x*mRigid.state.linVelocity.x + 
		mRigid.state.linVelocity.y*mRigid.state.linVelocity.y +
		mRigid.state.linVelocity.z*mRigid.state.linVelocity.z);
	mRigid.state.force -= bx * speed * mDot(bx,mRigid.state.linVelocity) * mDataBlock->horizontalSurfaceForce * mClampF((forwardLen-mDataBlock->stallSpeed)/mDataBlock->maxFowardVel,0,1);
	mRigid.state.force -= bz * speed * mDot(bz,mRigid.state.linVelocity) * mDataBlock->verticalSurfaceForce * mClampF((forwardLen-mDataBlock->stallSpeed)/mDataBlock->maxFowardVel,0,1);

	// Drag at any speed
	//mRigid.state.force  -= mRigid.state.linVelocity * 80;//mDataBlock->minDrag;
	mRigid.state.torque -= mRigid.state.angMomentum * mDataBlock->rotationalDrag;


	

    ///////////////////////////
#6
06/05/2004 (9:45 am)
Part III: Make a data block in script.

Heres my data block for a p51 mustang I made. You'll have to change it to use your own models. Plus you have to make spring and wheel datablocks, but none of that has changed from regular wheeled vehicles.

datablock WheeledVehicleData(p51Land)
{
   category = "Vehicles";
   displayName = " ";
   shapeFile = "~/data/shapes/vehicles/p51Land.dts";
   emap = true;
   nummountpoints = 1;
   minMountDist = 5;

   maxDamage = 800;
   destroyedLevel = 800;

   maxSteeringAngle = 0.785;  // Maximum steering angle, should match animation
   integration = 4;           // Force integration time: TickSec/Rate
   tireEmitter = TireEmitter; // All the tires use the same dust emitter

   // 3rd person camera settings
   cameraRoll = true;         // Roll the camera with the vehicle
   cameraMaxDist = 15;         // Far distance from vehicle
   cameraOffset = 2.5;        // Vertical offset from camera mount point
   cameraLag = 0.0;           // Velocity lag of camera
   cameraDecay = 0.0;        // Decay per sec. rate of velocity lag

   useEyePoint = false;	


	defaultTire	= p51Tire;
	defaultSpring	= p51Spring;
	flatTire	= p51FlatTire;
	flatSpring	= p51FlatSpring;


   // Rigid Body
   mass = 200;
   drag = 0.2;
   bodyFriction = 0.6;
   bodyRestitution = 0.4;
   minImpactSpeed = 5;        // Impacts over this invoke the script callback
   speedDamageScale = 10.0;

   softImpactSpeed = 5;       // Play SoftImpact Sound
   hardImpactSpeed = 15;      // Play HardImpact Sound
   groundImpactMinSpeed    = 5.0;

   // Engine
   engineTorque = 1000; //4000;       // Engine power
   engineBrake = 6000;         // Braking when throttle is 0
   brakeTorque = 0;        // When brakes are applied
   maxWheelSpeed = 60;        // Engine scale by current speed / max speed

   // Energy
   maxEnergy = 100;
   jetForce = 3000;
   minJetEnergy = 30;
   jetEnergyDrain = 2;


   splash = PlayerSplash;
   splashVelocity = 4.0;
   splashAngle = 67.0;
   splashFreqMod = 300.0;
   splashVelEpsilon = 0.60;
   bubbleEmitTime = 0.4;
   splashEmitter[0] = PlayerFoamDropletsEmitter;
   splashEmitter[1] = PlayerFoamEmitter;
   splashEmitter[2] = PlayerBubbleEmitter;
   mediumSplashSoundVelocity = 10.0;   
   hardSplashSoundVelocity = 20.0;   
   exitSplashSoundVelocity = 5.0;


	damageEmitter[0] = p51landSmokeEmitter1;
	damageEmitter[1] = p51landSmokeEmitter2;
	damageEmitter[2] = p51landSmokeEmitter3;
	damageEmitterOffset[0] = "0.0 -3.0 0.0 ";
	damageEmitterOffset[1] = "0.0 -3.0 0.0 ";
	damageLevelTolerance[0] = 0.3;
	damageLevelTolerance[1] = 0.7;
	numDmgEmitterAreas = 3;

   // Sounds
//   jetSound = ScoutThrustSound;
	//engineSound = idleSound;
	//squealSound = skidSound;
	softImpactSound = slowImpactSound;
	hardImpactSound = fastImpactSound;
	wheelImpactSound = clatchSound;

//   explosion = VehicleExplosion;
	justcollided = 0;

	maxinv[p51ammo] = 1000;

	forwardThrust		= 3000;
	reverseThrust		= 2000;
	lift			= 0;
	maxFowardVel		= 70;
	maxReverseVel		= 70;
	horizontalSurfaceForce	= 10;   // Horizontal center "wing" (provides "bite" into the wind for climbing/diving and turning)
	verticalSurfaceForce	= 100; 
	rollForce		= 6000;
	yawForce		= 6000;
	pitchForce		= -4000;
	rotationalDrag		= 2;
	stallSpeed		= 30;
};


'flatTire' and 'flatSpring' are part of a damage system I added, so you wont need those
#7
06/05/2004 (10:08 am)
Thanks Eric !

I'll give it a try ASAP !
#8
06/06/2004 (2:22 pm)
Eric,

I implemented as you specified. I used the racing buggy datablock and added most of your datablock code.

The only change that I actually made was in the c++ code. mRigid doesn't have a state member anymore, but all the submembers where there so I change mRigid.state.force to mRigid.force and so on.

The car now behave differently, it does some super jumps, but I'm not really able to control it.

Any hints ?

If there is something too big for posting that you wish to send me, you may use my email : grieco@matrix.com.br

TIA

Bruno
#9
06/06/2004 (2:48 pm)
Can you control it in the air at all? Try increasing rollForce, yawForce, and pitchForce and decreasing rotationalDrag in the datablock.
#10
06/06/2004 (4:19 pm)
Nope,

didn't work.

here is my Datablocck
datablock WheeledVehicleData(DefaultCar)
{
   category = "Vehicles";
   displayName = " ";
  shapeFile = "~/data/shapes/buggy/buggy.dts";
   emap = true;
   nummountpoints = 1;
   minMountDist = 5;

   maxDamage = 800;
   destroyedLevel = 800;

   maxSteeringAngle = 0.785;  // Maximum steering angle, should match animation
   integration = 4;           // Force integration time: TickSec/Rate
   tireEmitter = TireEmitter; // All the tires use the same dust emitter

   // 3rd person camera settings
   cameraRoll = true;         // Roll the camera with the vehicle
   cameraMaxDist = 15;         // Far distance from vehicle
   cameraOffset = 2.5;        // Vertical offset from camera mount point
   cameraLag = 0.0;           // Velocity lag of camera
   cameraDecay = 0.0;        // Decay per sec. rate of velocity lag

   useEyePoint = false;   


   // Rigid Body
   mass = 200;
   drag = 0.2;
   bodyFriction = 0.6;
   bodyRestitution = 0.4;
   minImpactSpeed = 5;        // Impacts over this invoke the script callback
   speedDamageScale = 10.0;

   softImpactSpeed = 5;       // Play SoftImpact Sound
   hardImpactSpeed = 15;      // Play HardImpact Sound
   groundImpactMinSpeed    = 5.0;

   // Engine
   engineTorque = 1000; //4000;       // Engine power
   engineBrake = 6000;         // Braking when throttle is 0
   brakeTorque = 0;        // When brakes are applied
   maxWheelSpeed = 60;        // Engine scale by current speed / max speed

   // Energy
   maxEnergy = 100;
   jetForce = 3000;
   minJetEnergy = 30;
   jetEnergyDrain = 2;


   // Sounds
//   jetSound = ScoutThrustSound;
   //engineSound = idleSound;
   //squealSound = skidSound;
   softImpactSound = slowImpactSound;
   hardImpactSound = fastImpactSound;
   wheelImpactSound = clatchSound;

//   explosion = VehicleExplosion;
   justcollided = 0;

  // maxinv[p51ammo] = 1000;

   forwardThrust      = 3000;
   reverseThrust      = 2000;
   lift         = 0;
   maxFowardVel      = 70;
   maxReverseVel      = 70;
   horizontalSurfaceForce   = 10;   // Horizontal center "wing" (provides "bite" into the wind for climbing/diving and turning)
   verticalSurfaceForce   = 100; 
   rollForce      = 6000;
   yawForce      = 6000;
   pitchForce      = 4000;
   rotationalDrag      = 2;
   stallSpeed      = 30;
};

Do you see anything strange in it ?
#11
05/17/2005 (10:48 pm)
I've implemented this almost exactly as Eric describes, and it works not-too-bad. Behaves more like a glider than a plane though, for some reason. To fly you need to jump off a bit of a ramp, then work the mouse up and down to give you some altitude.

Thanks Eric, this will give me a good base to work off to develop my own wheeled plane.
#12
05/17/2005 (11:34 pm)
Soooo... nobody can use the sweet new google search?

searched for "wheeled flying vehicle" in the resources
first hit:
http://www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=7405
#13
05/18/2005 (2:48 am)
How do you suppose I found this thread if not with the search? I found that resource a bit later but obviously not with the search strings I used to find this thread.

It's good to have that link here tho.
#14
05/25/2005 (2:16 pm)
Thank you!
#15
11/23/2005 (9:40 am)
Just for the record.....

The WheeledFlyingVehicle resource posted by Josh, was first posted April 3, 2005, where clearly this thread had ended June 6, 2004.

However, it does offere quite a bit of insight into the inner workings between C++ and Torque Script.