by Ben Tyers
if global.level<13 exit;
if can_shoot_2==false exit;
alarm[1]=room_speed;
show_debug_message("Missile 2");
var xx = x + lengthdir_x(64, image_angle);
var yy = y + lengthdir_y(64, image_angle);
missile=instance_create_layer(xx,yy,"Missiles",obj_player_missile;
missile.image_angle=image_angle;
missile.direction=image_angle;
missile.speed=10;
can_shoot_2=false;
alarm[2]=room_speed*1.5;
The code for weapon 1 and 2 addon for top and bottom Alarm Event code is:
alarm[0]=(room_speed*3)+room_speed*5/global.shoot_speed;
ang=image_angle;
xx = x + lengthdir_x(32, ang);
yy = y + lengthdir_y(32, ang);
bullet=instance_create_layer(xx,yy,"Missiles",obj_bullet_1);
bullet.direction=ang;
bullet.speed=5;
bullet.image_angle=ang;
if global.level<6 exit;
bullet=instance_create_layer(xx,yy,"Missiles",obj_bullet_1);
bullet.direction=ang-30;
bullet.speed=5;
bullet.image_angle=ang-30;
bullet=instance_create_layer(xx,yy,"Missiles",obj_bullet_1);
bullet.direction=ang+30;
bullet.speed=5;
bullet.image_angle=ang+30;
We’ll change that to:
alarm[0]=(room_speed*1.5)+room_speed*5/global.shoot_speed;
ang=image_angle;
xx = x + lengthdir_x(32, ang);
yy = y + lengthdir_y(32, ang);
bullet=instance_create_layer(xx,yy,"Missiles",obj_bullet_1);
bullet.direction=ang;
bullet.speed=7;
bullet.image_angle=ang;
if global.level<6 exit;
bullet=instance_create_layer(xx,yy,"Missiles",obj_bullet_1);
bullet.direction=ang-30;
bullet.speed=7;
bullet.image_angle=ang-30;
bullet=instance_create_layer(xx,yy,"Missiles",obj_bullet_1);
bullet.direction=ang+30;
bullet.speed=7;
bullet.image_angle=ang+30;
Similary we’ll change the code for the second weapon, top and bottom from:
/// @description Calculate Position
alarm[0]=(room_speed*3)+room_speed*4;
ang=image_angle;
xx = x + lengthdir_x(32, ang);
yy = y + lengthdir_y(32, ang);
bullet=instance_create_layer(xx,yy,"Missiles",obj_bullet_2);
bullet.direction=ang;
bullet.speed=5;
bullet.image_angle=ang;
to:
alarm[0]=room_speed*4;
ang=image_angle;
xx = x + lengthdir_x(32, ang);
yy = y + lengthdir_y(32, ang);
bullet=instance_create_layer(xx,yy,"Missiles",obj_bullet_2);
bullet.direction=ang;
bullet.speed=7;
bullet.image_angle=ang;
A quick play through for a few minutes, shows a marked improvement.
HUD is not in keeping with the rest of the game
We’ll add a background for the HUD and change the font used for HUD.
A quick look on GameDeveloperStudio.com finds a suitable sprite, which matches in with the menu room.
I found suitable sprite, Papyrus
The updated HUD code now looks like this:
/// @description Draw HUD
draw_set_font(font_menu);
draw_set_colour(c_black);
draw_set_halign(fa_center);
draw_set_valign(fa_middle);
draw_set_alpha(0.5);
draw_sprite(spr_hud,0,0,0);
draw_text(200,40,"Score "+string(score));
draw_text(200,80,"Highscore "+string(global.highscore));
draw_text(500,40,"Level "+string(global.level));
draw_text(500,80,"Power "+string(global.pow));
if obj_player.shield>0
{
draw_text(800,40,"Shield Active");
}
else
{
draw_text(800,40,"No Shield");
}
draw_text(800,80,"Health "+string(health));
draw_set_alpha(1);
The game after applying, makes the game level look like the screen shot shown in Figure 6_6:
Figure 6_6: Showing updated HUD
Aspect ratio should be changed
Another bit of feedback from my beta testers was the screen ratio.
We’ll make some changes to make the game more widescreen. I quick search on the net told me that the average minimum screen resolution width is 1366, so we’ll change the window size to 1300 to accommodate this.
The steps for doing this:
Change the room size for all rooms, so they have a width of 1300
Resize sprite for in game HUD
Change drawing locations of text for in game HUD
After updates, the game room looks like that in Figure 6_7:
Figure 6_7: Showing game with new screen ratio
Collision masks are impresise
Figure 6_8 shows a sprite collision mask before changes:
Figure 6_8: Showing default mask settings
The problem with this is obvious, it will detect a collision well to the left of the sprites actual image. Due to the fact the sprite changes size with each subimage, we’ll change the collision setting to use precise per frame setting as shown in Figure 6_9:
Figure 6_9: Showing new mask settings
Using this collision masking too often can slow down your game, so should only be used when needed. We’ll also use this for the player’s sprite mask, as it also changes size each frame.
Figure 6_10 shows an updated mask, using a rectangle, which is better that the above option, when you want to set a a collision that doesn’t change too much:
Figure 6_10: Showing a manual rectangle mask
I would now go through and check the masks for all sprites used in the game.
GUI life and dots not in keeping with game style
We’ll change the colour of the health bar, and position it in the middle above the enemy. We’ll also add a player’s health bar at the bottom of the game window. See the programming section for the relevant code. The dot, used for detecting player hitting target area of the boss enemy, can just be made invisible.
To visually show damage to player
We’ll make the player flash red when it receives any damage. We’ll use a similar system to that which was used for the boss enemy.
Figure 6_11 shows game room with changes made:
Figure 6_11: Showing changes applied from beta testing
Once you’ve made all the changes based on your feedback, I suggest one further round of beta testing, just to check no bugs remain.
The download has a file Game_Final, you can play this to see the finished game.
Debugging
Another stage of development is debugging, which goes hand in hand with writing the code. You can add (and then remove when fixed) code that will display messages in the console window. This could include simple messages such as, “Collision With Enemy Detected”, which the code would be:
show_debug_message(“Collision With Enemy Detected”);
Or include values or strings of variables, for example the code below:
show_debug_message(“Health is now “+string(health));
Figure 6_12 shows the effect when added to a collision event with an enemy projectile, console window output is shown, the first with shield active so taking no damage, then again without shield showing damage taken:
Figure 6_12: Showing console window
This is great to use if only test the occasional object instance or event that happens every so often, but if you try to debug lots of things as once, the console window would fill up quicker than you could read it. Fortunately, GameMaker Studio 2 come with quite
an impressive debugger. I suggest you spend some time learning the basics of it.
Chapter 7 Programming
Programming Introduction
The Programming Introduction covers the initial basics you will need to work through the programming chapter, it is strongly suggested that you do this section before attempting anything else, if you are new to GameMaker Studio 2 / GML.
In this section we’ll make a very basic clicker type game. You'll learn the basics of how to set up and use the following:
Rooms
Sounds
Sprites
Fonts
Objects
Drawing
GUI
Alarms
INI Files
Randomization
Create Events
Mouse Events
Step Events
There will be an object instance that appears at random positions and the aim of the game is to click it before the timer runs out. Each time you successfully click the object the timer will get faster and it will magicaly jump to a new position. If you don’t click the object before the time runs out, you will lose a life – and it jumps to a new position. If you lose all your lives, then the game is over. We’ll also have basic menu that shows the current highscore of the game if present.
This game is here to show you around GameMaker Studio 2’s IDE, setting up objects and programming what they do, how to assign sprites and play sounds. It certainly wont win any awards, but does serve as great introduction. The sketch below shows the ideas for the menu room and game room:
SKETCH A
Sketch B
Resources
The resources for this mini game are in the download you got with this book. See the acknowledement page at the front of the book for the source of these assets.
Sprites
Sprites are images that will be used in your game. You’ll use them to display the player, enemy, and other graphics in your game. Images needed for this
Sprites will generally be drawn by referencing or assigning them to objects. Next, load in the sprites for this game.
There are five of them, spr_logo, spr_start, spr_target, spr_exit, and spr_lives.
You can create a new sprite by clicking the right-clicking where shown in Figure 7_1:
Figure 7_1. Showing where to click to create a sprite
Then select Create Sprite as shown in Figure 7_2:
Figure 7_2: Creating a new sprite
Name the sprite spr_logo and click the import button, as shown in Figure 7_3:
Figure 7_3: Naming sprite and clicking import
Select spr_logo, shown in Figure 7_4:
Figure 7_4: Selecting sprite image
Name the sprite spr_logo and click Load Sprite, select the file shown below, then Open, set the Origin to the center, the setting for this is shown in Figure 7_5:
Figure 7_5: Setting the origin to middle center
Repeat this for the remaining sprites, naming them spr_exit, spr_lives, spr_start, and spr_target. Set the origin of all sprites to middle center. The origin is point in the sprite where it will be positioned in the room.
When done, the resources tree will look like that in Figure 7_6. You can change the order if you want to by clicking and dragging an asset.
Figure 7_6: Showing sprite resources
This game only uses a few sprites, though some games can run into many hundreds. You can organize sprites (or other assets) by right-clicking in the resource’s tree and creating a folder. You can then drag the assets to the created folder. You can sort by the room, or the type or any other way you want.
Rooms
Note: When starting out, ensure all rooms have the same size settings, for example a width of 800 and a height of 400. If rooms have different sizes then anything drawn may be distorted.
Rooms are where the action takes place and where you put your objects. You’ll use these objects to display graphics, process user input, play sounds, and make other things happen.
We will create two rooms. The first will be a splash screen that shows some information about the game, while the second room will be where the actual gameplay takes place. First create two rooms; name them room_menu and room_game. Set the room size for each as 800 by 400.
You can do this by clicking the right clicking where shown in Figure 7_7 and selecting Create Room:
Figure 7_7: Creating a room
Right click on the room room0 in the resource tree and select rename, rename as room_menu. Set the room dimensions as shown in Figure 7_8:
Figure 7_8: Setting room dimensions
Repeat this process for room_game, again setting the dimensions to 800 by 400.
The room at the top of the section of rooms in the resources tree will be the first room to run when the game starts. Ensure that room_menu is the first room to run.
Sounds
Sounds can be music or sound effects. You name each one and use code later to play the sound when you want to hear it. We will load them now, so we can simply refer to them later.
The example uses two sounds: snd_click and snd_miss.
You can do this by right clicking and selecting the the Create a sound option, as shown in Figure 7_9:
Figure 7_9. Create a new sound
Select the appropriate sound from the resources folder as shown in Figure 7_10, and name as snd_click:
Figure 7_10: Loading in a sound resource
Repeat this with the sound file snd_miss.
Fonts
If you want to display text or variables on screen in your game, you’re going to need to define and name some fonts. You can then set drawing to this font when you want text or variable values displayed. A font can be created by clicking the Create a font button by right-clicking where shown and select Create Font:
Figure i-11. Creating a font
Set the font name as font_hud and the size as 20 Arial as shown in Figure 6_12:
Figure 7_12: Naming and setting a font
Objects
Objects are the life blood of GameMaker Studio 2. Objects are used for displaying sprites, playing sounds, drawing text, detecting movement, processing functions, performing math calculations, and more.
Next we'll create the objects. There are five of them: obj_logo, obj_start, obj_target, obj_exit, and obj_hud.
First create the object obj_logo and assign the sprite to it.
This can be done by right clicking on Objects in the resource tree and selecting Create Object.
Name this object as obj_logo, as shown in Figure 7_13:
Figure 7_13: Creating a new object
Next is to assign a sprite to this object, assign the sprite spr_logo as shown in Figure 7_14:
Figure 7_14: Assigning a sprite to an object
Then click ok.
Next create a new object, obj_start and assign the sprite spr_start.
The next step is to program some Events. Events are things that happen. The events you’ll use most are the Create Event, Step Event, Alarm Event, and Draw Event. These can be set up using GameMaker Studio 2’s built-in GUI.
Do this by clicking Add Event then Create Event, as shown in Figure 7_15:
Figure 7_15: Making a create event
Drag the windows around using the Middle Mouse Button, so the window looks like that shown in Figure 7_16:
Figure 7_16: Showing window with create code in focus
In the open window, enter the following code:
/// @description Set Up
//see if ini file exists and load saved score ini_open("savedata.ini"); //open file savedata.ini
global.highscore = ini_read_real("score", "highscore", 0); //set global.highscore to value or set as 0 if no value present
ini_close(); //close ini file - always do this after loading or saving data
//set starting values for game:
score=0;
lives=5;
This code will load any high score from a previous play of the game to the variable
global.highscore, set current score to 0, and lives to 5. It is not important at this stage to understand this code. The purpose of this exercise is to learn how to add GML code to an event.
When you’ve added the code, the open window will look as shown in Figure 7_17.
Figure 7_17. Showing code added
Next create a new event, a Mouse Left Button Pressed Event as shown in Figure 7_18:
Figure 7_18: Creating a mouse left button released event
The code for this event is:
/// @description goto the room room_game
room_goto(room_game);
Next open up obj_logo and add a Draw Event by clicking Add Event followed by Draw Event, as shown in Figure 7_19:
Figure 7_19: Selecting a draw event
The code for this event is:
/// @description Drawing Stuff
draw_self(); //draws sprite assigned to this object
draw_set_font(font_hud); //set font
draw_set_halign(fa_center); //set horizontal alignment for drawn text
draw_set_colour(c_white); //sets drawing colour as black