3D_for_GML:_Sniper_zoom - hpgDesigns/hpgdesigns-dev.io GitHub Wiki

20.1 Adding animation to scope

In many a shooter, you will see a sniper scope. Let’s try and find out how a sniper zoom can be made in GM. As usual, we’ll take a look at the objects and scripts to make this possible. Take a look at the gm6 file that comes with this tutorial and you will see we’ll use a camera, a character, an overlay, a sky, a floor and a target object. From top to bottom, the first script is called ‘ani_overlay’ and it holds the following code:

ani+=0.1;
if ani>360 then ani=0;

This script will be used to add some motion (or animation) to the sniper zoom when we’re zooming in. It will make it more difficult to hit a target because the crosshairs will slowly move, as if we’re holding a rifle in real life.

20.2 Creating camera zoom

When we take a look at the camera script, most of the lines will look familiar but we’ll need to highlight some of the lines here. The first line needs a little explanation:

ani=s in(obj_overlay.ani) /128*obj_overlay.zoom;

Here you see the ani value from the previous script (ani_overlay) being used to create a ani value for the camera. This value will be added to the point the camera looks at, in these lines:

xt=xf+cos(degtorad(direction))+ani; //x to look to (with direction)
yt=yf-sin(degtorad(direction))+ani; //y to look to (with direction)
zt=zf-sin(degtorad(zdirection))+ani;    //z to look to (with z direction)

As we will see later, it’s the obj_overlay.zoom value that determines whether zoom is on or off. When zoom is on, we will view the world as if seen through the sniper scope. You should be familiar with the following code by now:

d3d_set_projection(xfrom, yfrom, zfrom, xto, yto, zto, xup, yup, zup);

It’s what has been used in the tutorials many times. To create a zoom, we will use an extended version of this code:

d3d_set_projection_ext(xfrom, yfrom, zfrom, xto, yto, zto, xup, yup, zup, angle, aspect, znear, zfar);

As you can see, four new variables have become available: angle, aspect, znear and zfar. It’s the angle value that is essential in creating a sniper zoom. Back to our camera script. The next line is:

Angle=60-obj_overlay.zoom*40;

This code sets the Angle value, depending on whether zoom is on or off. In the next line, the resulting value is used in the projection code:

d3d_set_projection_ext(xf, yf, zf, xt, yt, zt, 0, 0, 1, Angle +ani*16, 1.33, 1, 2048); //look from & to

The ani value will be added to the Angle value to create a focusing effect of sorts. The next script (scr_floor) draws the floor:

//draw floor
d3d_draw_floor(-8192, 8192, 0, 8192, -8192, 0, background_get_texture(bk_floor), 128, 128);

20.3 Adding border and crosshairs

The next script draws the overlay. More info about overlays can be found in the Overlays tutorial, by the way. Anyway, it uses this code:

//draw overlay
if zoom=0 then exit;
d3d_set_projection_ortho(0, 0, 640, 480, 0);
draw_sprite_stretched(spr_hole, 0, 0, 0, 640, 480);
draw_set_color(c_black);
draw_line(320-32, 240, 320+32, 240);
draw_line(320, 240-32, 320, 240+32);
draw_set_color(c_white);

The first line makes sure we leave the script when we’re not zoomed in. The rest of the script switches to overlay drawing (orthographic projection). It draws the black border sprite and two black lines that together will make up the scope and crosshairs.

20.4 Activating zoom

I won’t go into the next four scripts. If we skip those, we will see that the next script ‘ini_overlay’ sets up the overlay. The final script worth mentioning is ‘scr_overlay’ and it holds the following code:

//overlay on or off
if mouse_check_button(mb_right) then {zoom=1;} else {zoom=0;}

This will make the zoom value change according to the right button state. In other words, you can enter sniper zoom mode by holding the right mouse button. Simply put, sniper zoom can be created like this: you change the zoom value of the camera by choosing a low value for the angle variable in the extended camera projection code. That’s all for now.