3 registered members (Ayumi, Akow, AndrewAMD),
1,505
guests, and 9
spiders. |
Key:
Admin,
Global Mod,
Mod
|
|
|
The Ultimate Resident Evil Camera
#38203
12/20/04 02:32
12/20/04 02:32
|
Joined: Aug 2000
Posts: 7,490
Orange Brat
OP
Senior Expert
|
OP
Senior Expert
Joined: Aug 2000
Posts: 7,490
|
A huge thanks to "tesanders". Without him most of this code wouldn't exist, so if you use this, give him a nice, huge credit. This is what I consider to be the finest Resident Evil style camera system around. Of course, you can use it for other types of games....point & click adventures for example....but most of us associate them with survival horror type acton adventures. The system sets up a "voronoi field". If you don't know what that means, you can find an explanation, complete with browser demo, here: http://www.cs.cornell.edu/Info/People/chew/Delaunay.html This type of environment sets up hot zones for each trigger and allows you to disconnect the camera from the trigger. This means you can place the camera 150000 miles away from its trigger or 150 inches for that matter. This opens up the creative possibilities and gives you, the level designer, much more breathing room. It does have a quirk or two. For example, it doesn't work very well with multifloored levels. You CAN use them with them, but it can be tricky at first. Once you get the hang of it, you'll find the right way but it can still be a royal hair pulling exercise to get the triggers in just the right spot. It requires 3 objects to work(or 2 if you use the commented out alternate version of camera_move), and you can have cameras that always look at the player, always look at an offset between the player and another object, or completely still views like prerendered backgrounds. Each camera has a camera entity and its corresponding trigger entity. You assign the "set_cam" and "set_cam_trigger" actions and set each entities skill1 to a value. Both entities must have the same skill1 value and you can use up to 200 cameras, by default, but you can use any total you want by changing the array value. Do not assign "0" as a skill1 value or it'll return without switching cameras. You can also use more than one trigger entity for each camera. This is useful when you need to extend the influence of a specific camera. You can insert an "island" of influence inside the zone of another camera's hotzone, too. The 3rd object is a look at entity. It is used for an offset(if desired) based on the "cam_factor" variable. If you set it to 0, the camera will always look directly at the player. If you set it to 1, it will always look at the look at entity and will never move...a perfectly still camera. If you set it to any value between 0 and 1, it will always watch the "lerped" spot between the player and the look at entity and will move when the player moves. The downside to this setup is, as is, you can only have one look at object per level. It can easily be adapted so that each camera has its own look at object, but if you don't require an offset, you can comment out the camera_move function and uncomment the other. Using the alternate function, you can still achieve a perfectly still camera by setting the camera entities' flag1 to on. If you want it to follow the player, set it to off.
/////////////CAM
entity* cam_look_at; //the look at object pointer
entity* cam_ptr; //the camera object pointer
var cam_array[200]; // a maximum of 200 cameras...increase/decrease for your needs
var cam_closest_distance;
var cam_active; //0 = not active; 1 = active
var cam_target[3]; //temp camera storage
var cam_factor = 1; //0 = always follows player
//1 = always look at cam_look_at
//between 0-1 looks at offset between player and cam_look_at
function init_cameras() //gets first camera
{
get_cam(1);
}
starter cam_poller() //controls the camera trigger array
{
proc_kill(4);
while(1)
{
cam_closest_distance = 100000;
wait(1);
}
}
function get_cam(cam_number) //retrieve fixed view
{
proc_kill(4);
if(cam_array[cam_number] == 0) { return; }
cam_ptr = ptr_for_handle(cam_array[cam_number]);
}
action set_cam //store fixed view
{
my.invisible = on;
my.passable = on;
cam_array[my.skill1] = handle(me);
}
action set_cam_trigger //trigger for fixed view
{
while(player == null) { wait(1); }
my.passable = on;
my.invisible = on;
while(1)
{
if(vec_dist(my.x, player.x) < cam_closest_distance)
{
cam_closest_distance = vec_dist(my.x, player.x);
get_cam(my.skill1);
}
wait(1);
}
}
action set_cam_look_at //assign to look at object
{
my.passable = on;
my.invisible = on;
cam_look_at = me;
}
function camera_move() //camera looks at cam_look_at or player or inbetween them depending on cam_factor
{
while(cam_ptr == null) { wait(1); }
while(cam_active == 1)
{
if(cam_look_at != null)
{
vec_set(camera.x, cam_ptr.x);
vec_lerp(cam_target.x, player.x, cam_look_at.x, cam_factor); //get offset based on cam_factor
vec_set(temp, cam_target.x); //assign to temp
vec_sub(temp, camera.x); //get cam_target's distance from camera
vec_to_angle(camera.pan, temp); //camera looks at cam_target
}
wait(1);
}
}
/*function camera_move() //alternate method...no offset funtionality
{
while(cam_ptr == null) { wait(1); }
while(cam_active == 1)
{
if(cam_ptr.flag1 == 1) //still camera
{
vec_set(camera.x, cam_ptr.x);
vec_set(camera.pan, cam_ptr.pan);
}
else //pivot camera
{
vec_set(camera.x, cam_ptr.x);
vec_set(temp, player.x); //assign to temp
vec_sub(temp, camera.x); //get player's distance from camera
vec_to_angle(camera.pan, temp); //camera looks at player
}
wait(1);
}
}*/
action player_action //assign to player
{
wait(1);
if (player == null) { player = me; }
my.narrow = on;
//my.fat = on;
//my.shadow = on;
//my.cast = on;
//put any other player flags here
cam_active = 1;
camera_move();
init_cameras();
//player while loop will go here
}
My User Contributions master list - my initial post links are down but scroll down page to find list to active links
|
|
|
Re: The Ultimate Resident Evil Camera
[Re: Orange Brat]
#38208
12/20/04 03:39
12/20/04 03:39
|
Joined: Jan 2004
Posts: 3,023 The Netherlands
Helghast
Expert
|
Expert
Joined: Jan 2004
Posts: 3,023
The Netherlands
|
yeah i know all those pointers suck, but heck, it works flawless, and there is no useless point about them:P i have had that idea since ever, i dunno if you remember (together with ayrus in A5 later period time it was) i was the guy that made that "resident evil" alley, and i tried to explain this idea to you once too, but you didnt understood really. well now i took the time to learn c script and can realise my own idea's. atm i am working on a resident evil style tut, alltogether with zombie "ai". as one of the first things, the camera gets covered (busy with that atm), so if it's finished (if ever, this tut was started for the tutorial A6 contest :P) you'll get the scripts to see regards,
|
|
|
Re: The Ultimate Resident Evil Camera
[Re: Helghast]
#38211
12/20/04 04:08
12/20/04 04:08
|
Joined: Mar 2001
Posts: 3,298 Beverly, Massachusetts
Rhuarc
Expert
|
Expert
Joined: Mar 2001
Posts: 3,298
Beverly, Massachusetts
|
Quote:
it is just a lot of code, cuz if you want 10 camera area's, it need 20 pointers.
Actually, this isn't true . A little known fact is that you can store pointers in an array and draw them back out into a "real" pointer to access an object, so:
Code:
define MAX_CAMERAS,20; //hold up to 20 cameras
var camera_objects[MAX_CAMERAS];
var camera_index=0;
function register_camera()
{
if(camera_index>=MAX_CAMERAS){beep; return(0);}
camera_objects[camera_index]=my;
camera_index+=1;
return(1);
}
action my_camera
{
register_camera();
// ... rest of code here
}
entity* temp_camera;
function get_closest_camera() //finds the closes camera object to PLAYER
{ //returns the pointer to the nearest camera
var i;
var best_dist;
var best_pointer;
while(i<camera_index)
{
temp_camera = camera_objects[i];//temp_camera now points to the next camera registered in the array
if(vec_dist(temp_camera.x,player.x)<best_dist)
{
best_dist=vec_dist(temp_camera.x,player.x);
best_pointer=temp_camera;
}
i+=1;
}
return(best_pointer);
}
function test_best_cam() //moves the camera to the closest camera object to the player and rotates to the same angle as the camera object.
{
temp_camera=get_closest_camera();
vec_set(camera.x,temp_camera.x);
vec_set(camera.pan,temp_camera.pan);
}
on_b = test_best_cam;
That should be enough to get you started
-Rhuarc
|
|
|
Re: The Ultimate Resident Evil Camera
[Re: Rhuarc]
#38212
12/20/04 04:32
12/20/04 04:32
|
Joined: Aug 2000
Posts: 7,490
Orange Brat
OP
Senior Expert
|
OP
Senior Expert
Joined: Aug 2000
Posts: 7,490
|
I haven't tested this, but one way to have more than one look at object per level may be to change its action to this:
Code:
action set_cam_look_at //assign to look at object
{
my.passable = on;
my.invisible = on;
while(1)
{
if(my.skill1 == cam_ptr.skill1)
{
cam_factor = my.skill2;
cam_look_at = me;
}
wait(1);
}
}
You'd have to make sure to include 1 entity per each camera/trigger and make sure each trio's skill1 matches. The entities' skill2 would be your cam_factor value, so you could assign different offsets to each one if desired.
Like I said I haven't tested it, but I don't see why it wouldn't work. If for whatever reason it failed, you'd have to set it up using an array with handles like with the cams and triggers. When you call the get_cam function would be when you called out for a new look at entity.
My User Contributions master list - my initial post links are down but scroll down page to find list to active links
|
|
|
|