Cleaned-up third person camera
Assumed knowledge
It is assumed that before you begin this tutorial, you are familiar with the following concepts:
Understanding these concepts is vital to understanding the following tutorial.
Use and advantages
The internal third person cam is preferable, but in a select few well-planned instances, scripts such as the following may be used instead. As the page title suggests, this script will control a camera that follows the player.
Unlike other scripts that have been posted, this one is relatively free of clutter. This script set corrects old hacks used for sin and cos, which did not work correctly in pre-96x versions. Aside from that, the math has been cleaned up drastically, and an emphasis was placed on multiplayer compatibility and using as few map level variables as possible. Instead of spawning, setting, and then removing the camera, this script uses the new SetActorPosition function to move the camera about. It also takes full advantage of the GetActorPitch and SetActorPitch functions for a fully three dimensional chase cam.
DECORATE
actor ChaseCam { Height 16 Radius 8 +NOGRAVITY +NOBLOCKMAP states { Spawn: TNT1 A -1 stop } }
Script
Setting things in motion
Using “ENTER” and “RESPAWN” scripts, the camera mode is turned on, and the main script is executed. This is important for managing multiplayer compatibility.
//Third person camera simulation. //solarsnowfall #include "zcommon.acs" #define C_TID 1000 //Default camera tid #define MAX_R 128 //Maximum radius (or distance from the player) #define ADJUST_R 8 //Amount to adjust the camera by #define VIEW_HEIGHT 41.0 //The approximate height of the player's view bool cam_mode[8]; //Variable for turning the camera on or off. Script 1 ENTER { cam_mode[PlayerNumber ()] = ON; ACS_ExecuteAlways (3, 0, PlayerNumber ()); } Script 2 RESPAWN { cam_mode[PlayerNumber ()] = ON; ACS_ExecuteAlways (3, 0, PlayerNumber ()); }
Generation of coordinates
This segment grabs the coordinates of the player and generates coordinates to spawn the camera. If it fails, the script is terminated and an error message is printed.
Script 3 (int p_num) { int r = MAX_R; while (cam_mode[p_num] == ON) { int a = GetActorAngle (0); int p = GetActorPitch (0); int x = GetActorX (0); int y = GetActorY (0); int z = GetActorZ (0) + VIEW_HEIGHT; int xyr = r * cos (p) >> 16; if (!ThingCountName ("ChaseCam", C_TID+p_num)) { while (!Spawn ("ChaseCam", x-cos(a)*xyr, y-sin(a)*xyr, z+sin(p)*r, C_TID+p_num, a >> 8) && r > 0) { r -= ADJUST_R; xyr = cos (p) * r >> 16; } if (ThingCountName ("ChaseCam", C_TID + p_num)) ChangeCamera (C_TID + p_num, 0, 0); else { cam_mode[p_num] = OFF; print (s:"Camera script failed to initialize."); } }
If the camera was successfully spawned the spawn segment will now be skipped, and the script will begin moving the camera with the player. If when trying to move the camera into position a failure occurs, the script recalculates the coordinates and attempts to move the camera towards the player.
else { while (!SetActorPosition (C_TID+p_num, x-cos(a)*xyr, y-sin(a)*xyr, z+sin(p)*r, 0) && r > 0) { r -= ADJUST_R; xyr = cos (p) * r >> 16; } SetActorAngle (C_TID + p_num, a); SetActorPitch (C_TID + p_num, p); if (r < MAX_R) r += ADJUST_R; } delay (1); } }
Camera removal
Script 4 will turn the "camera mode" off and remove the player's camera when they die. Script 5 will do the same if the player disconnects.
Script 4 DEATH { cam_mode[PlayerNumber ()] = OFF; Thing_Remove (C_TID + PlayerNumber ()); } Script 5 (int p_num) DISCONNECT { cam_mode[p_num] = OFF; Thing_Remove (C_TID + p_num); }