Source code and demonstration of a scrolling displayable built on multiple layers with a parallax effect.
Important
|
HParallax is only compatible with Ren’Py 8.1+. |
h_parallax foo:
"images/backgrounds/scrolling_forest/10.png" 0.0 # Doesn't scroll
"images/backgrounds/scrolling_forest/09.png" 0.001
"images/backgrounds/scrolling_forest/08.png" 0.0025
"images/backgrounds/scrolling_forest/07.png" 0.005
"images/backgrounds/scrolling_forest/06.png" 0.0075
"images/backgrounds/scrolling_forest/05.png" 0.025
"images/backgrounds/scrolling_forest/04.png" 0.025
"images/backgrounds/scrolling_forest/03.png" 0.05
"images/backgrounds/scrolling_forest/02.png" 0.05
"images/backgrounds/scrolling_forest/01.png" 0.075
"images/backgrounds/scrolling_forest/00.png" 0.1 # Scrolls 10% of its width per second
The h_parallax
statement declares a new parallax image with the given name
("foo" in the above example) constructed of the frames and frame scroll speeds
given in the following block.
Each line in the block may be one of the following things:
-
An image name/path followed by a scroll speed value.
-
The
height
keyword followed by an int value declaring theh_parallax
's display height. -
The
width
keyword followed by an int value declaring theh_parallax
's display width. -
The
direction
keyword followed by either the string'left'
or'right'
. -
The
render_delay
keyword followed by a float value declaring the delay between frames in the scrolling animation.
The given layers are rendered in back to front order with the first declared layer being on the bottom and the last declared layer being on top.
height <int>
-
A height value for the
h_parallax
. Controls the display height that the parallax scroll will be cropped to. This value should match the size of the images being used in the scroll.Defaults to
config.screen_height
.h_parallax bar: height 600
width <int>
-
A width value for the
h_parallax
. Controls the display width that the parallax scroll will be cropped to. This value should match the size of the images being used in the scroll.Defaults to
config.screen_width
.h_parallax fizz: width 800
direction <"left"|"right">
-
The scroll direction for the parallax scroll. Must be one of the strings
"left"
or"right"
.A value of
"left"
causes the parallax scroll to move from right to left. A value of"right"
causes the parallax scroll to move from left to right.Defaults to
"left"
.h_parallax buzz: direction "left"
render_delay <float>
-
The delay between render frames for the scroll. A smaller value means a smoother animation.
Defaults to
0.01
h_parallax foo: render_delay 0.01
image foo = HParallax(
("images/backgrounds/scrolling_forest/10.png", 0.0), # Doesn't scroll
("images/backgrounds/scrolling_forest/09.png", 0.001),
("images/backgrounds/scrolling_forest/08.png", 0.0025),
("images/backgrounds/scrolling_forest/07.png", 0.005),
("images/backgrounds/scrolling_forest/06.png", 0.0075),
("images/backgrounds/scrolling_forest/05.png", 0.025),
("images/backgrounds/scrolling_forest/04.png", 0.025),
("images/backgrounds/scrolling_forest/03.png", 0.05),
("images/backgrounds/scrolling_forest/02.png", 0.05),
("images/backgrounds/scrolling_forest/01.png", 0.075),
("images/backgrounds/scrolling_forest/00.png", 0.1), # Scrolls 10% of its width per second
)
def __init__(self, *layers, **kwargs)
*layers : tuple[renpy.Displayable | str, float]
-
One or more two-tuples that each contain a displayable to render and a float which represents the scrolling speed of the layer.
The first value of each tuple MUST be either an instance of renpy.Displayable (Composite, Image, Transform, etc.) or a string representing the name of or path to a defined image or an image file.
The second value of each tuple MUST be a float value between
0.0
and1.0
inclusive. This value represents the percent of the layer image’s width that will scroll across the screen per second.The layers are ordered back to front, meaning the first given layer will be the furthest from the player while the last given layer will be the closest.
direction : "left"|"right"
-
Controls the direction the HParallax layers will scroll.
A value of "left" means the layers will scroll from right to left, where a value of "right" means the layers will scroll from left to right.
Any other value passed as the
direction
argument will cause an exception to be raised.Defaults to
"left"
. render_delay : float
-
Controls the delay between Displayable re-renders.
Defaults to
0.01
height : int
-
Controls the display height of the parallax. The displayable will be cropped to this height. This value should match the size of the source image.
Defaults to
config.screen_height
width : int
-
Controls the display width of the parallax. The displayable will be cropped to this width. This value should match the size of the source image.
The HParallax
class extends Ren’Py’s Transform
type, meaning any
normal transform keyword argument is permitted and will be applied to the
HParallax
.
For example, the colors of the parallax may be inverted by doing the following:
HParallax(
... # dimensions
... # layers
matrixcolor=InvertMatrix(1.0)
)
The exception to the above rule is the crop
keyword argument, which is used
to contain the scrollable within it’s configured size boundaries. Specifying
the crop
keyword will result in an Exception
being raised.
Each layer consists of a single image or Displayable that is repeated on the x-axis to fill the target width for the ParallaxScroll. Each layer is stacked on top of one another in the given order with each layer given it’s own scroll speed to create the parallax effect.
Layer displayables will only be repeated along the x-axis and will be positioned at the top of the ParallaxScroll bounding box.
While the first layer given (the layer furthest back in the image) may or may not have transparency, the layers above it should have some transparency to show through to the layers underneath. This makes PNG files a perfect fit unless you are creating the images on the fly via a Creator Defined Displayable or some other mechanism.
This source code and project are released under the MIT license, which to paraphrase in a way that is not legally binding:
-
You can use it for free things
-
You can use it for paid things
-
You can modify it however you see fit
-
You can redistribute it as you see fit
-
Go nuts!
For a better breakdown of what the license actually means see: https://choosealicense.com/licenses/mit/