3D_for_GML:_Gravity - hpgDesigns/hpgdesigns-dev.io GitHub Wiki
1.1 Using gravity
Gravity and friction are used in 2D games as you will probably know. This tutorial shows how to use gravity (and friction) in 3D. It even shows how to use gravity interactively. Gravity and friction can change based on events that you, the programmer or game designer, choose. In this case, a ball object behaves differently under water than above water. If you run the gm6 file of this tutorial, you will be able to control a character (with the WASD and Up/Down arrow keys). Let’s take a look at the scripts that are used in the gm6 file of this tutorial about gravity. Let’s simply start at the top of the list and work our way down.
1.2 Setting up values
The first script is called scr_ini_character. This is the initialization (or setup) script of the object obj_character. It holds the following code:
//initialise character
speed = 4;
zspeed = 0;
zgravity = 0.25;
zfriction = 0.99;
friction = zfriction;
As you can see, there are two types of variables: the ones which deal with the normal things like speed and friction and the ones that start with z. If you are familiar with GML (Game Maker Language) you will recognize the gravity and friction values. The kind of gravity this tutorial is about is the gravity of the z value: zgravity.
1.3 More scripts
If you’ve done the tutorial Getting Started with 3D, the next script (scr_start3d) should look very familiar. In this script 3D mode is set up (initialised). The next script in the list is scr_camera. It is used to draw what the camera sees:
//draw what the camera sees
x = obj_character.x + cos((obj_character.direction + 180)*pi/180)*128;
y = obj_character.y - sin((obj_character.direction + 180)*pi/180)*128;
z = obj_character.z + 16;
xt = obj_character.x
yt = obj_character.y
zt = obj_character.z
d3d_set_projection(x, y, z, xt, yt, zt, 0, 0, 1);
The values x, y and z are set to indicate the point from which to look. The point from which to look is based on the position of obj_character and obj_direction). The value of 128 is used to define the distance of the camera to the object it faces. The value of 16 is used to keep the camera at the center of obj_character. The point the camera looks at is simply the position of obj_character. The next script scr_character is used to draw the character object, in this case a ball (sphere or ellipsoid):
//draw the character
d3d_transform_set_identity();
d3d_transform_add_rotation_y(-speed*4);
d3d_transform_add_rotation_z(direction);
d3d_transform_add_translation(x, y, z);
d3d_draw_ellipsoid(-16, -16, 0, 16, 16, 32, background_Get_texture(bk_character), 1, 1, 32);
d3d_transform_set_identity();
Transformation was used to add some rotation to the object. Don’t worry about these lines of code now, because they are not essential to the subject of this tutorial. They just add some animation to the character, making sure it tilts in the direction it flies in. The second to last line draws the actual ellipsoid. The next script scr_declare_z declares the z value (see Z Values).
//draw flame if pressing up
if keyboard_check(vk_up)=false && keyboard_check(ord('W'))=false then exit;
//draw jet flame
d3d_transform_set_identity();
d3d_transform_add_rotation_y(-speed*4);
d3d_transform_add_rotation_z(direction);
d3d_transform_add_translation(x, y, z);
draw_set_color(c_white);
draw_set_blend_mode(bm_add);
d3d_draw_ellipsoid(-8, -8, 16, 8, 8, -random(32), background_get_texture(bk_flame), 1, 2, random(16)+5);
draw_set_blend_mode(bm_normal);
d3d_transform_set_identity();
The first line checks to see if the W key is pressed. If it isn’t, we exit the script. Next some transformation scripts are used (again) to create some simple animation of the flame. It just makes sure the flame is drawn on the right spot when the character object tilts. Next, the draw color is set to white. And the blend mode is set to add. This means that the flame that is drawn (in the next line) is drawn as if it lights up the screen. It is drawn on like a light, sort of. Just run the gm6 of this tutorial and you will probably see what I mean. In the next script (scr_make) some objects are created. The script after that is scr_move which holds this code:
//perform the movements
z += zspeed; //perform zspeed on z
zspeed -= zgravity //perform zgravity on zspeed
zspeed *= zfriction //perform friction on speed
The z value is changed based on zspeed, zgravity and zfriction. Note that zgravity is a negative value, decreasing z, making the object fall. Zfriction is used to slow the object down, or, in other words: to decrease zspeed. The up and down keys are used to move the object up or down. The next script scr_move_down make sure the object moves down. Our character will have a kind of rocket or jet engine which makes it fly up but it can also move forward. In the next script scr_move_forward this is taken care of:
//move forward
if speed<16 then speed += 0.5;
Note that this is not a z based value. It is a standard value, so to speak, used for motion in the x-y plane. The next script is scr_move_up which makes the character move up.
1.4 Using gravity interactively
The script after that (scr_move_z) holds the following code:
//check z values
if z<-256 then {friction=2; z=-256; zspeed*=0.25; zgravity=-0.1; zfriction=0.8; exit;} //rock bottom
if z < 0 then {friction=0.25; zgravity=0.1; zfriction=0.5} //underwater
if z > 0 then {friction=0.1; zgravity=0.5; zfriction=0.99;} //above water
if z > 2048-256 then {zspeed*=0.9; friction=2; zgravity=2;} //stay within limit of sky bubble
This is the heart of the gravity calculation. Speed, gravity and friction are defined based on the z value of the character. If the character hits rock bottom, this is where the z motion values are set. For more information about this, see Z Detection.
1.5 Some more scripts
The next two scripts, scr_turn_right and its lefty counterpart, hold no surprises in their code. The next script is scr_world in which the world is drawn. The code should speak for itself, I think. The last script is scr_wrap. It makes sure the character jumps to the beginning of the room when it reaches the end.