GM: Studio - Shadow Tutorial
Hey guys, Case here (Programmer for Flynn: Son of Crimson) giving a short tutorial on how to apply shadows to your 2D platformers made in Game Maker: Studio and Game Maker: Studio 2 to give it a little extra visual spice. I will note, you should have a basic understanding of GML before diving into this tutorial, as it’s not aimed for people just starting out.
I will go over two different styles, blob shadows and dynamic shadows. NOTE: neither methods work for slopes, I may extend this tutorial later on once I figure it out fully.
First up you’re going to need a sprite/object to apply the shadow to, in this case I’ll be using our main character, Flynn. Next, you’ll want to have your solid objects set up (the walls/floors that your player collides with), if you need help setting that up I strongly recommend Shaun Spalding’s tutorial here. Everything else such as player movement and actions from here on out are entirely optional but again, Shaun has many tutorials for basic movements and platforming, so go check out his Youtube channel if need be.
We’re going to need an extra sprite for this one so open up the sprite editor and draw out a shape that you would like your shadow to resemble, this can be anything you want as long as it takes form somewhat similar to the image below:
The origin of the sprite should be set directly in the middle of the shadow, then rename it to something like “spr_blob_shadow”. Close the sprite editor.
Okay, so first up we’re going to need to write some code to check how far the player is from the ground regardless of it’s elevation and have the shadow always be where it should be.
Open up your the object you wish to add the shadow to and then create a Draw Event (if you already have one, simply open up the existing one). We now need to declare two temporary variables, max_length and solid_object which will check how far away the shadow is from the object we set.
max_length - How far from the ground until the shadow disappears. Solid_object - The object used for ground collision (e.g. obj_solid).
Next we create a ‘for loop’ which continuously checks if the player is within range of the ground (e.g. 64 pixels) else we break the loop. Using the function collision_point gives us a great point of reference as we use the temp var ‘ly’ to find the lengthdir_y below us (direction 270 is directly down).
(This method can also be used for hit-scan, I will cover in a later tutorial)
Now that we have done all the calculations, it’s time to apply it to the blob shadow sprite we created earlier. We declare a new variable named shadow_size. The shadow then needs to check whether or not to be drawn by reading the variable ‘i’ from earlier and if it’s greater then stop drawing the shadow.
Finally we draw the shadow sprite which takes all the above calculations and resizes itself accordingly, then draw_self() will draw your player sprite above the shadow.
Blob Shadow Done!
The method I used for the dynamic shadow uses a few variables which may differ in your game, but to keep things simple we shall assume the player’s image_xscale flips when you turn around (-1 for left and 1 for right). Effectively, what we are doing is drawing a flipped and ‘squashed’ version of our player object which mimmicks every movement and sticks to the ground.
So, picking up from the last part, we only need to do a few minor changes, firstly we want to remove the ‘spr_blob_shadow’ from the first argument of spr_sprite_ext and replace it with ‘sprite_index’ as this will keep track of which sprite you are using in the object.
Staying inside ‘draw_sprite_ext’ we need to multiply the shadow_size by the image_xscale inside the ‘image_xscale argument order for the shadow to flip with the player, then inside the ‘image_yscale’ argument we give it ‘-shadow_size’ which flips the shadow upside down, then divide by 4 to match the size.
You should end up with something that looks like this:
The circled parts below are what you can change to move the shadow around to your liking, but these values worked for me:
And that is it, dynamic shadows done!