We're using param_value to track the current value of the parameter.
exiting indicates whether we’re currently exiting a room. It’s true at the start of the transition, and when we switch over to the target room, it'll be set to false.
We then create a temporary layer for the FX, and then the FX itself, using the filter name set in the variables.
Then we apply the FX to the temporary layer. Finally, we apply the param_value to the correct parameter in the filter so it starts where we need it to.
Animating Parameter
Add the Step event:
Add the following code:
if (exiting)
{
param_value += param_speed;
if (param_value >= param_max_value)
{
room_goto(target_room);
}
}
else{
param_value += -param_speed;
if (param_value <= param_min_value)
{
instance_destroy();
}
}
fx_set_parameter(filter, param_name, param_value);
If we're leaving or exiting the room, this code increases param_value by param_speed. Once param_value is greater than or equal to its max value, we go to the target room!
Going to the target room would set exiting to false – we’ll add this at a later step.
If we're entering a room, and not exiting, then param_value is reduced by param_speed. Once param_value is less than or equal to its minimum value, we destroy the instance, ending the transition.
So if the min value is 0 and the max value is 10, it will go from 0 to 10 when exiting a room, and from 10 to 0 when entering a room. The last line of code or action sets the parameter’s value in the FX struct regardless of whether we're entering or exiting a room.
Switching Transition Mode
When the room changes, we need to tell the object that we’re not exiting anymore, and instead entering a room.
This event will trigger when we've entered a new room.
Here we’re changing exiting to false, so the transition now plays in reverse.
The temporary layer we created in the Create event was in the previous room, so we create a new temporary layer and then apply the same filter to this new layer.
Cleaning Up
This layer should be deleted when the transition instance is destroyed, which happens when the transition ends.
Add the Destroy event:
Add the following code:
layer_destroy(temp_layer);
This code runs when the transition instance is destroyed using the code in the Step event, and destroys the temporary layer that we created at Room Start.
The transition parent object is now complete.
Now we need to create a child object from this, with details of a filter, and play it on changing rooms.
Create the First Transition Object
When working with objects in GameMaker, you can set up Parent/Child hierarchies.
When an object has a parent assigned, it can share code, actions, and events with that parent.
Not only can a child share code with its parent, but you can perform checks and run code on parent objects which will automatically include the child objects, which saves a lot of time and energy.
Inheritance is very useful, and Windy Woods uses it a lot. I recommend checking out some examples of object hierarchy in the project, such as characters and blocks.
Create an object, name it obj_transition_pixelate, and make it Persistent.
Set its parent to obj_transition_parent:
Now this object will inherit all of the events and object variables from obj_transition_parent.
Simply put, it will 'copy' all the functionality of its parent.
Open the Variable Definitions window and change the following variables:
This will create the pixelate filter, whose internal name is “_filter_pixelate”.
It targets the “g_CellSize” parameter, which is the size of each individual pixel.
It sets the values for param_min_value, param_max_value, and param_speed.
These are example values, so experiment with them once the transition is in, and change them to your liking.
Don't forget that you can look up all the different filters and their parameters on this page.
You can change the filter for a transition by changing the name and parameter in the variables.
Create a Menu Transition
We’ll play this Pixelate transition when we go from the menu room, to the first level.
For this, we’ll modify obj_button_play, which is the “Play” button you click in the main menu (found under Objects -> UI -> Buttons -> Main Menu).
Open User Event 0 in obj_button_play, and delete all existing actions/code.
Then add the following code:
var _transition = instance_create_layer(0, 0, "Instances", obj_transition_pixelate);
_transition.target_room = rm_level_1;
This code creates an instance of obj_transition_pixelate, and stores its ID in the temporary variable transition.
It then uses that variable to set the target room, which is rm_level_1.
If you want it to go to the next level in the Room Order instead of Level 1 specifically, call room_next(room) instead of rm_level_1.
How to Load a Filter
If we ran this now, we'd get a game crashing error.
GameMaker will only load filters it knows are being used. If it doesn't know... well, it can't load them.
We're setting the value of the filter in a variable (filter_name). This doesn't tell GameMaker to load the mentioned filter.
Luckily, the fix is simple.
Create a new script:
Name it Filters:
Delete any existing code/actions, and insert the following code:
Here we're initialising two filters: Linear Blur and Pixelate. We'll be using Linear Blur later in this tutorial.
Result
Now run the game and see the transition from the menu to the level:
Let's apply a transition on finishing a game level.
Create the Level Transition
We’ll create a new child object for this transition, with a new filter.
Duplicate obj_transition_pixelate by right-clicking on it in the Asset Browser.
Name the new object “obj_transition_linear_blur”. You can guess which filter we’re going to use here!
Open the Variable Definitions windows, and change these variables:
This creates the linear blur filter (_filter_linear_blur) and targets its blur vector parameter.
"g_LinearBlurVector" actually contains both the X and Y components, but currently only its X component will change, which is the result we're looking for.
Apply the Transition
Open the obj_player_end_level object (found under Objects -> Characters -> Player)
, which spawns when the player touches the “end gate” and walks into it.
Open its Step event. Here you'll find an action called “Go To Next Room”, or a function called room_goto_next().
This simply moves you to the next room when you finish a level.
Remove this function call or action, and in its place, add these three lines of code (or actions) under the same condition:
When using GML Visual, make sure to attach your new actions to the existing If Variable action.
This code creates an instance of obj_transition_linear_blur, stores its ID in the variable transition, and then uses that variable to set the target room.
The target room is the next room in the Room Order.
Finally, it deletes the current instance, so this code doesn’t run again.
Results
Open rm_level_1, and move the player instance near the end gate, so transitions can be tested quickly:
Run the game, and check out your cool new transition!
Extra Credit
There's one more place that needs a transition.
When you press Escape to open the pause menu, you can click on “Back to menu” to go into the main menu.
Modify the project to play a transition when that happens. You can either use an existing transition object or (for extra, extra credit) create a new one!
Hint: Check out obj_button_menu's User Event 0 and compare it to obj_button_play's User Event 0.
Summary
Here are some key takeaways from this tutorial:
You can create and control Filters and Effects at Runtime, not just in the Room Editor