3D_for_GML:_Platforms - hpgDesigns/hpgdesigns-dev.io GitHub Wiki
5.1. Introduction
What you will learn:
- About platform games
- Using gravity
- Designing simple levels
- Using a third person view
- Animating by deformation
- Making the character walk, jump, land and fall
5.2. About platform games
In the previous tutorials we have seen how to declare the z value and use it interactively. We used things like:
//set speed
if z>0 {speed*=0.99}
Platform games are typically games in which a horizontal flat form is used on which a character can walk, jump and get into all kinds of trouble. Height plays a crucial role in such a game.
It doesn’t make much sense to have a platform game without height differences. If you have no height differences in a platform game, there will only be one flat surface. There will have to be points where you can fall through the platform into the deep or some way to get onto higher platforms.
If you have a character that walks on a platform, he will have to be able to fall off or jump onto other platforms. The rise and fall in height is what is expressed in the z value.
5.3. Using gravity
The force of gravity is what makes platform games work. Without gravity you would have a character that can walk in mid air. Even in cartoons where the character can walk off a cliff with nothing but space beneath him, he eventually falls even if he tries to run back onto solid ground.
For our tutorial, we will take two textures: a metal surface and a water surface, because that’s really all we need. We will want the character to walk on the metal platforms and fall off them into the water surface. Our character will be allergicwater (but not to metal).
In the real world, gravity pulls all the time. In the virtual world of platform games, gravity can be switch on and off. This means we can switch gravity off for the character when it is on a solid platform and switch it on when it is not.
In paragraph 5.7 of this tutorial text you will see that gravity is used in making the character walk, run, jump, land and fall.
5.4. Designing simple levels
For the sake of simplicity we will create simple platforms, not overlapping ones (platforms that are on top of each other). Overlapping platforms can be walked over and under. Simple platforms are side by side but in different heights.
We will need to draw a level in GM’s Room Editor to place platforms at different locations and heights. To accomplish this, we will use height markers that we will place on the platform level layout. This means we can design a level, both in layout and in height (or depth).
Some height markers placed on a simple platform design. If you take a look at the gm6 file in the script scr_Marker, you will see that for each segment of the platform we will assign a z value.
//make the height
if collision_rectangle(x-32, y-32, x+32, y+32, obj_height0, false, false) then z=0*global.grid;
else if collision_rectangle(x-32, y-32, x+32, y+32, obj_height1, false, false) then z=1*global.grid;
else if collision_rectangle(x-32, y-32, x+32, y+32, obj_height2, false, false) then z=2*global.grid;
else if collision_rectangle(x-32, y-32, x+32, y+32, obj_height3, false, false) then z=3*global.grid;
else if collision_rectangle(x-32, y-32, x+32, y+32, obj_height4, false, false) then z=4*global.grid;
else if collision_rectangle(x-32, y-32, x+32, y+32, obj_height5, false, false) then z=5*global.grid;
else if collision_rectangle(x-32, y-32, x+32, y+32, obj_height6, false, false) then z=6*global.grid;
else if collision_rectangle(x-32, y-32, x+32, y+32, obj_height7, false, false) then z=7*global.grid;
else if collision_rectangle(x-32, y-32, x+32, y+32, obj_height8, false, false) then z=8*global.grid;
else if collision_rectangle(x-32, y-32, x+32, y+32, obj_height9, false, false) then z=9*global.grid;
The above code makes the heights of each platform tile. The variable global.grid defines the height grid. The actual tiles are drawn in the Draw event of the par_child object. (Parent-child method was used in the example). This is what the code for drawing the tile looks like:
//draw a platform tile
d3d_draw_block(x-32, y-32, z-8, x+32, y+32, z, background_get_texture(bk_metal), 1, 1);
When designing your own levels, it’s best to start with placing the platform tiles, then placing the height markers and finally the camera object (which also creates the character object).
5.5. Using a third person view
Of course, we will need a camera to view the scene. This is done in the camera code which looks like this:
//draw what the camera sees
//from x, y, z
xf = obj_character.z - sin(degtorad(-obj_character.direction+90))*global.zoom
yf = obj_character.z + cos(degtorad(-obj_character.direction+90))*global.zoom
zf = obj_character.z + global.zoom
//to x, y, z
xt = obj_character.x
yt = obj_character.y
zt = obj_character.z
d3d_set_projection(xf, yf, zf, xt, yt, zt, 0, 0, 1);
The first part defines the point from which to view (xf, yf, zf). It is based on the character’s position and direction, as well as on the zoom value of the camera. Sine and cosine were used in a specific way to rotate the camera in such a way that it stays behind the character. The camera looks at the object’s position (xt, yt, zt). Finally, the projection is set as you would expect (in the last line of code).
5.6. Animating by deformation
A simple jumping animation was added to make it clear to the player when he is jumping or falling and when he is not. The red ball that is the main character is deformed based on its speed. The code should speak pretty much for itself:
//animation (deform)
if abs(zspeed)<8 then deform = abs(zspeed);
//draw ball
d3d_draw_ellipsoid(x-16, y-16, z-deform, x+16, y+16, z+32+deform, background_get_texture(bk_character), 1, 1, 16);
5.7. Making the character walk, jump, land and fall
The code that deals with walking, jumping, landing and falling of the character is quite intricate. It involves quite a bit of logic. In the Step event of the character (obj_character) we find the script scr_gravity. This will basically check if the character is on a platform or not. It looks like this:
//check if jumping
if jump = 1 then exit;
//check if falling
if fall = 1 then exit;
//define gravity
if collision_point(x, y, chi_platform, false, false) then
{
znear = instance_nearest(x, y, chi_platform).z;
if z = znear then zgravity = 0;
else {fall = 1; speed +=0.2; zgravity = -0.5;}
}
In the same Step event the character is moved in the z direction:
//move in z direction
z += zspeed;
zspeed += zgravity;
//drowned
if z <-512-128 then game_restart();
Checking for landing of the character is also done in this Step event. The code looks like this:
//check if not falling yet
if sign(zspeed)>=0 then exit;
//check if falling
if sign(zspeed)<0 then fall = 1;
//land if falling
if collision_point(x, y, chi_platform, false, false) then
{
znear = instance_neareset(x,y,chi_platform).z;
if z=znear||
(z>znear && z<znear + global.grid/4)
then {jump = 0; fall = 0; z = znear; zspeed = 0; zgravity = 0}
}
I will not go into it in detail. It’s basically a lot of if this happens then do that stuff. It makes the character land on the platform tiles. A final script worth mentioning is the jumping script (found in the press Space event of obj_character) named: scr_jump. It holds the following code:
//check if jumping
if jump = 1 then exit;
//check if falling
if fall = 1 then exit;
//check if you can jump
znear = instance_nearest(x, y, chi_platform).z;
if z = znear then {jump = 1; zspeed = 8; zgravity=-0.5}
Again, a lot of checking if stuff. Basically, this script checks to see if the character is exactly on the platform and if so, makes the character jump.