2.6 Simple third person sprite movement

By Mike Damert, Damert@navpoint.com.

In this tutorial, I'll go over moving a sprite forward and moving a sprite to the right, and I'll let your own creativity allow you to figure out moving left and backward. The method I use is somewhat ugly, but it works, and also reveals through implication how almost any sort of simple third person camera might work, so I post it here despite its flaws. I start within the SetupFrame() function, with this line:

if (kbd->GetKeyState (CSKEY_UP))
  MoveForward ();

Obviously, I'm foreshadowing a MoveForward() function, which I make a part of the Simple class. And here it is:

void Simple::MoveForward ()
{
  //Rotate camera temporarily up
  c->GetTransform ().RotateThis (CS_VEC_TILT_UP, PI/12);
  c->Move (CS_VEC_FORWARD * speed);
  //Character is moved in terms of world coordinates
  movable->MovePosition ( c->GetTransform ().This2OtherRelative ( CS_VEC_FORWARD ) * speed );
  //De-rotate camera from temporary up position
  c->GetTransform ().RotateThis (CS_VEC_TILT_DOWN, PI/12);
  //Character faces a direction in relation to the camera
  movable->GetTransform ().SetT2O ( c->GetTransform ().GetT2O() );
  //Re-orient character to face forward
  movable->GetTransform ().RotateThis (CS_VEC_ROT_RIGHT, PI/2);
  movable->UpdateMove ();
}

Normally, the camera is tilted downward by PI/12 radians. This allows us to get a better look at the scene without forcing the view to be drawn to the horizon. You could change this if you want, because it forces us to tilt the camera into a normal, parallel to the ground position when we move. I'll explain why later.

The first step is to tilt the camera into a normal position. Having done that, we move the camera forward. I use the varibale speed here, which is defined in the Simple2 application, so that the camera and player will move at a relative speed to the time elapsed between frames.

The next step is to move the player sprite forward. The player is represented by an iMovable named movable. For this, I cannot just use the sprite's position and move it forward--what if the sprite were on an angle? This is why I take the camera's transformation and tell the sprite to move in camera units, not world units. Now you can tell the camera to return to its original angle.

The second- and third-to-last lines rotate the character so that he faces forward, no matter how he was rotated before. And finally, we call UpdateMove() because the documentation says it is important to do so :)

Now we can move on to moving right, called here:

if (kbd->GetKeyState (CSKEY_RIGHT) && !move)
  MoveRight ();

The idea behind the MoveRight() function is much the same as the idea behind the MoveForward() function, so much of the code will be the same. The difference is that when you move right, the camera stays at a fixed position, but rotates the position it looks at, and the character moves when he rotates, using the camera as a pivot. I hope this part of the code is self-explanitory. I believe this code is imperfect in that it does not properly handle the angle of the camera (but I'm not certain), but it should give you an idea of one way to rotate the camera.

void Simple::MoveRight ()
{
  //rotate both camera and character to the right
  //Rotate in world space, not camera space
  c->GetTransform ().RotateOther (CS_VEC_ROT_RIGHT, speed/10);
  //Move character right in relation to the camera
  movable->MovePosition ( c->GetTransform ().This2OtherRelative ( CS_VEC_RIGHT ) * speed );
  //Character faces a direction in relation to the camera
  movable->GetTransform ().SetT2O ( c->GetTransform ().GetT2O() );
  //Re-orient character to face forward
  movable->GetTransform ().RotateThis (CS_VEC_ROT_RIGHT, PI);
  movable->UpdateMove ();
}