Game Development Community

Determining a Player is airborne.

by Kuju Manila · in Torque Game Engine · 05/02/2007 (7:18 pm) · 12 replies

Is there a way to determine whether a player object is airborne? For instances like players that fall of a cliff.

#1
05/02/2007 (7:42 pm)
Z velocity can be determined in source code, it's used in player.cc to play the falling animation. I don't know of a way to do this in script.
#2
05/04/2007 (12:43 am)
Z velocity won't help you if he isn't moving in Z direction. I've wondered about this too-- a way to tell if the player is in contact with the ground.
#3
05/04/2007 (1:01 am)
Well you could use this:
// Get distance from bottom of controlled object to terrain
getControlObjectAltitude()
Or cast a simple ray from the player's feet.
#4
05/04/2007 (1:07 am)
%bla = %z.getTerrainHeigh();
%unbla = %actualZ

Have you tried doing something to the extent of VectorDist(%bla, %unbla);

I know that is not exactly correct code, but the general idea...i'm tired, it's 3...Spider Man premier....
#5
05/04/2007 (1:08 am)
Ah, raycasting. Yes...I've read a lot about it but haven't tried it.

I shall have to do so! :-)
#6
05/04/2007 (1:54 am)
bool Player::isAirborne(F32 fudgefactor)
{
   U32 mask = InteriorObjectType | TerrainObjectType | ForceFieldObjectType;
   Point3F start = getPosition();
   Point3F end = start + VectorF(0,0,-1) * fudgefactor;

   RayInfo rInfo;
   disableCollision();
   bool los = getContainer()->castRay(start, end, mask, &rInfo);
   enableCollision();

   return los;
}

ConsoleMethod(Player,isAirborne,bool,3,3,"obj.isAirborne(fudgefactor)")
{
   return object->isAirborne(dAtof(argv[2]));
}

bool isAirborne(F32 fudgefactor);

I use that code in player.cc and player.h respectively to check if a player is in the air. The other built-in code methods only check for the terrain and not interiors.
The same thing can be done in script using ContainerRayCast(start, end, masks, ignoreobject);
The end position will be the same as the player position plus a few to the z axis, and if it returns anything then you are not airborne. You'll also want to set the player object as the ignore object or you will always be touching something (i.e. you).
#7
05/04/2007 (2:36 am)
Here's an easy scripted solution:

Place this function in server/scripts/player.cs
//-----------------------------------------------------------------------------
// Determine if player is falling (Server)
// %player = player server ID
//-----------------------------------------------------------------------------
function Player::checkPlayerFalling(%player)
{
   %mask = $TypeMasks::StaticShapeObjectType | $TypeMasks::InteriorObjectType | $TypeMasks::TerrainObjectType;
   %rayStart = %player.getWorldBoxCenter();
   %rayEnd = getWord(%rayStart, 0) SPC getWord(%rayStart, 1) SPC getWord(%rayStart, 2) - 2;
   %foundObject = ContainerRayCast(%rayStart, %rayEnd, %mask, 0);

   if (!%foundObject)
   {
      echo("--> Player is falling!");
      messageAll("","player is falling!");
   }

   if(%player.isEnabled())
      %player.schedule(100, checkPlayerFalling);
}
//-----------------------------------------------------------------------------
Add this to the Armor::onAdd method:
function Armor::onAdd(%this,%obj)
{
...
...
   // Determine if player is falling
   %obj.checkPlayerFalling(%obj);
   // Determine if player is falling
}

Done.

The function continues to loop and checks if there's anything beneath the player's feet whilst they are alive. The function stops on death.
#8
05/04/2007 (3:02 am)
Quote:
Z velocity won't help you if he isn't moving in Z direction
Well if the player is falling they will be moving in the Z direction.

As Paul points out, "getControlObjectAltitude()" only checks for terrain which is why I presented my scripted alternative above.
#9
05/04/2007 (3:17 am)
Hmm, Tim, do you not hit your own player container when searching without setting the search to ignore the player?
#10
05/04/2007 (8:00 am)
No, the player isn't detected as I haven't included it in the search masks. I have only included terrain, interiors and static shapes.

If I wanted to include players in the search, I would use $TypeMasks::PlayerObjectType.
#11
05/04/2007 (9:29 am)
Ah, silly me, should have known that. Having a brain-fart of a day :)
#12
05/04/2007 (1:09 pm)
@Tim: I hear ya. I just have a tendency to have gravity-defying elements in my game ideas :-)

Another thread to bookmark...