1. Animate brightness, contrast, color, transparency
2. Images moving, zooming and rotation
3. Sprite Manager and Movie Clips
4. Animated Shaders & Conclusion (with downloadable complete game)
5. (bonus) BlockDrop ("crumbling") effect
1. Animate brightness, contrast, color, transparency
(I won't talk much about transparency, as changing it is as simple as
Code: Select all
transform alpha_half:
alpha 0.5
https://renpy.org/doc/html/gui.html#scr ... o-continue
)
When you want an element to smoothly change brightness, contrast or color, `matrixcolor` transforms will do that for you:
https://renpy.org/doc/html/matrixcolor.html
(In particular, there are several matrices for color, e.g.:
Hue
Invert
Saturation
Sepia
Tint
)
Here's an example:
"Shimmering" Effect
Code: Select all
transform shimmer:
matrixcolor SaturationMatrix(.25) * BrightnessMatrix(-.2)
block:
easein 1.5 matrixcolor SaturationMatrix(1.) * BrightnessMatrix(0.)
0.5
easeout 1.5 matrixcolor SaturationMatrix(0.25) * BrightnessMatrix(-.2)
0.5
repeat
SaturationMatrix(.25) means that the image will have only 25% of its original color.
BrightnessMatrix(-.2) means it will have 20% less brightness.
Note that different matrices have different behavior:
BrightnessMatrix gets the parameter between -1.0 and 1.0 (with normal brightness at 0).
SaturationMatrix: between 0.0 and 1.0 (1.0 is normal, full original saturation).
ContrastMatrix: from 0.0 and below 1.0 it decreases contrast, and above 1.0 it increases contrast.
Here we change saturation and brightness in a loop, using warpers
https://renpy.org/doc/html/transforms.html#warpers
"easein" and "easeout", each for 1.5 seconds, with a pause 0.5 sec.
In a screen, apply this transform to a picture
Code: Select all
screen some_screen():
add "some_picture":
at shimmer
This effect can be used to draw attention to a pulsating element (like an urgent notification, or a rare edible bonus in a minigame, etc.), to depict heartbeat, or siren flashes, etc. You can vary all the parameters: timing, changes in brightness & saturation etc.
For now, this might not seem like very much, but we only just started. Look at another, more impressive example, where we apply brightness and saturation effects to the whole scene -
"Lights Out" Effect
Now I'll explain step by step how to use this effect in Main Menu.
Usually we have a background image for Main Menu. In this example, I'll use a file I created and put in "gui" folder, named "main_menu.webp". So it will be available as
gui/main_menu.webp
To make it darker, we can use for example this transform:
Code: Select all
transform night_fall:
matrixcolor SaturationMatrix(1.) * BrightnessMatrix(0.)
ease .67 matrixcolor SaturationMatrix(0.4) * BrightnessMatrix(-.2)
When the picture becomes both darker and less saturated, it really looks like the night is coming.
Apart from that, we can make the bottom part of the picture even darker (because it's very often that the top of the room gets a bit more light - through the window etc.).
In that case, we can supplement our transform with "gradient" shader, to transition smoothly from the lighter top to the darker bottom. I'll just take the shader from the Ren'Py documentation:
https://renpy.org/doc/html/model.html#c ... tom-shader
and change it to be "top to bottom" rather than "left to right":
Code: Select all
init -1 python:
renpy.register_shader("gradient.vertical", variables="""
uniform vec4 u_gradient_top;
uniform vec4 u_gradient_bottom;
uniform vec2 u_model_size;
varying float v_gradient_done;
attribute vec4 a_position;
""", vertex_300="""
v_gradient_done = a_position.y / u_model_size.y;
""", fragment_300="""
float gradient_done = v_gradient_done;
gl_FragColor *= mix(u_gradient_top, u_gradient_bottom, gradient_done);
""")
Code: Select all
transform dark_bottom:
matrixcolor SaturationMatrix(1.)
shader "gradient.vertical"
u_gradient_top (1.0, 1.0, 1.0, 1.0)
u_gradient_bottom (1.0, 1.0, 1.0, 1.0)
ease .67:
matrixcolor SaturationMatrix(0.4)
u_gradient_top (0.8, 0.8, 0.8, 1.0)
u_gradient_bottom (0.3, 0.3, 0.3, 1.0)
Here we start with the normal, unmodified picture: saturation 1. and "gradient" that has the white color all the way from top to bottom, hence not modifying the picture at all.
(Four color channels: Red, Green, Blue and Alpha all have values 1.0 - meaning it's fully opaque white color:
u_gradient_top (1.0, 1.0, 1.0, 1.0)
u_gradient_bottom (1.0, 1.0, 1.0, 1.0)
)
Then we have "ease" transition during 0.67 sec, that changes saturation to 40%, top lighting to 80% and bottom lighting to 30%:
Code: Select all
ease .67:
matrixcolor SaturationMatrix(0.4)
u_gradient_top (0.8, 0.8, 0.8, 1.0)
u_gradient_bottom (0.3, 0.3, 0.3, 1.0)
OK... that's good enough, but to make the effect really standing out, we can also make the window look brighter.
Yes, you might have noticed in the picture above that it's not just an optical illusion: the window is actually getting brighter, when the room gets darker.
How to do that?.. We use 2 pictures there. One is the window, another is the rest of the room. We can add the window "on top" of the room picture, or we can cut out a piece of the room picture (creating a transparent area there) and show the window image behind that transparent area. This technique can be used also for showing a movie through the transparent part, etc. As the window frame can have a complicated shape, with semi-transparent pixels at the edges etc., maybe plants at the window sill etc., I prefer to put the window picture behind the room picture, through a transparent area (but YMMV).
Now, for the window picture we can use a transform like this:
Code: Select all
transform brighter:
matrixcolor ContrastMatrix(1.) * BrightnessMatrix(0.)
ease .67 matrixcolor ContrastMatrix(1.2) * BrightnessMatrix(0.2)
Now, how do we actually apply those transforms?
As you can see from the picture above, the effect is applied when we hover the button "Quit". How to change screen elements by hovering a button?
Here's the code I used:
Code: Select all
screen main_menu():
tag menu
style_prefix "main_menu"
default hover_quit = False
if hover_quit:
add "gui/window.webp" pos (514, 219) at brighter
add "gui/main_menu.webp" pos (0, 0) at dark_bottom
else:
add "gui/window.webp" pos (514, 219)
add "gui/main_menu.webp" pos (0, 0)
if renpy.variant("pc"):
textbutton "Quit":
pos (1890, 840)
xanchor 1.
action Quit(confirm=False)
hovered SetScreenVariable("hover_quit", True)
unhovered SetScreenVariable("hover_quit", False)
Then we add to our button properties "hovered" and "unhovered":
Code: Select all
hovered SetScreenVariable("hover_quit", True)
unhovered SetScreenVariable("hover_quit", False)
Now to change an element we just check if "hover_quit" is True, and if so, we show the pictures with the transforms applied.
Here's how you can test this in a freshly created Ren'Py 8 project:
1. Put files (see the attachment) "main_menu.webp" & "window.webp" in "game/gui" folder.
2. Open file "screens.rpy" and replace lines
Code: Select all
screen main_menu():
## This ensures that any other menu screen is replaced.
tag menu
add gui.main_menu_background
Code: Select all
init -1 python:
renpy.register_shader("gradient.vertical", variables="""
uniform vec4 u_gradient_top;
uniform vec4 u_gradient_bottom;
uniform vec2 u_model_size;
varying float v_gradient_done;
attribute vec4 a_position;
""", vertex_300="""
v_gradient_done = a_position.y / u_model_size.y;
""", fragment_300="""
float gradient_done = v_gradient_done;
gl_FragColor *= mix(u_gradient_top, u_gradient_bottom, gradient_done);
""")
transform dark_bottom:
matrixcolor SaturationMatrix(1.)
shader "gradient.vertical"
u_gradient_top (1.0, 1.0, 1.0, 1.0)
u_gradient_bottom (1.0, 1.0, 1.0, 1.0)
ease .67:
matrixcolor SaturationMatrix(0.4)
u_gradient_top (0.8, 0.8, 0.8, 1.0)
u_gradient_bottom (0.3, 0.3, 0.3, 1.0)
transform brighter:
matrixcolor ContrastMatrix(1.) * BrightnessMatrix(0.)
ease .67 matrixcolor ContrastMatrix(1.2) * BrightnessMatrix(0.2)
screen main_menu():
tag menu
style_prefix "main_menu"
default hover_quit = False
if hover_quit:
add "gui/window.webp" pos (514, 219) at brighter
add "gui/main_menu.webp" pos (0, 0) at dark_bottom
else:
add "gui/window.webp" pos (514, 219)
add "gui/main_menu.webp" pos (0, 0)
Code: Select all
textbutton _("Quit") action Quit(confirm=not main_menu)
Code: Select all
textbutton _("Quit") action Quit(confirm=not main_menu):
hovered SetScreenVariable("hover_quit", True)
unhovered SetScreenVariable("hover_quit", False)
You are welcome to use this stuff for any project, and be inspired to create something even more amazing.
The image files that I used: