Introduction To Game Design & Programming in GameMaker Studio 2
Page 15
image_index – Set a specific sub image.
sprite_get_number(index) – Returns how many sub images a sprite has.
draw_sprite_ext(); - Allows drawing with additional settings.
For example, you may a have a different sprite for the character moving left and moving right. These could be sub images 0 and 1. You can set the sub image that is being shown by using image_index, for example, when the player is moving left:
image_index=0;
And when it’s moving right:
image_index=1;
Remember you can set image_speed to 0 to set the frame so it doesn't animate away on its own; do this in the object’s Format for Event or change the above code to:
image_speed=0;
image_index=0;
And when it’s moving right:
image_speed=0;
image_index=1;
Basic Projects
• A) Draw an animated character sprite that animates when moving right.
• B) Set it so the coin animates through its cycle 4 times, then jumps to a new position and starts the cycle again.
• C) Make simple top-down maze game with a character that points in the direction the player is moving.
Advanced Project
• D) Draw a sprite that changes perspective (size) depending on the y location.
Appendix 8 Health, Lives & Score
Most casual games will have some sort of health, lives, or score system. Players usually start off with full health and lose some of it when they get hit by an enemy bullet, land on spikes, or collide with something they shouldn’t. Once a player loses all their health, they usually lose a life and are transported back in the level to a re-spawn site. Different games have different goals, though with a lot of them the aim is to achieve the highest score possible. Fortunately GameMaker Studio 2 makes it really easy to set up such a system described above.
health, lives, and score are built-in global variables. Which means you don’t need to put “global.” before them to access or change the value from any instance.
You would use global. when using your own variables that you want multiple objects to be able to use, for example: global.level, global.hp.
Note: health, lives, and score are basically global variables; as such it should only be used for one instance, usually the player. If you need to monitor health, lives, or score from more than one object, you’ll need to create your own instance or global variables, for example, my_health or global.enemy_1_health.
Most games you create are likely to have a number of lives and / or health, and a score to keep track of. You’re not obliged to use the built in variables. Lots of casual games have an aim of trying to get the highest score.
health, lives, and score can be drawn on the screen in text or graphically.
At the start of the game you’ll want to set the initial values for these (or load them as saved from a previous play). An example is shown below.
score=0;
health=100;
lives=5;
Note: health starts with a default value of 100; however, I prefer to set it so I may change it later, depending on what’s required for the game.
Health
You can treat all of these: health, lives, and score the same as you would any variable; you can test, change, and draw these variables.
Some examples:
In the Collision Event of enemy bullet with the player.
For example, in a bullets Collision Event with a player object:
health-=1;
instance_destroy();
Or if you are doing the Collision Event within the player object:
health-=1;
with (other) instance_destroy();
Note: it is very important to destroy the bullet at this point, to prevent health being reduced by 1 each step / frame.
In the Collision Event with a health bonus object. As before, destroy the health bonus straightaway to prevent it being added every step:
health+=5;
with (other) instance_destroy();
Note: health is not capped at 100. You can make use of this depending on what your game requires. For example, you could test if it’s greater than 100 and cap at 100, or create an extra life if it reaches a determined value.
In a Step Event you may want to constantly check the health and lives variables:
if health<=0
{
lives-=1;
health=100;
}
if lives<=-1
{
room_goto(room_game_over);
}
You can draw the value health just as you would any other real variable.
There is also a function for drawing a health bar, Draw the health bar. For example:
draw_healthbar(x-50,y-40,x+50,y-20,(health/100)*health,c_red, c_green,c_green,0,true,true);
Which would draw a health relative to the instance drawing it. Sometimes, if not relative to an instance you may use a control object to draw the player’s health, lives and score.
Lives
As with other variables, you can test, change, and draw the lives variable. Draw score:
draw_text(50,50,lives);
You can also draw lives graphically using a bit of code, for example
for (var i = 0; i < lives; i += 1)
{
draw_sprite(spr_lives,0,50+(50*i),50);
}
This will space out the lives at 50 pixel intervals; this will look like what is shown in Figure A_8_1.
Figure A_8_1: Showing lives drawn using code
Score
You can draw the score using GML, for example:
draw_text(30,30, "Score "+string(score));
You may also wish to display this graphically, for example, to indicate how many points are needed until you reach the next level. This will depend on the style of game you’re creating.
For example, you have a game that levels up after every 1000 points. The following code would draw a bar at the top of the room, visually displaying how many points the player needs for the next level and their current level. This example assumes a room width of 800 and a font font_score set up an Arial size 20.
Step Event
level=(score div 1000)+1; //calculate level bar_width=(score mod 1000)*.8; //make bar fit room width of 800
Draw Event or Draw GUI Event
/// @description Draw Info
//draw background of bar
draw_set_colour(c_red);
draw_rectangle(1,1,800,40,false);
//Draw Current Level
draw_set_colour(c_green);
draw_rectangle(1,1,bar_width,40,false);
//Draw Over Hud
draw_set_colour(c_blue); draw_rectangle(1,1,800,40,true);
//Draw Current Level in Text
draw_set_font(font_score);
draw_set_colour(c_white);
draw_set_halign(fa_center);
draw_set_valign(fa_middle);
draw_text(400,25, "Level="+string(level));
Basic Projects
• A) Draw a health bar across the whole of the top of the game window, draw lives under this as images. Allows keys Q and W to change health value, and A and S to change lives. Limit health to a maximum value of 100.
• B) Draw lives as images, but make the sprite grow and shrink. Do this through code or editing sprites.
Advanced Projects
• C) Draw a bar at the top of the screen that draws the current score mod 1000. For each 1000 score increase the level by 1. Also draw score and level as text. Gains a level for each 1000 points. Allow key Q to increase the score/
• D) Create 3 level buttons that each become clickable for every 1000 score points. Show they are clickable using different sub images.
Appendix 9 Mouse
Mouse interaction is valuable in quickly providing inputs into a game. Object movement and selection is more intuitive and doesn’t require memorization that may be required with k
eyboard interaction. This section serves as an introduction to using the mouse.
Mouse input can be used for:
Clicking on menu buttons
Creating a location to move an object to
Making an object move
Using the middle button to change weapons
Making an object point in the direction of the mouse
Detecting screen presses (in iOS / Android)
Displaying mouse cursor
Display stats of a clicked object
About 99% of the time you'll want to constantly check the position of the mouse or mouse button interaction. This can be achieved by placing your code at the Step Event.
As with keyboard interaction, you can test the mouse just being clicked, being held down, and being released, for example:
if mouse_check_button(mb_left) // check for being held down
{
//do something
}
if mouse_check_button_pressed(mb_left) //activates one time only when button is pressed
{
//do something
}
if mouse_check_button_released(mb_left) // activates one time only when button is released
{
//do something
}
The same logic applies when using Mouse Events.
The position of the mouse can be found using:
mouse_x the x position of the mouse in the room.
mouse_y the y position of the mouse in the room.
For mouse buttons actions you can use, for example:
if (mouse_check_button(button))
Where button can be any of the following:
mb_left
mb_right
mb_middle
mb_none
mb_any
mb_middle means middle button
mb_none means no button
mb_any means any mouse button
You can also use the Mouse Events instead of GML, though using GML will provide you with more flexibility.
Using GML you can make things happen when a mouse button is pressed. So the following, when placed in the Step Event, would make the object move slowly to the mouse’s position when the left button is pressed:
if (mouse_check_button(mb_left))
{
movement_speed=25; //Higher Number Makes Slower Speed target_x=mouse_x; //or other target position
target_y=mouse_y; //or other target position
+=(target_x-x)/ movement_speed; //target position-current
position
+=(target_y-y)/ movement_speed; //target position-current
position }
An example YYZ for the above is available in the resources.
You can also detect movement of the mouse wheel (if present):
if (mouse_wheel_up())
{
weapon+=1;
}
You can detect scroll down in a similar manner:
if (mouse_wheel_down())
{
weapon-=1;
}
You can also set the cursor to a sprite of your choice:
cursor_sprite=spr_name;
when spr_name is a sprite that exists.
You can hide the default windows cursor using:
window_set_cursor(cr_none);
There are a number of built-in cursor types, see window_set_cursor in the manual for more info. This can be used (as with cursor_sprite above) with great effect in a game. Changing the cursor depending what the player is doing or what objects are at the cursor position can give your player extra info, that is, making it clear an instance can be interacted with.
The following code will detect if the mouse is over an object and add to the score, which would increment by 1 every step if placed in a Step Event:
if (position_meeting(mouse_x, mouse_y, object_name))
{
score+=1;
}
The following code would check that the mouse is over the object’s sprite and the left mouse button is released. The code will then play a sound snd_bounce, with a priority of 1 with looping set as false.
if position_meeting(mouse_x, mouse_y, id) && mouse_check_button_released(mb_left)
{
audio_play_sound(snd_bounce,1,false);
}
There are also a number of Mouse Events that can be used instead of code, which are perfectly viable options. As with GML code, you can check for a button being held down, just pressed, or released (and you should understand the difference by now):
Basic Projects
• A) Create an object that follows only the mouse’s x position.
• B) Make the mouse cursor change when it’s over an object.
• C) Draw the mouse’s x and y positions in the bottom left of the screen. Remember to use the font and drawing colour and formatting.
Advanced Projects
• D) Create a sound board (lots of buttons each of which plays a sound when clicked with the mouse). Draw text over each button, explaining what sound it plays.
• E) Create an object that can be moved around the room with the mouse.
Appendix 10 Alarms
Alarms are useful for many timed activities or abilities that are temporarily available. Timers can enhance gameplay by creating urgency in completing an action before an ability disappears. This section covers the basics of alarms. Alarms can be used to make something happen (or stop happening) when an alarm triggers. Alarms are set to a starting value when the alarm is created.
Alarms can be used for the following:
Displaying a splash screen for a while
Making a bomb explode an amount of time after firing
Changing the player to invincible and then back again
Display a bonus object for a set amount of time
Create or move objects after an amount of time
Create basic AI systems
Limiting how quickly a player can shoot
An alarm can be set, for example, using, using the default room_speed of 30:
alarm[0]=60; //set alarm at 2 seconds
As you may wish to change the default room speed, a better code would be to use the following approach in all your alarms:
alarm[0]=2*room_speed; //set alarm at 2 seconds
By using the above method you can change the room_speed as needed without messing up your timings.
In total you can have 12 alarms for each object:
alarm[0] alarm[1]
....
alarm[10] alarm[11]
When an alarm activates (alarm goes off / runs out of time) you can detect this using an Alarm Event, which can be selected as shown in Figure A_10_1:
Figure A_10_1: Showing alarm events
You can add to an existing alarm, for example, adding 1 second:
alarm[0]+=1*room_speed;
Alarms run until they reach 0, which is when they trigger, and then count one more to -1, so you can stop an alarm by setting it to -1.
Here are some examples:
Moving to another room, room_menu after 5 seconds. You could use this in a room set up as a splash screen. For example, this could be used to display your company's logo or a graphic of some description. Create Event:
alarm[0]=5*room_speed;
Alarm[0] Event:
room_goto(room_menu);
Delaying how quickly a player can shoot, the code below would limit the rate of fire to once every 2 seconds:
Create Event:
can_shoot=true;
When player shoots, by pressing the Z key:
if can_shoot && keyboard_check(ord(“Z”))
{
//bullet creation code here
can_fire=false;
alarm[1]=2*room_speed;
}
Alarm [1] Event:
can_shoot=true;
As you can see, Alarm Events are a very useful commodity allowing us to set how often something can happen or how long something lasts.
No
te: Be careful about holding alarms open by constantly setting them. Use a flag to prevent this, as was done with can_shoot in the example above.
Basic Projects
• A) Create a program that changes the drawn text every 5 seconds, and use a list of 10
strings.
• B) Create a program with an object that moves with a speed of 1 and increases the speed of the object every 5 seconds. Also make the object wrap around the screen.
• C) Create a program that plays a random sound every 4 seconds.
Advanced Projects
• D) Create a simple system that allows the player to shoot bullets at a maximum rate of 1 bullet every 2 seconds.
• E) Create an enemy AI that changes direction randomly every 5 seconds. Make the enemy object’s sprite point in the direction that it is traveling. Also make the enemy object wrap around the screen. Set the object to shoot a bullet in the direction it is traveling every 8 seconds.
Note: You can assign an instance’s value to a variable when you create it, and then set other variables for that instance. For example:
ball=instance_create_layer(x,y,”Instances”,obj_ball);
ball.speed=2; ball.heatlh=50;
Appendix 11 Collisions
When planning on motions or deciding actions, it is often critical to see if collisions occurred with other instances within the game world. Put simply, collisions are what happens when two instances (with sprites or masks assigned) collide (their sprite or mask overlaps) with each other.
You use this to check if an instance is in collision with another, for example, a character walking on a platform in a platformer game or an enemy being hit by a player’s bullet.
For example, here are things that can be made to happen when a collision occurs:
destroy an object
create an effect
play a sound
change score, health, or lives
make something start or stop moving
create a new object
Most of the time it’s sufficient to use the Collision Event. You can create a Collision Event as shown in Figure A_11_1; just select the object you want to check a collision with.