How to sink / show up (almost) instantly.
by Bullitt Sesariza · in Torque Game Engine · 08/04/2008 (9:41 am) · 8 replies
Hi, I use a waterblock in one of my missions. I have a few AIPlayers that will swim / move along their designed paths. They can also be scheduled to sink/drown and show up repetitively, but still maintain their original horizontal velocity and heading. This is my script as of now:
This is the datablock of the AIPlayer:
So you see, when I want it to sink, I just change the its density and mass and applied an impulse down the z axis. Vice versa if I want it to show up and float again. But I wanted it to sink / show up almost instantly. FYI as of now it would need a few seconds until it is totally submerged (if set to sink) or float at the original buoyancy (if set to show up again). I need it to be faster. I've tried changing the water's viscosity to no avail. I've tried changing the density & mass to a bigger number but it still would take a few seconds to sink. I've tried increasing the z-impulse but no effect (except if I change it to a very large value, then it would all disappear at once). So, is there any other way that I should try? Thanks in advance.
//-----------------------------------------------------------------------------
// Function for sinking / showing scheduler
// Syntax: AIPlayer::sinkShowSched(%this)
// Params:
// %this = the instance of the object
//-----------------------------------------------------------------------------
function AIPlayer::sinkShowSched(%this)
{
//Change the sinking status
if (%this.sinkTime > 0 && %this.showTime > 0)
{
if (%this.sinkStatus == true) //We are now sinking. Set to showing up and float.
{
%this.sinkStatus = false; //Now we are showing up
//Un-sink
%this.applyImpulse("0 0 0", "0 0 1000");
%this.getDatablock().density = %this.getDatablock().densityOri;
%this.getDatablock().mass = %this.getDatablock().massOri;
//Scheduling
%this.sinkSchedule = %this.schedule(%this.sinkTime, sinkShowSched);
}
else
{
%this.sinkStatus = true;
//Sink
%this.applyImpulse("0 0 0", "0 0 -3000");
%this.getDatablock().density = 100000;
%this.getDatablock().mass = 100000;
//error("------------ mass=" SPC %this.getDatablock().mass);
//Scheduling
%this.sinkSchedule = %this.schedule(%this.showTime, sinkShowSched);
}
}
}This is the datablock of the AIPlayer:
datablock PlayerData(CrocDBlock)
{
emap = true;
className = "Platform";
shapefile = "~/data/shapes/Croc/croco.dts";
cameraMaxDist = 3;
computeCRC = true;
canObserve = true;
cmdCategory = "Clients";
runForce = 40 * 2450;
//boundingBox = "4.4 5 4";
boundingBox = "4 10 4";
//mass = 0.5;
mass = 1;
density = 0.8;
massOri = 1;
densityOri = 0.8;
//drag = 0.3;
//maxdrag = 0.4;
drag = 0.0;
maxdrag = 0.1;
};So you see, when I want it to sink, I just change the its density and mass and applied an impulse down the z axis. Vice versa if I want it to show up and float again. But I wanted it to sink / show up almost instantly. FYI as of now it would need a few seconds until it is totally submerged (if set to sink) or float at the original buoyancy (if set to show up again). I need it to be faster. I've tried changing the water's viscosity to no avail. I've tried changing the density & mass to a bigger number but it still would take a few seconds to sink. I've tried increasing the z-impulse but no effect (except if I change it to a very large value, then it would all disappear at once). So, is there any other way that I should try? Thanks in advance.
#2
In your case, setting to -40 would cause a fairly quick sinking, while a changeover to +10 would cause a bobbing to the surface. You'de need a surface check to reset to -20 to complete it.
08/04/2008 (10:15 am)
Move all the sGravity (player, vehicle, item) variables up to shapebase, and add a get/set routine. In my char loading routine, I do %player.setGravity(-20); to get started. I can easily change this on the fly, giving me varying gravity effects.In your case, setting to -40 would cause a fairly quick sinking, while a changeover to +10 would cause a bobbing to the surface. You'de need a surface check to reset to -20 to complete it.
#3
@Erik: Did you mean mGravity? If I read it correctly, the variable is a static one, right? So if I change it on the fly, wouldn't that also affect all the rest of the objects' gravity? Even if I only wanted to make a single object dive, the rest of the objects would also dive. CMIIW. But I get the idea though. Maybe I'll just add one more variable for this. Thanks.
Thanks a lot guys.
PS: A little OOT. Are 'dive', 'sink', and 'drown' the same? Dunno the differences between them. My vocabulary is so messed up right now. :D
08/04/2008 (8:01 pm)
@Scott: Yeah I know that isn't the correct way to do it. I just don't know how to do it in Torque beside that. In real world physics, if we want to take a dive (not sink like I wrote before. I know it's a terrible choice of word) it means that we are making a force downward (negative z). And the force should be made constantly so we would stay submerged. In Torque, the only way to implement a force is by applying impulse with the applyImpulse( ) function AFAIK. And it can only be called once. CMIIW. FYI, actually the datablock value changing is working because my game is actually a single player one. But the problem is the objects wouldn't dive instantly.@Erik: Did you mean mGravity? If I read it correctly, the variable is a static one, right? So if I change it on the fly, wouldn't that also affect all the rest of the objects' gravity? Even if I only wanted to make a single object dive, the rest of the objects would also dive. CMIIW. But I get the idea though. Maybe I'll just add one more variable for this. Thanks.
Thanks a lot guys.
PS: A little OOT. Are 'dive', 'sink', and 'drown' the same? Dunno the differences between them. My vocabulary is so messed up right now. :D
#4
On topic, I think Erik was implying adding dynamic gravity to every object, not just modifying the class static. I think there's a resource for it.
What you're doing should work, but maybe you need a combination of the two approaches. You're right that forces can't be applied constantly, unless you use a schedule very often (which probably isn't a great solution). My idea: when you want a thing to sink, change its density, AND apply a large downward force. The force will ensure that it bobs downwards instantly, and the density will ensure that it stays down.
08/05/2008 (9:37 am)
I will pick up the OT ;) The three words refer to the same movement, but have different connotations. Dive implies you're deliberately swimming downwards. Sink implies going downwards because you're not able to float. And drown simply implies dying because of asphyxiation underwater.On topic, I think Erik was implying adding dynamic gravity to every object, not just modifying the class static. I think there's a resource for it.
What you're doing should work, but maybe you need a combination of the two approaches. You're right that forces can't be applied constantly, unless you use a schedule very often (which probably isn't a great solution). My idea: when you want a thing to sink, change its density, AND apply a large downward force. The force will ensure that it bobs downwards instantly, and the density will ensure that it stays down.
#5
@Daniel: Well, that's my first attempt before. I've tried changing the density and adding an impulse downward with applyImpulse. Although it can make the object sink, it would do so slowly not like I wanted it to be (which should be way faster).
I've tried adding some gravity hack but didn't work. Here's the code:
shapebase.h:
shapebase.cc:
player.cc, method Player::updateMove():
BTW, my current Player::updateMove() method has some modifications in it. One is from:
http://www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=11218 to solve the jerky animation. The other is the code for swimming from this resource: http://www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=11543. Do they have any effect to my dive / sinking problem? Thanks.
08/10/2008 (7:23 pm)
Sorry it takes too long to reply again. @Daniel: Well, that's my first attempt before. I've tried changing the density and adding an impulse downward with applyImpulse. Although it can make the object sink, it would do so slowly not like I wanted it to be (which should be way faster).
I've tried adding some gravity hack but didn't work. Here's the code:
shapebase.h:
...
protected:
F32 mGravityHack;
...
public:
inline void setGravityHack(const F32 lvl) { mGravityHack = lvl; }; //Sets the object additional gravity level!
inline F32 getGravityHack() const { return mGravityHack; };
...shapebase.cc:
...
//Set the hack!!!
ConsoleMethod( ShapeBase, setGravityHack, void, 3, 3, "(float hackValue)")
{
F32 lvl = dAtof(argv[2]);
object->setGravityHack(lvl);
}
//Get the HACK!!!
ConsoleMethod( ShapeBase, getGravityHack, F32, 2, 2, "")
{
return object->getGravityHack();
}
...player.cc, method Player::updateMove():
...
// Acceleration due to gravity
VectorF acc(0.0f, 0.0f, mGravity * [b]mGravityHack[/b] * mGravityMod * TickSec);
...
// Container buoyancy & drag
if (mBuoyancy != 0.0f)
{ // Applying buoyancy when standing still causing some jitters-
if (mBuoyancy > 1.0f || !mVelocity.isZero() || !runSurface)
mVelocity.z -= mBuoyancy * mGravity *[b] mGravityHack [/b] * mGravityMod * TickSec;
}BTW, my current Player::updateMove() method has some modifications in it. One is from:
http://www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=11218 to solve the jerky animation. The other is the code for swimming from this resource: http://www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=11543. Do they have any effect to my dive / sinking problem? Thanks.
#6
As for density, if you want to change the players density on command, you can follow the same steps as the above resource to add console functions and networking for a dynamic bouyancy. As far as diving down quickly, why not use several impulses successively?
You could also just apply one very large impulse (z impulse of 4,000-5,000 or so?). If you think of the physics of a dive, you are really only jumping in and using gravities impulse once to dive deeper into the water. There would still be the issue of staying underwater which can be solved either by adding the dynamic gravity resource and setting a different gravity while diving or by following the same steps with bouyancy.
08/10/2008 (8:41 pm)
There's a great resource for dynamic gravity that adds a setGravity(S32 value) function. Just do a search for "dynamic gravity" and it should come up first.As for density, if you want to change the players density on command, you can follow the same steps as the above resource to add console functions and networking for a dynamic bouyancy. As far as diving down quickly, why not use several impulses successively?
%obj.applyImpulse("0 0 1500");
%obj.schedule(1000, applyImpulse, "0 0 1500"); // 1 second later
%obj.schedule(2000, applyImpulse, "0 0 1500"); // 2 seconds laterYou could also just apply one very large impulse (z impulse of 4,000-5,000 or so?). If you think of the physics of a dive, you are really only jumping in and using gravities impulse once to dive deeper into the water. There would still be the issue of staying underwater which can be solved either by adding the dynamic gravity resource and setting a different gravity while diving or by following the same steps with bouyancy.
#7
08/10/2008 (10:44 pm)
Oh, sorry - I should read a bit more thoroughly next time :P
#8
Oh, BTW, thank you so much guys.
08/20/2008 (11:39 pm)
Done. I implemented both the gravity hack and the density changing. BTW, IMHO the physics for waterblock is kind of weird. The floating / sinking is only based on density without considering any outside interference. I've tried adding an impulse of 1 million downward to the floating object but it only made the object behave weirdly. It seems like it tried to take a dive put got pushed back upward. So it was rendered like a flickering object. One frame it would dive, and on the next 1-2 frames it would rise again immediately (and it almost looks like jumping above the water surface ), and so on. So it looks like it tried to dive but got held back by a bigger force than the impulse. Weird.Oh, BTW, thank you so much guys.
Associate Scott Burns
GG Alumni