Game Development Community

dev|Pro Game Development Curriculum

Dynamic and Individualized Gravity

by Chris "Dark" Evans · 11/23/2001 (9:08 am) · 32 comments

Download Code File

Dynamic and Individualized Gravity:

This mod will let you set the gravity to any object derived from the shapebase class (virtually everything except projectiles). It's set specifically to an object, not the object's datablock. So you could have a player that floats around, and a player that smashes into the ground from a small drop.

I suggest you read this whole tutorial (and all tutorials) before you start on it, just to make sure it doesn't interfere with your previous changes. You wouldn't want to get half way through and find out that it's incompatable with your game, then rip it all out again.



----------------------------------------------------
Part I - In Shapebase.cc:
----------------------------------------------------


Find the function "void ShapeBase::consoleInit()" Scroll down until you see:
------------
Con::addCommand("ShapeBase", "getEyeVector", cGetEyeVector, "obj.getEyeVector()", 2, 2);
Con::addCommand("ShapeBase", "getEyeTransform", cGetEyeTransform, "obj.getEyeTransform()", 2, 2);

Con::addCommand("ShapeBase", "setEnergyLevel", cSetEnergyLevel, "obj.setEnergyLevel(value)", 3, 3);
Con::addCommand("ShapeBase", "getEnergyLevel", cGetEnergyLevel, "obj.getEnergyLevel()", 2, 2);
------------


In the space between insert the following:
------------
Con::addCommand("ShapeBase", "setGravity", cSetGravity, "obj.setGravity(value)", 3, 3);
Con::addCommand("ShapeBase", "getGravity", cGetGravity, "obj.getGravity()", 2, 2);
------------


Like so:
------------
Con::addCommand("ShapeBase", "getEyeVector", cGetEyeVector, "obj.getEyeVector()", 2, 2);
Con::addCommand("ShapeBase", "getEyeTransform", cGetEyeTransform, "obj.getEyeTransform()", 2, 2);

//***New code...
Con::addCommand("ShapeBase", "setGravity", cSetGravity, "obj.setGravity(value)", 3, 3); // <-------
Con::addCommand("ShapeBase", "getGravity", cGetGravity, "obj.getGravity()", 2, 2);// <-----------
//***End new code...

Con::addCommand("ShapeBase", "setEnergyLevel", cSetEnergyLevel, "obj.setEnergyLevel(value)", 3, 3);
Con::addCommand("ShapeBase", "getEnergyLevel", cGetEnergyLevel, "obj.getEnergyLevel()", 2, 2);
------------


I don't think it matters which order you put the commands in, it just helps keep things organized.


Find the function "static const char* cGetEyeTransform(SimObject *ptr, S32, const char **)"

Right underneath it write:
------------
static void cSetGravity(SimObject *ptr, S32, const char **argv)
{
ShapeBase* obj = static_cast(ptr);
obj->setGravity(dAtof(argv[2]));
}

static F32 cGetGravity(SimObject *ptr, S32, const char **)
{
ShapeBase* obj = static_cast(ptr);
return obj->getGravity();
}
------------


Like So:
------------
static const char* cGetEyeTransform(SimObject *ptr, S32, const char **)
{
// ...code...
}

// ***New functions:
static void cSetGravity(SimObject *ptr, S32, const char **argv)
{
ShapeBase* obj = static_cast(ptr);
obj->setGravity(dAtof(argv[2]));
}

static F32 cGetGravity(SimObject *ptr, S32, const char **)
{
ShapeBase* obj = static_cast(ptr);
return obj->getGravity();
}
// ***End new functions.

static void cSetEnergyLevel(SimObject *ptr, S32, const char **argv)
{
// ...code...
}
------------


Find the function "F32 ShapeBase::getEnergyLevel()" and write the following above it:
------------
F32 ShapeBase::getGravity()
{
return mGravity;
}

void ShapeBase::setGravity(F32 gravity)
{
mGravity = gravity;
if(!isGhost())
setMaskBits(GravityMask);
}
------------


Like So (getting repetitive isn't it):
------------
//***New functions
F32 ShapeBase::getGravity()
{
return mGravity;
}

void ShapeBase::setGravity(F32 gravity)
{
mGravity = gravity;
if(!isGhost())
setMaskBits(GravityMask);
}
//***End functions

F32 ShapeBase::getEnergyLevel()
{
// ...code...
}
------------


Find the function:
------------
U32 ShapeBase::packUpdate(NetConnection *con, U32 mask, BitStream *stream)
{
}
------------



Inside it there will a lists of masks similar to this:
------------
if(!stream->writeFlag(mask & (HideNodeMask | SkinMask | MaxSpeedMask | NameMask | DamageMask | SoundMask |
ThreadMask | ImageMask | CloakMask | MountedMask | ShieldMask)))
return retMask;
------------

You'll have to add the GravityMask to that:
------------
if(!stream->writeFlag(mask & (HideNodeMask | SkinMask | MaxSpeedMask | GravityMask | NameMask | DamageMask | SoundMask |
ThreadMask | ImageMask | CloakMask | MountedMask | ShieldMask)))
return retMask;
------------
It doesn't matter where you put it, as long as it's there.


Scroll down a little in the same function until you find another list of masks similar to this:
------------
if (stream->writeFlag(mask & (HideNodeMask | SkinMask | MaxSpeedMask | NameMask | ShieldMask | CloakMask))) {
if (stream->writeFlag(mask & CloakMask)) {
------------

Add GravityMask to that too:
------------
if (stream->writeFlag(mask & (HideNodeMask | SkinMask | MaxSpeedMask | GravityMask | NameMask | ShieldMask | CloakMask))) {
if (stream->writeFlag(mask & CloakMask)) {
------------
Again, it doesn't matter which order you put it in, as long as it's there.

In the same function, scroll down until you find:
------------
if (stream->writeFlag(mask & NameMask)) {
stream->writeInt(mNameTag,NetStringTable::StringIdBitSize);
con->checkString(mNameTag);
}
------------

Either above, or below it add this:
------------
if (stream->writeFlag(mask & GravityMask)) {
stream->write(mGravity);
}
------------

We're finished with packUpdate()



Find the function:
------------
void ShapeBase::unpackUpdate(NetConnection *con, BitStream *stream)
{
}
------------

In that function, find:
------------
if (stream->readFlag()) { // NameMask
mNameTag = stream->readInt(NetStringTable::StringIdBitSize);
checkTagsNeeded = true;
}
------------

Either above or below it add:
------------
if (stream->readFlag()) { // GravityMask
F32 gravity;
stream->read(&gravity);
setGravity(gravity);
}
------------

We're finished with unpackUpdate()



That's the hardest part. Now we have to add the default gravity.

Search for "ShapeBase::ShapeBase()"
Scroll down until you find:
------------
mEnergy = 0;
------------

Right above it write:
------------
mGravity = -20;
------------

Now search for "bool ShapeBase::onNewDataBlock(GameBaseData* dptr)"
Scroll down again until you find:
------------
mEnergy = 0;
------------

Right above it write:
------------
mGravity = -20;
------------


We're finished with shapeBase.cc.


----------------------------------------------------
Part II - In Shapebase.h:
----------------------------------------------------

Search for "enum ShapeBaseMasks {"

Inside it you need to add a Gravity Mask.

So if it looks like this:
------------
enum ShapeBaseMasks {
HideNodeMask = Parent::NextFreeMask,
SkinMask = Parent::NextFreeMask << 1,
MaxSpeedMask = Parent::NextFreeMask << 2,
NameMask = Parent::NextFreeMask << 3,
DamageMask = Parent::NextFreeMask << 4,
NoWarpMask = Parent::NextFreeMask << 5,
MountedMask = Parent::NextFreeMask << 6,
CloakMask = Parent::NextFreeMask << 7,
ShieldMask = Parent::NextFreeMask << 8,
SoundMaskN = Parent::NextFreeMask << 9, // Extends + MaxSoundThreads bits
ThreadMaskN = SoundMaskN << MaxSoundThreads, // Extends + MaxScriptThreads bits
ImageMaskN = ThreadMaskN << MaxScriptThreads, // Extends + MaxMountedImage bits
NextFreeMask = ImageMaskN << MaxMountedImages
};
------------

You would change it to this:
------------
enum ShapeBaseMasks {
HideNodeMask = Parent::NextFreeMask,
SkinMask = Parent::NextFreeMask << 1,
MaxSpeedMask = Parent::NextFreeMask << 2,
GravityMask = Parent::NextFreeMask << 3,
NameMask = Parent::NextFreeMask << 4,
DamageMask = Parent::NextFreeMask << 5,
NoWarpMask = Parent::NextFreeMask << 6,
MountedMask = Parent::NextFreeMask << 7,
CloakMask = Parent::NextFreeMask << 8,
ShieldMask = Parent::NextFreeMask << 9,
SoundMaskN = Parent::NextFreeMask << 10, // Extends + MaxSoundThreads bits
ThreadMaskN = SoundMaskN << MaxSoundThreads, // Extends + MaxScriptThreads bits
ImageMaskN = ThreadMaskN << MaxScriptThreads, // Extends + MaxMountedImage bits
NextFreeMask = ImageMaskN << MaxMountedImages
};
------------

Make sure to change the above numbers so they stay in sequence.



Search for "F32 mEnergy;"
Right above it enter:
------------
F32 mGravity;
------------


Search for "virtual void setEnergyLevel(F32 energy);"
Above it write:
------------
void setGravity(F32 gravity);
F32 getGravity();
------------

We're finished with shapeBase.h


----------------------------------------------------
Part III - In Player.cc:
----------------------------------------------------

Find and comment out the following line:
------------
F32 Player::mGravity = -20;
------------

Done with this file.


----------------------------------------------------
Part IV - In Player.h:
----------------------------------------------------

Find and comment out the following line:
------------
static F32 mGravity;
------------

Done with this file too.


----------------------------------------------------
Part V - In Item.cc:
----------------------------------------------------

Find and comment out the following line:
------------
F32 Item::mGravity = -20;
------------

Next...


----------------------------------------------------
Part VI - In Item.h:
----------------------------------------------------

Find and comment out the following line:
------------
static F32 mGravity;
------------


----------------------------------------------------------------------------
We're finished with this, it should be fully functional. If you want to add the gravity mod to the vehicles continue on, otherwise just compile and test it.

Use %obj.setGravity(%grav);
And %obj.getGravity();
----------------------------------------------------------------------------


----------------------------------------------------
Part VII - In files flyingVehicle.cc, hoverVehicle.cc, vehicle.cc, and wheeledVehicle.cc
----------------------------------------------------

Find and comment out the following lines (they're in the corresponding files):
------------
static F32 sFlyingVehicleGravity = -20;
static F32 sHoverVehicleGravity = -20;
static F32 sVehicleGravity = -20;
static F32 sWheeledVehicleGravity = -20;
------------


----------------------------------------------------
Part VIII - In files flyingVehicle.cc, hoverVehicle.cc, and wheeledVehicle.cc
----------------------------------------------------

Now we have to set the vehicles so they use mGravity instead of their own gravity variables.

------------
In flyingVehicle.cc replace:
Point3F force = Point3F(0, 0, sFlyingVehicleGravity * mMass * mGravityMod);
With:
Point3F force = Point3F(0, 0, mGravity * mMass * mGravityMod);

And:
F32 vf = -sFlyingVehicleGravity * mMass * mGravityMod;
With:
F32 vf = -mGravity * mMass * mGravityMod;

And:
force -= Point3F(0, 0, 1) * (mBuoyancy * sFlyingVehicleGravity * mGravityMod);
With:
force -= Point3F(0, 0, 1) * (mBuoyancy * mGravity * mGravityMod);
------------


------------
In hoverVehicle.cc replace:
Point3F gravForce(0, 0, sHoverVehicleGravity * mGravityMod);
With:
Point3F gravForce(0, 0, mGravity * mGravityMod);

And:
force += Point3F(0, 0,-mBuoyancy * sHoverVehicleGravity * mGravityMod);
With:
force += Point3F(0, 0,-mBuoyancy * mGravity * mGravityMod);
------------


------------
In wheeledVehicle.cc replace:
(mMass * -sWheeledVehicleGravity) / contactCount);
With:
(mMass * -mGravity) / contactCount);
NOTE: This above looks weird because it's split in two pieces. The whole thing should read:
verticalLoad = (mDataBlock->staticLoadScale * (mMass * -mGravity) / contactCount);

And:
force = Point3F(0, 0, sWheeledVehicleGravity);
With:
force = Point3F(0, 0, mGravity);

And:
force += Point3F(0, 0, -mBuoyancy * sWheeledVehicleGravity);
With:
force += Point3F(0, 0, -mBuoyancy * mGravity);
------------



And that's it. I think I got it all, if anyone has problems E-Mail me, I'll try to help out.
Page «Previous 1 2
#1
11/24/2001 (4:28 am)
If you added to the tutorial stating how to make gravity for each mission different ( by putting something in the .mis file ), that would be extremely useful.

(such as in level.mis add to set gravity value).

Thanks in advance, great tutorial, very useful.
#2
11/24/2001 (4:29 am)
If you added to the tutorial stating how to make gravity for each mission different ( by putting something in the .mis file ), that would be extremely useful.

(such as in level.mis add to set gravity value).

Thanks in advance, great tutorial, very useful.
#3
11/25/2001 (10:07 am)
In the .mis file, write:
$GlobalGravity = -20;

Then in your player spawn code write:
%player.setGravity($GlobalGravity);


You'd have to do it in your item and vehicle spawn code too. I know it's kind of a hack. You could add something in the engine that reads $GlobalGravity and automatically sets the default gravity to it.


Dark
#4
11/30/2001 (9:46 am)
Question:

Does the players point of view adapt to the gravity changes? Specifically, is the gravity vector always 'down' to him, regardless of world-space?
#5
02/01/2002 (6:29 am)
great resource :)
ive gone ahead and added the gravity field to my mission area ..
and from there in the code ive set it up for shapebase objects onAdd to utilize the mission area gravity setting
#6
02/06/2002 (3:12 am)
I fixed the way it updates. I added a GravityMask so it sends the new info to the client as soon as you change it. Now it updates instantly.

E-mail me if you want the changes.
#7
02/14/2002 (2:38 pm)
Ok, I just updated this to use the GravityMask. It's easy to convert the old code to this. Now it updates instantly.
#8
12/30/2002 (9:38 pm)
did you change the code from the original post? FYI, im using the HeAD as of a day or 2 ago and although it was not exactly the same as your instructions, it was easy to do using your instructions. Great resource. Thanks.

If you've changed something can you please email me what you have changed in the instructions? Thank you.

robertbrower@attbi.com
#9
02/22/2003 (6:42 pm)
This seems to work as a quick way to turn off gravity, but it's not per-object. Just add this to the .mis file:

new PhysicalZone(PhysicalZone) {
gravityMod = "0";
polyhedron = "-10000 -10000 -10000 20000 0 0 0 0 20000 0 20000 0";
};

This creates a physical zone which surrounds your likely mission area and multiplies the normal force of gravity (1.0) by the modifier given (0).
#10
12/20/2003 (12:12 am)
Obviously some things have changed since this resource was written about two years ago. Has anyone gotten this to work lately? For example, the first instuction is to find void ShapeBase::consoleInit() and to find the lines beginning with Con::AddCommand.

The ShapeBase::consoleInit() function in my version of TGE looks like this though:

void ShapeBase::consoleInit()
{
Con::addVariable("SB::DFDec", TypeF32, &sDamageFlashDec);
Con::addVariable("SB::WODec", TypeF32, &sWhiteoutDec);
Con::addVariable("pref::environmentMaps", TypeBool, &gRenderEnvMaps);
}

Also, going to the second instruction, the function "static const char* cGetEyeTransform(SimObject *ptr, S32, const char **)" doesn't exist.

Any ideas?

Dan
#11
12/20/2003 (8:25 am)
As a matter of fact, yes I did just today:

Ignore the initial stuff up to
Find the function "F32 ShapeBase::getEnergyLevel()" and write the following above it:

Throw these at the end of shapebase (or where ever you want them in the file):

ConsoleMethod( ShapeBase, getGravity, F32, 2, 2, "")
{
return object->getGravity();
}

ConsoleMethod( ShapeBase, setGravity, void, 3, 3, "(float gravity)")
{
object->setGravity(dAtof(argv[2]));
}

-Jerry
#12
07/04/2005 (8:47 am)
This will come in handy ;)
#13
11/21/2005 (4:20 pm)
@Lynx:

I tried making the mission zone with the Gravity Mod you suggested, but it doesn't seem to have an effect, even tho GravityMod *is* in the code.
#14
03/26/2006 (10:01 am)
Does anyone know if this will work with TGE 1.4?
#15
03/31/2006 (6:20 am)
got this working in tge 1.4, had to use a bit of common sense but apart from that the instructions above were fine. main problem was with vehicles but got it sorted out
#16
03/31/2006 (6:45 am)
how would i add gravity to an object?

new TSStatic() {
position = "-61.5018 -257.412 121.419";
rotation = "1 0 0 0";
scale = "1 1 1";
shapeName = "~/data/shapes/environment pack/rock5.dts";
};

thats the bit in the mission file how would i give it gravity?
#17
04/01/2006 (1:40 am)
ConsoleMethod( ShapeBase, getGravity, F32, 2, 2, "")
{
return object->getGravity();
}

ConsoleMethod( ShapeBase, setGravity, void, 3, 3, "(float gravity)")
{
object->setGravity(dAtof(argv[2]));
}


crashes the engine
#18
04/01/2006 (1:53 am)
ok I got it all working, its works fine in my tge 1.4
Ill post the changes below
#19
04/01/2006 (1:53 am)
Quote:
Ignore the initial stuff up to
Find the function "F32 ShapeBase::getEnergyLevel()" and write the following above it:

Throw these at the end of shapebase (or where ever you want them in the file):

ConsoleMethod( ShapeBase, getGravity, F32, 2, 2, "")
{
return object->getGravity();
}

ConsoleMethod( ShapeBase, setGravity, void, 3, 3, "(float gravity)")
{
object->setGravity(dAtof(argv[2]));
}
#20
04/01/2006 (1:54 am)
then in the game.cs file:

change:

%player.setGravity($GlobalGravity);

to

%player.setGravity(-20);
Page «Previous 1 2