3D_for_GML:_Third_person_view - hpgDesigns/hpgdesigns-dev.io GitHub Wiki
1.1 Understanding third person view
We’ve talked about first and third person views before in the First person mouselook tutorial. This is what I wrote:
Basically, there are two types of views in games: first person and third person. Originally, these are grammatical terms used for describing the perspective in language or literature: first being “I”, second being “you” and third being “he/she/it”. In the world of game graphics, these terms are not used to describe the narrative perspective but the visual perspective (or type of view). Also, by the very nature of visual perspective the second person view is non-existent. You may have seen text-based adventure where it says something like: “You are in a desert-like landscape, strewn with large rocks”. This is a second person perspective in language. Any visual illustration of that description would be either first or third person. This tutorial will show you how to create a first person view with mouselook. Mouselook is when the mouse can be used to have the character look around in the virtual 3D world. This tutorial will show you how to create a third person view in which the camera stays behind the game character. We will create a camera that stays behind the main character that is controlled by the player.
The main difference between first and third person view is this: first person view means the character and camera are at the same point in space (“I”), while in third camera and character are separate. This enables the player to view himself from a different point in space as if he is watching someone else (“he/she/it”). So, how can this be done in GM? Let’s walk through the objects and scripts needed to make third person view work. Three objects were used in the gm6 file that comes with this text: a character object that moves around, a camera object that will follow the character and a building that the character collides with. That’s it. The first script used is called col_car_building. It manages the collision of the car with a building, simply slowing down the car when it hits a building:
speed*=.25;
The second script draws the building:
<syntaxhighlight lang="edl">
if distance_to_object(obj_camera)>1024+256 then {exit;}
d3d_draw_block(x-63,y-63,0, x+63,y+63,256, tex,2,2);
d3d_draw_block(x-65,y-65,256, x+65,y+65,258, obj_world.tex2,1,1);
First line makes sure the building is not drawn if too far away from the camera. Next lines draw the textured blocks that make up the building. The texture is set in script scr_ini_building, like this:
tex=background_get_texture(bac_building);
==1.2 Drawing a third person camera==
The next script (draw_camera) draws what the camera sees.
<syntaxhighlight lang="edl">
//to
xt=x+cos(degtorad(direction));
yt=y-sin(degtorad(direction));
zt=z-tan(degtorad(zdirection));
//draw
d3d_set_projection_ext(x,y,z, xt,yt,zt, 0,0,1, 90,1.33,1,8192);
Notice how the camera uses its own location as the from point for the projection and its own direction and zdirection for the to point of the projection. The camera is a separate object that follows the car around at all times. The camera object will be used to initialize 3D mode, in script scr_ini_camera:
d3d_start(); //go to 3d
d3d_set_perspective(true); //use perspective?
d3d_set_hidden(true); //remove hidden surfaces?
draw_set_color(c_white); //drawing color
d3d_set_fog(true,c_black,512,1024); //use fog?
d3d_set_lighting(false); //use lighting?
d3d_set_culling(true); //use culling?
d3d_set_shading(true); //smooth textures when lit?
texture_set_interpolation(true); //smooth pixels?
//set values
z=12;
zdirection=0;
//create instances
instance_create(x+64,y,obj_character);
instance_create(0,0,obj_world);
for (h=1;h<16;h+=1)
{
for (w=1;w<16;w+=1)
{
if random(1)>.8 then
{
instance_create(w*256,h*256,obj_building);
}
}
}
The z value sets the height of the camera above the floor. In the last couple of lines buildings will be placed in the room randomly within a grid, using a loop structure. The camera can be moved up or down (above the ground) by the script ‘scr_cam_down’:
if z>12 then z-=4;
and ‘scr_cam_up’:
if z<512 then z+=4;
This way the player can change the perspective from behind the car to above the buildings.
1.3 Drawing the character
In the script ‘draw_character’, the car is drawn as a simple textured block, turned to point in the direction it is heading. Next, a simple shadow is added to enhance the illusion of depth.
d3d_transform_set_identity();
d3d_transform_add_rotation_z(direction);
d3d_transform_add_translation(x,y,z);
d3d_draw_block(-16,-12,4, +16,+12,+16, tex,1,1);
draw_set_blend_mode(bm_subtract);
d3d_draw_block(-15,-11,1, +15,+11,+1, -1,1,1);
draw_set_blend_mode(bm_normal);
d3d_transform_set_identity();
Just your basic rotation. (More info on rotation can be found in the Rolling Ball tutorial). The character will be followed around by the camera object as we will see later on. The character is set up in script ‘scr_ini_character’:
z=0;
friction=.1;
tex=background_get_texture(bac_character);
1.4 Drawing the world
The world will consist of a sky and floor. First the sky is drawn (without fog) and then the floor by the script ‘draw_world’:
d3d_set_fog(false,c_black,512,1024); //use fog?
d3d_draw_ellipsoid(obj_character.x-2048,obj_character.y+2048,-2048, obj_character.x+2048,obj_character.y-2048,2048, tex,4,4,16);
d3d_set_fog(true,c_black,512,1024); //use fog?
d3d_draw_floor(0,4096,0, 4096,0,0, tex2,16,16);
Notice how the sky is drawn around the character so that it always stays at the same distance. The world textures are set up in script scr_ini_world:
tex=background_get_texture(bac_Sky);
tex2=background_get_texture(bac_Floor);
1.5 Moving the camera
So, how will the camera be able to follow the character around the room? Well, let’s take a look at the lines in script mot_camera:
dir=point_direction(x,y,obj_character.x,obj_character.y);
dis=point_distance(x,y,obj_character.x,obj_character.y);
if dis>16 then
{
direction=dir;
zdirection=-point_direction(0,0,dis,z);
}
if dis>64 then
{
motion_set(dir,dis/16);
}
else
{
speed*=.9;
}
In the first two lines the direction and distance of the camera are set in relation to the car object. The next couple of lines prevent the camera from flipping too much when the car is driving backwards. The last couple of lines make the camera follow the car, by speeding it up and slowing it down, relative to the distance between camera and car. If the car moves away from the camera, the camera speeds up. And it slows down again when the car is near.
1.6 Moving the character
The motion of the car is controlled by the player using the keyboard in script mot_character:
//front & back
if keyboard_check(ord('W')) then {speed+=.25;}
else
if keyboard_check(ord('S')) then {speed-=.5;}
//left & right
if keyboard_check(ord('A')) then {direction+=speed/4;}
else
if keyboard_check(ord('D')) then {direction-=speed/4;}
//limit speed
if speed>25 || speed<-2 then {speed*=.95;}
In the last line, some speed limits are set for the car.