« Tribes 1 Physics, Part One: Overview | Main | Tribes 1 Physics, Part Three: Collision »

Tribes 1 Physics, Part Two: Movement

Posted on February 24, 2008 11:48 PM

This article covers the movement physics of Tribes 1, i.e. jumping, jetting, and ground movement/friction. These account for ~90% of the "Tribes" feeling, although even 90% will still feel wrong to anyone who knows the authentic feel well. There will be some variables which are only set in the Collision code, but there shouldn't be any confusion as to what they do.

Movement Code

There are a few spots where Tribes took shortcuts with it's math and assumed that gravity would always be "0 0 -X", saving a couple multiplies on dots and such. I've replaced these spots to be gravity agnostic as I don't think the CPU savings are that big and they make the code difficult to understand. It shouldn't be hard to "re-optimize" if you feel the need. Dot products will be a .Dot method because overloaded multiplication operators confuse me.


Player.Tick starts off by taking the user's movement input (left, right, forward, back) and creating the speed vector for walking and direction vector for jumping and jetting. This is pretty basic and there is nothing out of the ordinary here.

After this, the Player energy is updated, we check lastJumpableNormalTimestamp to see if a jump should be allowed, and then do the jumping, jetting, and walking. Most of the real work takes place in Jump, Jet, and Friction, so the tick function is fairly sparse.

A few things to note:

  • Tribes lets you jump up to 256ms after your last ground contact, allowing you to jump smoothly through little bumps and such where you technically leave the ground, but don't really appear to.
  • Tribes handles jetpack energy a little differently, i.e. once you get to around 5% of your jets, they cut off and recharge a little causing the jets to stutter. I haven't worked this part out yet, but may re-edit this section if I do.
  • Tribes applies gravity constantly, it is not hacked off when you are resting on a surface.
  • JETENERGY_CHARGE equals "8 + 3" with the "+ 3" being the recharge boost from an energy pack.

Side jets only kick in if the player is holding down a movement key and it's been longer than MAXJUMPTICKS since the last ground contact. Since jumping sets lastJumpableNormalTimestamp to the limit, jumping and jetting results in side jets being enabled immediately, while simply holding down your jets on the ground will give a little startup time of full jets regardless of whether a direction key is down.


This is needed for the gravity agnostic Friction function. I don't know how common it is.


Multiplying GROUNDTRACTION by currentFriction is unfortunately not the magical "Friction = 0" that supposedly causes skiing. currentFriction is decayed every tick when there hasn't been a ground contact, resulting in the ability to jet and slide against walls and ceilings without being slowed down by the contact friction.

ProjectOntoPlane is probably not needed since the player should always be oriented so the move will never include a component not in the gravity plane, but it doesn't hurt to include it.

Tribes 1 Physics Series

TrackBack Info

TrackBack URL for this entry:

Post a comment

(If you haven't left a comment here before, you may need to be approved by the site owner before your comment will appear. Until then, it won't appear on the entry. Thanks for waiting.)