Reflections in GameMaker
Reflective Objects in GameMaker

This is a guide to help you put reflections in your GameMaker game, This might be used for puddles, water, shiny surfaces, mirrors etc.

We are going to use masking which I have spoken about lots on my website.

How it Works:

First we need to make a negative of this sprite that stores all the information about the shape of the object. It should be transparent in the places we want a reflection and black everywhere else. We could make this automatically like I did in this lighting example, however I’m going to draw it by hand to make it more tailored.


How to mask in GameMaker

This is going to work using surfaces and blend modes, surfaces are like a blank sprite we can draw onto and then place onto the screen.

Reflection Sprite in GameMaker

We will first check to see if the player is near our reflective object. This allows us to have lots of reflective objects spread around the room that might not even be very big, so this just improves things by not doing reflections if we don’t need to.

We will draw a duplicate of our player (and anything else we want reflected) with a small offset onto the surface, I called mine surface_player however you might want to use sur_* as a convention on your surfaces.

I have given many examples above with different types of offset, but normally it will be just up and to the side like a mirror or flipped like I did on the puddle. You need to remember here that when drawing onto a surface the top left corner isn’t going to be the top left of the window because we will draw this reflection at the location of the reflective object. That’s why I have to say this to draw at the correct location:

x-other.x-8,y-other.y-10
	

We can now use gpu_set_blendmode(bm_subtract) to tell GameMaker that anything we want to draw should now delete from the surface rather than draw. This used to be called draw_set_blend_mode(bm_subtract) in versions of GameMaker <= 1.4.

Reflections Sprite in GameMaker

Well that should explain how everything works, lets look at the code.

Full Code:

Create:

image_index = 0 // in image_index 0 we have the image and in image_index 1 we have the bit to blank out
image_speed = 0

playercollision = false
	

Step:

playercollision = place_meeting(x, y, obj_player);
	

Draw:

draw_self() // draw the normal image

if (playercollision) { 

	surface_player = surface_create(sprite_width, sprite_height)
	if (surface_exists(surface_player)) {
		
		surface_set_target(surface_player)
	
		draw_clear_alpha(c_black, 0);

		with(obj_player) {
			// make this one a little transparent 
			draw_sprite_ext(sprite_index,image_index,x-other.x+12,y-other.y-3,1,1,0,c_white,0.75) // give it a little offset
		}
	
		gpu_set_blendmode(bm_subtract) // draw_set_blend_mode() in GM 1.4
		draw_sprite(sprite_index,1,0,0) // this has the image we want to blank out
		gpu_set_blendmode(bm_normal)

		surface_reset_target()
	
		draw_surface(surface_player,x,y)
	
		surface_free(surface_player)
	}

}
	
Some Final Thoughts:

This fully works with semi-transparent masks, I didn’t use them enough but it does look really good. The jug on the right has some different areas of opacity. This would make some areas of the object more reflective than others.

It’s really designed for smaller reflective object rather than huge areas like large bodies of water that take up the whole screen, however the underlying techniques would be very similar.

You could have animated reflection masks, I think this would be pretty exciting. If you wanted to do this rather than having the negative image contained in the sprite, split the negative image and the sprite image into their own sprites.

You could draw multiple things in the reflection at the same time like clouds in the sky or other objects around the player.

Credits:
Shiny Pot: https://neoriceisgood.deviantart.com/ (I had to use that!)
All other background stuff and walls: Kenny
Character: Matthew Krohn from art created by Johannes Sjölund
Download:

Download GMS2 Project File

Medium Difficulty
GameMaker
By David Strachan