Basics of Ren'Py #2

Character Objects and Text Tags

Welcome to Basics of Ren'Py! 

These tutorials should help you understand basic features of Ren'Py. If you're new here, you should see the first tutorial if you haven't already. You can find it Here (#1).

You can create a new project to be your guinea pig, or use one that you already have. I recommend writing into script.rpy, but any file will do, as long as there aren't any conflicts across files, like two different start labels. 

label start():
    
    "Lezalith" "Hi again!"

    "Lezalith" "How are you doing today?"

    return

Let's start with a quick reminder. The code above defines a simple label with two lines of dialogue. It took only a moment to write, functions as intended, looks clean. But we can improve this further. Let's see how.

First, let's address the issue of "Lezalith". Every line, I have to include my name so that the game knows it's me talking. Of course, I will always need to include something so that the game knows that, but "Lezalith" will get cumbersome if I intend to write a long script with myself as the main character. Watch me change our code.

define l = Character("Lezalith")

label start():
    
    l "Hi again!"

    l "How are you doing today?"

    return

There. That looks better, saves us time, and it keeps the same functionality, too.

What we see above the label is the define statement, followed by a name, an equal sign, and something

Define statement tells Ren'Py to take the provided something and remember it under the provided name. The main advantage is that this lets us reuse the same thing multiple times. And no matter how many times we use it, unless we deliberately change the something ourselves, it will remain the same over the course of a playthrough.

And it should remain the same. We use define for things that shouldn't change after the game has started, and for things that do change, there's the default statement. Default functions in almost the same way, but we don't need it right now, so let's keep it for another tutorial.


Character( [arguments] ) creates a Character object for us. Objects are a very important thing in all of programming. We could go on and on about them, but right now, let's just say what an object is.

It's a variable that bundles a bunch of stuff together under one name. Character object bundles together:

  • Name of the character
  • Side Image of the character
  • How character's name and dialogue look
  • And more.

Finally, we haven't mentioned arguments. Arguments are there to provide additional info to whatever we're creating. Character object has one mandatory argument, and that is the name of the character that we're defining.

If you're happy with that, you can join me at the next code block. Otherwise, a more programmer-friendly definition follows: 

Objects encapsulate functions and variables to a single variable. When defined under an object, variables are instead called properties, and functions are instead called methods. They are called in a similar way, and they're more powerful in many situations than standalone variables and functions are. However, even with how awesome they are, they shouldn't always be your first choice. There are many cases where using something simpler suffices just fine.


Whew. That was a lot of theory. But now we can get back to coding again. Let's see what we can do with the Character object.

define l = Character("Lezalith", who_color = "00FF00", what_color = "FF0000")

label start():
    
    l "Hi again!"

    l "How are you doing today?"

    return

We've added some arguments to the definition of our Character. Characters are objects that can use arguments with prefixes, a thing not entirely common. There is the who_ prefix which changes how the name of a Character looks. There is the what_ prefix which changes how Character's lines are written. And finally, window_ changes how the textbox looks when a Character is speaking.

As an example, one of the style properties we can change is color. who_color changes the color of character's name, and what_color changes the color of their dialogue.

(As you can probably tell, 00FF00 means green and FF0000 means red. These are called hex codes, and you can easily find them on websites like this one.)

I want to add more properties, but turns out, the line would be so long that it wouldn't fit on the webpage. However, you can split one line into multiple lines. Not only does that make your code more readable, you can also include empty lines to organize it even more. For example, here, I'm keeping who_ arguments separated from the what_ arguments.

define l = Character("Lezalith",
    who_color = "00FF00", 
    
    what_color = "FF0000")

label start():
    
    l "Hi again!"

    l "How are you doing today?"

    return

There are way more style properties than this, and they are split into categories. Character's arguments prefixed with who_ and what_ can use two of these categories. Color is an example of a text style property, all of which can be found here. Let's try some more. We'll make the text bigger, and in a different font. Ren'Py doesn't know many fonts by default, so I'll use the bold version of the original one.

define l = Character("Lezalith",
    who_color = "00FF00", 

    what_color = "FF0000",
    what_size = 72,
    what_font = "DejaVuSans-Bold.ttf")

label start():
    
    l "Hi again!"

    l "How are you doing today?"

    return

And I'll show you the result right away. Except that...

Whoops. That doesn't look right.

Let's try to add a positional style property then, the other category of style properties that Characters can use, which you can find here, on the same page.

All I'm going to do is move the text higher. I could change its pos or maybe its anchor, but I'll just go with yoffset. offset changes the position after it's calculated from other properties, so that way, I don't have to worry about breaking anything. And while offset takes two numbers, yoffset just one: the vertical offset.

define l = Character("Lezalith",
    who_color = "00FF00", 
    who_yoffset = -200,

    what_color = "FF0000",
    what_size = 72,
    what_font = "DejaVuSans-Bold.ttf",
    what_yoffset = -200)

label start():
    
    l "Hi again!"

    l "How are you doing today?"

    return

This moves both the name and the dialogue 200 pixels up. It looks like a lot, but I'll need more space in just a second. See how that turned out:


Lastly, I would like to discuss text tags.

If you have some programming experience, you might know tags from HTML, except that HTML ones are surrounded by < and >, and Ren'Py ones are surrounded by { and }. In Ren'Py, tags aren't used nearly as often, but often nonetheless.

What if you need bold text to emphasise what your character is saying? Or italic text for his thoughts? Or hey, maybe he's dreaming, and you want to use a different font for the dream altogether, while keeping the default you set in the Character's define-ition.

This is what tags are used for, to affect a marked part of a text. I'll write three dialogue lines, one to demonstrate each of the three cases I've just mentioned, but all the tags can be found here.

define l = Character("Lezalith",
    who_color = "00FF00", 
    who_yoffset = -200,

    what_color = "FF0000",
    what_size = 72,
    what_font = "DejaVuSans-Bold.ttf",
    what_yoffset = -200)

label start():

    l "This is how I can {b}shout out loud!{/b}"

    l "This is... I don't {i}actually know{/i} what this is."

    l "Maybe it's {font=DejaVuSans.ttf}just a dream.{/font}"

    return

The first line has the {b} tag, which makes some text bold. Note that the font our Character is using by default is already a bold font, so the change isn't as noticable.

A tag is closed with another tag, one with the same name, just with a forward slash right before the name, like so: {/b}. That marks where the effects of tags end.

The second line has the {i} tag, which makes some text italic. Contrary to the {b} tag, this one is considerably more noticable. It is closed by the {/i}.

And finally, the {font} tag. This one, like many others, needs an argument. Tag arguments are put into the curly brackets, right after the name, with an equal sign between the two.

An argument is only demanded by the opening tag, which is why we write the closing tag without it: {/font}. And in our case, we're using the regular version of DejaVuSans font.

Which is, by the way, the default font used across Ren'Py.

But this tutorial wasn't. What have we learned this time?

  • How we can use the define statement
  • What Character objects are
  • How style properties can be used in Character definitions
  • What text tags are and how to use them

And in the next one, I'll finally show you how to show some images. The novel is about to get visual!