GameMaker Drawing Sprites

GameMaker Drawing Sprites

Hi everyone, and welcome to the first of few blog posts covering some of the basics of GameMaker. When I started making games in 2012, I knew literally nothing about game development in general. My challenge at the time was to teach GameSalad to a group of school students in Langkawi.

Few weeks later, I began to play around with other game development tools available. GameMaker was a really great option for me because it had its own programming language, GML, which was a little more lenient and less obtuse than a lot of other languages out there. I have made dozens upon dozens of prototypes and a handful of small completed games. I want to use these blog posts to show you some of the things I wish knew when I started out.

This blog assumes you are already somewhat familiar with GameMaker and GML.

Overview and setup

We are going to be talking a lot about sprites in this post. A sprite is basically just an image that is being shown on your screen. A sprite can be a single image, or a series of images that form an animation.

First we need to break down what draw_sprite_ext(); is, and all of the arguments it uses. Draw_sprite_ext(); is an extended version of draw_sprite(); and gives us much more control over the sprite we are drawing. Primarily this function is used to draw sprites to the screen. Using this function, we can change the scale, angle, color blending, and alpha of the sprite being drawn. Check the list below for all of the arguments this function requires:

  • sprite – Index of the sprite you want to draw.
  • frame – Individual frame of the sprite you are drawing.
  • x – X position of where you are drawing the sprite.
  • y – Y position of where you are drawing the sprite.
  • xscale – Horizontal scaling of the sprite.
  • yscale – Vertical scaling of the sprite.
  • rot – Angle/rotation of the sprite.
  • color – Color blending (c_white displays as normal).
  • alpha – Alpha of the sprite. Range from transparent (0) to opaque (1).

There is a bit of setup required before we can really use this function effectively. We are going to define these arguments as variables, and throw all of it into a script so it can be used on any object.

Create a script and name it animation_init. Add the following lines:

//initialize variables for drawing, and animation.
sprite = sprite_index;
frame = 0;
xPos = x;
yPos = y;
xScale = 1;
yScale = 1;
angle = 0;
color = c_white;
alpha = 1;

frameSpeed = 1;
facing = 1;

By setting the sprite variable to sprite_index, it will use the sprite that the object has set. While we are creating scripts, we may as well create a couple of helper scripts we will need later. Create a new script called approach and add the following lines:

//approach(start, end, shift);

if(argument0 < argument1){
    return min(argument0 + argument2, argument1); 
    return max(argument0 - argument2, argument1);

This script allows you to increase a value by another value, until it reaches a maximum value. I’ll show you what we can do with this a little later. Moving on! Create another script and name it player_buttons. Add the following code:

left = keyboard_check(vk_left);
right = keyboard_check(vk_right);
up = keyboard_check(vk_up);
down = keyboard_check(vk_down);

All we are doing here is storing our keyboard inputs into variables. These are all booleans, meaning they can either be true or false. This makes it much easier to address button presses later on.

Now that we have our animation_init script ready to go, we are ready to start drawing… that is… once we have a sprite to draw! Go ahead and create a new sprite, and name it sprPlayer_Idle. Make sure this sprite has multiple frames, and each frame is different. Otherwise you won’t be able to tell it’s animating! Set the sprite origin to the x center, and y bottom. If you are using the sprites that I am using, that is 16 and 32 respectively.

Here is a link to all of the sprites I am using. I recommend downloading them and following along.

Next we need an object. Create a new object and name it oPlayer. Set your sprPlayer_Idle sprite as the object sprite. Add the Create, Step, End Step, and Draw events. Add the Execute Code action to each event. Open up the Create event code and add the following lines:


left = false;
right = false;
up = false;
down = false;

Next we move on the to Draw event. In the Draw event, add the following lines:

//draw sprite
draw_sprite_ext(sprite,frame,xPos,yPos,xScale * facing,yScale,angle,color,alpha);

Now we are almost ready to run the game and see our sprite being drawn on screen. Pretty exciting right? Create a room, name it whatever you want, and place your oPlayer object in the room. When you run the game you should see the sprPlayer_Idle sprite being drawn. However that sprite isn’t animated, and it doesn’t move. It’s just sitting there being boring. Let’s fix that.


Assuming that your sprite has multiple frames, we need to animate that sprite! Since we are manually drawing the sprite, we can’t use built in variables like image_speed to animate. However we did already define our own image_speed equivalent with frameSpeed. Create a new script, name it frame_counter, and add the following lines:

//increase frame by frameSpeed
frame += frameSpeed;

Then, create another script and name it frame_reset. Add the following lines:

//reset frame if it is greater than the total number of frames in the sprite
if(floor(frame) >= sprite_get_number(sprite)){
frame = 0;

The first script, frame_counter, will increase the frame we are drawing by the frameSpeed. The following script is there to keep frame from counting on forever and ever. This is also useful for animation purposes later. The sprite_get_number() function returns the total number of frames in any given sprite. So if our frame is greater than or equal to that number, reset frame to 0. If you need to change the animation speed of your sprite, all you need to do is change the value of frameSpeed.

That’s enough script creation for now. Let’s put all of this stuff to use. Open the Step event of your oPlayer object, and add the following lines:



Open End Step and add the following lines:


Go ahead and run the game. You should see your little dude animating! Depending on your frameSpeed, the animation may not look correct. Try adjusting the frameSpeed value and find something that looks right to you.

The guy on the left is animating at a frameSpeed of 0.10. His hyperactive friend on the right is animating at a frameSpeed of 1. This is running at 60fps in game. The number above their heads indicate the current frame of animation they are on.


Let’s move on to the x and y scaling. We will start by flipping the sprite to the left and right. This is something that I’ve seen a lot of folks use the image_xscale variable for, and you don’t necessarily want to do that all the time. Image_xscale will flip the sprite, but it also flips the sprite mask, which can cause problems. Part of the reason we are using draw_sprite_ext(); is that we are bypassing all of these built-in variables that can cause issues. Add a couple more lines to the step event, below the code we just added:

//change facing
    facing = -1;
}else if(right){
    facing = 1;

Run your game, and if everything was done correctly, you should be able to flip the direction your newly animated sprite is now facing by pushing the left and right arrow keys. This is because in the Draw event, we are multiplying xScale by facing. The best part about this is that your sprite mask is not changing when your sprite is flipped! Now, do you remember the Approach script we added? Using that to make your sprites squash and stretch is a great way to add some life to your animations. Add the following lines below what we just added:

//change scale
    xScale = 1.5;
    yScale = 1.5;
xScale = approach (xScale,1,0.03);
yScale = approach (yScale,1,0.03);

Run your game and slap the space bar. Your sprite should grow by 50% and then shrink back down to normal scale. Adjusting the x/y scale of your sprite can have a huge impact on the feeling of your game. Experiment with this a bit and find some values that feel right to you. I like to create a squash_stretch script because I use this trick all the time. Here is what that script looks like.

//adjust x and y scale
xScale = argument0;
yScale = argument1;

You can then replace the xScale and yScale lines with squash_strech(1.5, 1.5).

Angle and Rotation

Up next we have angle, which is basically just rotation. When using angle, be sure to use values between 0 and 360.  I’m sure that by now you can figure out how this will work. Go ahead and try to adjust the angle using the up and down arrow keys. Did you have any luck? Check out the code below and see if your code is similar:

//change angle/rotation
    angle -= 2;
}else if(down){
    angle += 2;

Color Blending

The next argument is color, specifically, this refers to color blending. Whatever color you put in here (such as c_red) will blend your current sprite into that color. We are going to use c_white for now, which means there is no color blending, and your sprite appears as normal.


Finally we have made it to the last argument in draw_sprite_ext();! Alpha is the transparency of your sprite. It ranges from 0, which is totally transparent, to 1, which is totally opaque. You could use this for all kinds of stuff like making your character blink after taking damage, or turning partially invisible when they are sneaking around. Try adjusting the alpha variable and see what happens! Here is the code I used to change the alpha. This uses the A and S keys to decrease and increase the alpha.

//change alpha
    alpha = approach(alpha,0,0.05);
}else if(keyboard_check(ord("S"))){
    alpha = approach(alpha,1,0.05);

This is another good place to use approach, as it prevents the alpha value from going below 0 or above 1.

That should cover the ins and outs of what I believe is one of the most important functions in GameMaker. Once you get the hang of draw_sprite_ext(); you’ll be able to create a lot of really interesting effects, and squeeze the most juice out of your sprites.


We hope you enjoyed this tutorial. See you next time!

Leave a Reply

Your email address will not be published. Required fields are marked *