We would love you to play this but your browser doesn't support HTML5 canvas.
Just use a different browser and you can happily play this game.

How to do Drop Shadows in GameMaker using Surfaces (HTML5 compatible)

In the above example you can see a very simple platformer I have mocked up to demonstrate how drop shadows can look in a game. You can click on the example to cycle through some different drop down examples. In this little guide I am going to talk about one way you can add these into your GameMaker project.

I feel I need to say first that this is not my preferred way of doing drop shadows, ideally you would just want to draw everything a second time in its own draw event but often this isn’t possible because of the depth of objects or objects overlapping. This way of doing it has the advantage of it all being in one object and I like keeping all the code in one place. This helps if you want to toggle it on and off or maybe do more complex things like with direction or colour.

Examples :

I originally wrote this code because I saw a tweet by @cilerbaa while I was working on shadows in top down games. You can see how he has used drop shadows in his upcoming game NipNip to really make the graphics pop out.

Before:

nipnip game no drop shadow made in GameMaker

After:

nipnip game with drop shadow made in GameMaker

Also drop shadows have been used in Mario Maker to great effect:

Mario Maker drop shadow

Anyway enough trying to show what drop shadows are, let’s look at the code because it is so easy.

Code :
// draw event
surfacedropshadow = surface_create(room_width, room_height);

surface_set_target(surfacedropshadow)

draw_clear_alpha(c_white,0) // empty the surface 

// everything drawn here will be added to the dropshadow
with (obj_wall) {
    draw_self();
}
with (obj_player) {
    draw_self();
}
with (obj_flower) {
    draw_self();
}

surface_reset_target();

draw_surface_ext(surfacedropshadow,8,8,1,1,0,c_black,0.5)

surface_free(surfacedropshadow)
    
So what’s Happening?

If you are not familiar with surfaces in GameMaker you should read up on them, they are really useful and can be used to add in loads of cool effects into your games. Basically they allow you to draw anything you want onto a blank canvas and then draw this canvas onto the screen just like you would draw a sprite.

I have a single object that loops through all other objects that want a shadow. I then draw these objects onto a blank surface I have created called surfacedropshadow. I then take this surface and make it solid black and slightly transparent so it looks like a shadow. It can then be slightly offset and drawn onto the screen behind everything else.

Explaining the Code :

surface_create() – This makes a blank surface that you can edit.

surface_set_target() – normally when you draw anything in GameMaker it is drawn onto the screen, this tells GameMaker that anything after this point should be drawn to a surface (surfacedropshadow) rather than the screen.

draw_clear_alpha() – I use this to blank out the surface, in the above example I have done everything in the draw event, however it might be more efficient to move the code around like putting surface_create() in the create event, if so I use this to erase what was drawn on the surface before.

with (obj_wall) { draw_self(); } – All this does is goes through all wall objects and draws the sprite, however because earlier we told GameMaker that everything drawn should be put on the surface rather than the screen. This builds up the surface with all the objects on.

surface_reset_target() – This tells GameMaker to stop drawing on the surface and anything from this point on should be put on the screen.

draw_surface_ext() – At this point our surface is in full colour, but this line makes the surface either black and semi-transparent or fully transparent. It also gives it a slight offset and draws it onto the screen behind everything else.

surface_free() – This deletes the surface from memory, I have added this line for people that are creating the surface fresh on every frame.

So you can see that my explanation is massively longer than the 15 lines I actually use to make the dropdown.

This seems like a good time to mention that normally when using surfaces you need to check it exists before calling it, however because I have just created I know it exists so I don’t seem to have to check.

HTML5 and WebGL :

It was really important to me that this was HTML5 compatible, so if you have the GameMaker HTML5 module you can use it on websites like I have done above. I’m pretty sure you would have to make WebGL required however I always check this box under the global settings.

Animating the Dropdown :

This effect is really good and looks like it would be hard to make but is actually really easy!

All I do is use this code:

shadowdriection += 1.5
draw_surface_ext(surfacedropshadow,lengthdir_x(5,shadowdriection),lengthdir_y(5,shadowdriection),1,1,0,c_black,0.5)
    

Using lengthdir_x() and lengthdir_y() to calculate how much the offset should be for the shadow and then every frame I increase the variable shadowdriection to make it look like it is rotating.

Optimisation changes you might want to make :

Optimisation 1: This is the big optimisation tip; most of the time you should just have another line in the draw event for each object that draws its shadow, however as I said above if for any ready (like you don’t like how the shadows overlap) you will have to use this method.

Optimisation 2: ideally you would want to only draw your surface a little bigger than the view not the whole size of the room like I did. The reason I did this is because everyone’s game would be different and it is easier for someone to add this in than it would be for someone to remove the code needed. Also the one I have above runs sufficiently well so for my purposes I didn’t need it.

Optimisation 3: I’m pretty sure when doing the HTML version you need to create the surface outside the draw event, I can’t remember if this was for performance reasons or where I read it, but I’m pretty sure this is best practice.

Optimisation 4: The GameMaker Manual does tell you to use surface sizes that are powers of two like: 16, 128, 512, 1024 etc. I never have and this is might be why I have so many problems with surfaces.

Notes :

If you are looking to cast shadows in GameMaker you might find this guide better.

Credits :

Sorry for mixing all the art styles in my example, it was just so you could have an interactive demo.

@cilerbaa for image of the game NipNip

Nintendo for image of Mario Maker

Credits for sprites: Matthew Krohn from art created by Johannes Sjölund