Screen Tearing / Wavy Effect in GameMaker Studio 2 (using Surfaces)

After playing Environmental Station Alpha, I decided I wanted to implement the screen tearing effect Hempuli is using in his game. I didn’t know how he achieved it so I had to start from scratch and think about different approaches.

Knowing nothing about shaders, I was left with surfaces. I jotted down some code and immediately hit a wall; after asking around in the yoyogames forums, reading other’s comments, I could finally come up with a pretty decent solution.

Actual Code

I wrote the code so it could be easily hackable. This goes into the create event of your game controller object.
// handy shorter names
dw = display_get_width()
dh = display_get_height()

tearings_surface  	= surface_create(dw, dh)    // We'll draw on this surface
tearings_y          = 0
band_num            = 16                        // How many bands you want on screen
band_height         = dh / band_num
tearings_x_offset   = 32                        // How much you want to displace the bands horizontally
tearing_speed       = 4                       	// Change this to speed up/slow down the tearings
I place the following code inside a draw_post event of my controller.
// Create surface if it doesn't exits
if !surface_exists(tearings_surface)
	tearings_surface = surface_create(display_get_width(), display_get_height())
	
// Let's set the target to our surface
surface_set_target(tearings_surface)
draw_clear_alpha(c_black, 0)

// We draw parts of our application surface on tearings surface
for (var current_band = 0; current_band < band_num * 2; current_band++)
{
	draw_surface_part(application_surface, 0, band_height * current_band - tearings_y, dw, band_height, sin( (degtorad(360) / band_num ) * current_band) * tearings_x_offset , band_height * current_band - tearings_y)
}

// Always reset the target surface
surface_reset_target()

// Draw the actual surface
draw_surface_stretched(tearings_surface, -tearings_x_offset, 0, dw + tearings_x_offset * 2, dh)

// Move the Tearings
tearings_y = (tearings_y + tearing_speed) % (band_height * band_num)

That's it.

And this is how I make that effect. I will implement a similar version for vertical tearings (for underwater levels? maybe?). Hope you find it useful.

A note about surfaces: remember to free the surfaces if you don’t need them anymore, otherwise it will lead to memory leaks.

What are your thoughts on this?

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: