3D_for_GML:_Stairs_&_ramps - hpgDesigns/hpgdesigns-dev.io GitHub Wiki

7.1 Setting up the objects

This tutorial is about Stairs and ramps. We will see that there is no real difference between them. The only difference is in the way they look, but not in the way they work. To see how it works, let’s take a look at the objects and scripts we will use. There are four objects that we will use: a camera (obj_camera), a floor (obj_floor), a block (obj_block) and a ramp (obj_ramp). The camera is needed to view the scene (an alien planet). It also serves as our character in first person view. The floor will serve as our ground object that is at z value 0 (zero height). We will need the block objects to walk on and the ramp object to get onto the blocks.

7.2 Setting up the scripts

Like I said, we will also use scripts. Let’s take a look at all of them and see what they do. The script ‘scr_start3D’ sets up the 3D mode as usual (see tutorial ‘Getting started with 3D’). The script ‘scr_camera’ should also look familiar (see Specific Use of Sine). The code looks like this:

//draw what the camera sees
xt = x + cos(direction*pi/180);
yz = y - sin(direction*pi/180);
zt = z + zdirection;

d3d_set_projection(x, y, z+64, xt, yt, zt+64, 0, 0, 1);//64 is character's height from z (feet)

Note that we will not use sine for the zdirection of the camera (pitch). But it still works. The script ‘scr_declare_z’ should not surprise you either (see Z Values), nor should the script ‘scr_mouselook’ (see Z Detection). The script scr_Block simply draws a block and the script scr_Floor does the same for the ground. No big surprises so far, right?

7.3 Bumping against blocks

We don’t want our camera (or character) to move inside the blocks, so we will want the camera to bump against the blocks when we are not on top of them. We will do this using the script ‘scr_camerabump’:

//camera bumps into solid things
x = xprevious;
y = yprevious;
speed = 0;

We will call this script when we need it. (Calling a script means executing or running a script which is a piece of code). When the camera object (obj_camera) collides with a block we will run this script ‘scr_blockcheck’. We will put an event in the camera’s Collision event. The script (scr_blockcheck) looks like this:

//check for bumping against blocks
if collision_circle(x, y, 2, obj_block, false, false) then
{
    near = instance_nearest(x, y, obj_block);
    if near.z >= z then script_execute(scr_camerabump);
}
else
{zgravity = 1;}

First we will check to see if the character is touching a block. If it’s not, the gravity will be switched on (see last line of code). If the character is touching a block, we will find the nearest block and check to see if its z value is bigger or equal that of our character’s z. If it is, we will execute the script using the ‘script_execute’ command. This means we will be able to walk on blocks (zgravity is 0) but we will fall off the blocks when we are not on them (zgravity is 1). (More about the use of gravity can be found in the tutorial Platforms).

7.4 Walking on ramps

In the Step event of our camera object we find two scripts, the first one being ‘scr_move’ which holds the following code:

//check for ramps
if collision_circle(x, y, 2, obj_ramp, false, false) then
{
    zgravity = 0; zspeed = 0;
    near = instance_nearest(x, y, obj_ramp);
    z = 48 - distance_to_point(near.x, near.y);
}
else
scr_execute(scr_blockcheck);

First we check to see if there is a ramp. If there isn’t, we execute the script ‘scr_blockcheck’ again (read previous paragraph). If there is a ramp, we will be able to walk on it by setting the zgravity and zspeed to zero and finding the nearest ramp object (obj_ramp) and setting our character’s (or camera’s) z to the height of the character (48) minus the distance to the point (x,y) of the nearest ramp.

If you take a closer look at the sprite of the ramp (spr_ramp_east), you will see where the origin of the sprite is. We will use that origin to calculate the height of the character. We will want the character to rise (higher z value) as he reaches the top (origin) of the ramp. The sprite is called ‘spr_ramp_east’ because it looks east. In a game, you might want to create more ramps facing other directions too.

The second script found in the Step event of our camera object is ‘scr_move_z’. The code it holds is:

//perform gravity
z += zspeed
zspeed -= zgravity;

if z<0 then {z=0; zspeed = 0; zgravity = 0;}

This simply makes sure the speed and gravity are working and that the character can’t go below ground level (z value of zero).

7.5 Switching between ramps and stairs

The code in script ‘scr_ramp’ looks like this:

//draw ramp
if stairs = 0
    {d3d_draw_floor(x-64, y-32, z, x, y+32, z+48, background_get_texture(bk_ramp), 1, 1)}
else
//draw stairs
{
    d3d_draw_block(x, y-32, z, x-64, y+32, z+12, background_get_texture(bk_ramp), 1, 1)
    d3d_draw_block(x, y-32, z+12, x-48, y+32, z+24, background_get_texture(bk_ramp), 1, 1)
    d3d_draw_block(x, y-32, z+24, x-32, y+32, z+36, background_get_texture(bk_ramp), 1, 1)
    d3d_draw_block(x, y-32, z+36, x-16, y+32, z+48, background_get_texture(bk_ramp), 1, 1)
}

The first line checks to see if the variable stairs is zero. If it is, we draw a ramp image (with d3d_draw_floor.) Otherwise, we will draw a succession of blocks also known as stairs. Switching between ramps and stairs is done in the Mouse event of the ramp object (obj_ramp). It holds the code to switch the variable stairs from zero to one and one to zero (toggle):

//change into stairs
stairs = abs(stairs)-1;

Note that you don’t need an if… then… loop to toggle the stairs value (one or zero). Clicking the left mouse button toggles between a ramp or stairs shape. The underlying principle in code remains the same. Like I said: the only difference is in the way they look, not in the way they work.