Adventure cameras

Many of you have used my "Resident Evil" - type cameras from Aum4. Please allow me to remind you how those cameras work: you move the player in the level and the closest camera to the player takes control. I believe that this system works ok for most games, but some of you have had problems with multiple story buildings, while others would have liked to be able to specify individual sensitivity areas for each camera. The code from this article fixes all these problems.

view adv_camera{ }

starter init_cameras()
{
sleep (0.5);
camera.visible = off;
adv_camera.pos_x = 0;
adv_camera.pos_y = 0;
adv_camera.size_x = screen_size.x;
adv_camera.size_y = screen_size.y;
adv_camera.visible = on;
adv_camera.x = 820;
adv_camera.y = -1150;
adv_camera.z = 620;
adv_camera.pan = 120;
adv_camera.tilt = -25;
adv_camera.roll = 0;
}

I have defined a new view named adv_camera. The starter function waits until the level is loaded, disables the default "camera" view, sets the position and size for adv_camera and then makes it visible. The last lines of code set the initial position and angles for adv_camera; this is what the player will see (the starting point for your game) when you run the level.

// uses cam_number, cam_range
action detect_player
{
my.invisible = on; // hide the model
my.passable = on;
while (player == null) {wait (1);} // wait until the player is loaded
if (my.cam_number == 0) {beep; beep; beep; exit;}
if (my.cam_range == 0) {beep; beep; beep; exit;}
while (1)
{
temp.x = 360; // horizontal scanning angle
temp.y = 180; // vertical scanning angle
temp.z = my.cam_range; // scanning range
scan_entity (my.x, temp);
if (result > 0) // got something?
{
set_camera(my.cam_number); // then set the proper camera position and angles
}
wait (1);
}
}

Place several models in the level, attach them the "detect_player" action and they will turn into invisible player detecting devices. You can set their scanning ranges (cam_range) and their number (cam_number) in Wed: the first device will have its cam_number set to 1, the second device will have cam_number = 2 and so on. Oh, and if you forget to set cam_number and / or cam_range for one of the devices the engine will shut down. How do these things work? They simply scan around them; when the player comes close to the 3rd device (just an example) we call function set_camera(3) which will set the position and angles for the 3rd camera.

function set_camera(number)
{
if (number == 1)
{
adv_camera.x = -40;
adv_camera.y = 340;
adv_camera.z = 1260;
adv_camera.pan = 270;
adv_camera.tilt = -72;
adv_camera.roll = 0;
}
........................
if (number == 5)
{
adv_camera.x = 1900;
adv_camera.y = 1460;
adv_camera.z = 800;
adv_camera.pan = 220;
adv_camera.tilt = -35;
adv_camera.roll = 0;
}
}

The function above sets the proper adv_camera position and angles depending on the number that was passed as a parameter to it. If the player is close to the model that has its "cam_number" set to 1 in Wed, the camera will be set to x = -40, y = 340, z = 1260, pan = 270, tilt = -72 and roll = 0, get it? I'm sure that some of you would like to know how did I come up with the values used in function set_camera, so here's the answer: I have created the level, I have run it as a wmb file (without using any script) and I have moved the camera to a convenient position for the first adv_camera set of values. F11 has revealed the current x, y, z, pan, tilt, roll angles, so I wrote them down, and then I moved to the second position, and so on.

Trap

This snippet was created for you, the users who liked my "intelligent music" article from Aum38. It's a gate that closes behind player's back as soon as he steps over one of the small triggers that are placed on the ground.

action trap_trigger
{
while (player == null) {wait (1);}
while (vec_dist (player.x, my.x) > 50) {wait (1);} // play with 50
player_close = 1;
}

The triggers wait until the player is created, and then they wait until the distance between them and the player goes below 50 quants. This is a critical value that depends on player's height and the z position of the triggers, so you should play with it. If the player steps over one of the triggers, a variable named "player_close" is set to 1.

action trap_player
{
while (player_close == 0) {wait (1);}
snd_play (gate_wav, 100, 0);
while (my.z > 170)
{
my.z -= 30 * time;
wait (1);
}
}

The action above is attached to the gate entity; it waits until player_close is set to 1, plays the gate_wav sound, and then decreases its z until it goes below 170 quants (experimental value). Make sure that the triggers aren't too close to the gate; otherwise, the player might escape. Well, you could also increase the falling speed by replacing 30 * time with 50 * time or 100 * time, depending on your needs.