Time to dust this blog off!
I’m doing the NaNoRenO 2016 game jam right now, making a short, surreal visual novel in the Ren’Py VN engine with Jen Tracy and Maize Wallin. My first experience with the engine was in the middle of last year, when I wrote and produced RE\VISION for #wagchallenge. One of my biggest challenges with that project was figuring out how to put image elements in the right place – Ren’Py’s ATL (Animation and Transform Language) is an incredibly powerful tool, but it’s also pretty incomprehensible to new users. So, with that in mind, I’m gonna show you how to define screen positions, both relative and precise, and include code snippets that you’re totally free to steal and use for yourself. :D
What is a transform?
A transform is any in-engine action that moves, manipulates, or positions an image element. This can include character sprites, backgrounds, UI elements, whatever.
Defining simple character positions
Let’s start with the simplest, most universal task: putting your character sprites in the right place. The Ren’Py transforms page describes nine default transforms for your sprite, but, hey, we want to do some custom positions!
For RE\VISION, we had a sequence where two characters had to appear next to each other close to the centre of the screen, but not on top of each other. The left and right positions, defined as defaults, weren’t close enough for us, so we had to define simple midleft and midright positions, like so:
# Transform declarations transform midleft: xpos 0.4 transform midright: xpos 0.6
Then, when we show our characters, we call them like this:
show maidenr at midright show maiden at midleft
Let’s tear this apart.
First, we’re defining a transform and giving it a name, midleft.
Then, on the next lines (tabbed), we’re able to give it attributes. These can include absolute position (defined from the top left), absolute x-position (horizontal, relative to the left side of the containing area, or screen), and absolute y-position (same as above, but vertical). In this case, we’re doing a simple x-position transform, which means that all we’re doing is aligning our images along a horizontal axis and not changing their position vertically.
When we give Ren’Py a number with decimal points – or, as it’s more precisely known, a float – Ren’Py will read and express that number as a fraction of the screen (0 being absolute left, 1 being absolute right). In this case, I’m telling Ren’Py to put my sprite’s center at 0.4, or 40% of the way across the screen.
In practise, my midleft and midright transforms look like this:
Compare that to this image, which defines the three characters onscreen as left, center, and right:
If your transform doesn’t look quite right, play around with the numbers! This is where Ren’Py’s auto-reload feature really comes in handy.
More granular character/image positioning
If you want to be more granular and precise with your positioning, you’ll want to define your elements by their exact, pixel-perfect position in the scene. For RE\VISION, this would translate to:
transform midleft: xpos 512 transform midright: xpos 768
These numbers are found by taking my project’s resolution (1280*720) and multiplying the horizontal resolution by the float mentioned above. Since the xpos values don’t have anything after the decimal point, Ren’Py reads them as integers, and uses them to precisely place the images on the desired points on the screen.
What other values can I use?
There’s a list, thankfully. You can even set transparency! Here’s an example of how you’d do that:
transform halftransparent: alpha 0.5
Setting transforms on already-existing elements
So you’d like to change something that’s already on-screen? Easy! Let’s start with moving a sprite from one place to another. In the scene I showed above, the on-screen characters appeared from the left and right with the easeinleft and easeinright transitions. A full list of transitions can be found here, by the way!
show maidenr at right with easeinright show maiden at left with easeinleft
Dissected, I’m telling the engine to show my maidenr character at the right side of the screen, with the easeinright transition, which moves the character gently in from off-screen. It’s the same with the maiden character, except, y’ know, on the left.
A few lines later in the script, they move closer to each other, again using an ease transition.
show maidenr at midright with ease show maiden at midleft with ease
Since they’ve already been shown earlier, instead of moving in from off-screen again, they move from their current position. You can do this with any transition that you like, including move, dissolve, and fade.
Bonus: frame-based background and character animation
For most of our backgrounds, we had some sort of animation to keep it visually interesting. For example, our Caterpillar Club background had a neon sign that’d flicker at non-regular intervals. It’s surprisingly easy to do! Here’s an example code snippet:
image bg caterpillar: "images/caterpillarclub.jpg" pause 10 "images/caterpillarclublit.jpg" pause 2 "images/caterpillarclub.jpg" pause 0.5 "images/caterpillarclublit.jpg" pause 0.2 "images/caterpillarclub.jpg" pause 0.3 "images/caterpillarclublit.jpg" pause 0.1 "images/caterpillarclub.jpg" pause 0.2 "images/caterpillarclublit.jpg" pause 0.1 "images/caterpillarclub.jpg" pause 0.1 "images/caterpillarclublit.jpg" pause 5 repeat
We begin by declaring a background, just like normal, but we turn it into an image statement by adding a :colon: to it. Then it’s just a matter of setting an image (the background without the sign lit), setting a pause time (in seconds), and then showing our second image, with the sign lit. After that it’s just some fancy repetition until the last line, repeat, which does exactly what it says on the box.
You can use this frame-based animation for anything – UI elements, character sprites, etc. In RE\VISION, we primarily used it for our backgrounds, but we also had an animated click-to-continue indicator with 52 frames that looked like this in code:
(shoutout to Shoehead for making FIFTY TWO FRAMES and generally being a great guy also)
Is that it?
I, uh, yeah, I think so. Is there anything else? I don’t know. While working on Ren’Py games, the documentation will be your best friend, but sometimes it can be pretty dense stuff! Hopefully this little primer is at least a tiny bit helpful for those starting out. If you’re working on your project: best of luck! Remember that there’s nothing wrong with finishing or releasing small, experimental work!