Ren'Py Tutorial: Character Overrides and Inheritence

Ren'Py Tutorial: Character Overrides and Inheritence

Definitions

A quick note before we begin: in this tutorial, I’ll be referring to both characters and Characters. A character refers to the person in the plot - they have a defined personality, goals and dreams, and hopefully do interesting things throughout the story. A Character is the object that we’re using to display text, and if you have no idea what I mean by that, you’re probably in the wrong place. Anyway, without further ado, let’s get into this!

Too Many Characters

Imagine the following scenario: you’ve got a scene in your visual novel where you’re introducing a character called Alice. She’s been defined like so:

default alice = Character("Alice", who_color="#6f73ff", what_color="#29248f")

 

Before she appears, the POV character (let’s call them Bob) hears her from offscreen, and he doesn’t know her name. For this line she’ll be referred to as “Offscreen Voice”, so we define another Character for her:

default alice_offscreen = Character("Offscreen Voice", who_color="#6f73ff", what_color="#29248f")

 

The scene then starts out as follows:

alice_offscreen "My blade is missing...where has it gone?"

show alice_staring at center

alice "You...did you take my blade?"

 

Only…wait…Since we’re using the Alice Character on the third line, her name will be displayed as Alice, even though we don’t know who she is in the story yet. We can’t refer to her as Offscreen Voice - she’s now onscreen. Looks like we’ll need to define a new character.

default alice_strange_woman = Character("Strange Woman", who_color="#6f73ff", what_color="#29248f")

 

Okay, now we can continue writing this scene.

alice_offscreen "My blade is missing...where has it gone?"

show alice_staring at center

alice_strange_woman "You...did you take my blade?"

bob "I - of course not, madame. I would not know what to do with a blade, were I given one."

alice_strange_woman "Are you certain?"

 

Except…maybe we want to make Alice talk a bit slower for the last line, so that she sounds more threatening, and we know that this is a character trait of hers, so to save on tags we’re going to hardcode it into the Character object. Guess we need yet another Character. And we’d better make another one, too, for once we know her name, later in the game.

default alice_slow_talk = Character("Alice", who_color="#6f73ff", what_color="#29248f", what_slow_cps=10)

default alice_strange_woman_slow_talk = Character("Strange Woman", who_color="#6f73ff", what_color="#29248f", what_slow_cps=10)

 

To recap, we’ve given this character three lines of dialogue, but have already had to define five different Character objects for her. Oh dear, this is starting to get quite complicated. Thankfully, however, there’s an easier way around this situation, which drastically cuts down on your variables.

Inline Overrides

Did you know that when you have a character say something in Ren’Py, you can pass in extra variables which modify the attributes of the Character for that one line? That’s a bit of a mouthful, so let’s use an example, with Alice’s introductory scene.

Remember how we needed to create a new character just to have Alice’s name display differently? Since she’s probably not going to be offscreen as a mystery voice that often, let’s just change her name for her initial line.

alice_offscreen "My blade is missing...where has it gone?" (name="Offscreen Voice")

show alice_staring at center

 

Pretty simple, right? All we needed to do was add in the changed attributes in after the text being displayed, and that line will display as though that attribute has changed in the actual Character object. Multiple attributes are easy, too - just keep adding them in, with commas to break them up. Let’s say that we’ve decided that Alice’s text should be a little smaller, to indicate that she’s far away when she speaks:

alice_offscreen "My blade is missing...where has it gone?" (name="Offscreen Voice", what_size=15)

show alice_staring at center

 

Now these opening lines only require one Character object, and look like this:

alice "My blade is missing...where has it gone?" (name="Offscreen Voice", what_size=15)

show alice_staring at center

alice "You...did you take my blade?" (name="Strange Woman")

bob "I - of course not, madame. I would not know what to do with a blade, were I given one."

alice "Are you certain?" (name="Strange Woman", what_slow_cps=10)

 

While it can be a little fiddly to check which attributes are being changed if you have long text lines, it nevertheless keeps your characters simple, and means that you don’t need to create a single character for every slight variation in character text display.

Inheriting Attributes

But what if you’re planning on keeping Alice labelled as Strange Woman for more than just a few lines? What if she’s hostile to Bob, and he doesn’t find out her name until far later in the game? It wouldn’t be practical to pass in the attribute change for her name for dozens, possibly hundreds, of lines, and it would be easy to make mistakes. Luckily, there’s still an easy way to do this.

Before going into this, it’s worth noting that for this scenario, it wouldn’t be the worst idea in the world to create a different Alice Character object, as we initially did in this tutorial - we’ll be using it often enough. But let’s say that after fleshing out Alice’s character and how she should be presented to the player some more, her object now looks like this:

default alice = Character("Alice", who_color="#6f73ff", what_color="#29248f", what_slow_cps=10, what_size=32, what_text_align=0.5, what_font="gui/GothicFont.ttf")

 

We’ve got enough points where she’s referred to as Strange Woman to justify creating another Character, but we’ve also got points where her identical twin sister (named Charlie) shows up that we need a Character for her. Our code is currently looking like this:

default alice = Character("Alice", who_color="#6f73ff", what_color="#29248f", what_slow_cps=10, what_size=32, what_text_align=0.5, what_font="gui/GothicFont.ttf")

default alice_strange_woman = Character("Strange Woman", who_color="#6f73ff", what_color="#29248f", what_slow_cps=10, what_size=32, what_text_align=0.5, what_font="gui/GothicFont.ttf")

default charlie = Character("Charlie", who_color="#6f73ff", what_color="#29248f", what_slow_cps=10, what_size=32, what_text_align=0.5, what_font="gui/GothicFont.ttf")

 

It’s all justified and will save us some clutter in the actual game script, but…it looks kind of messy to have all of those repeated variables, doesn’t it? Thankfully, there’s an easy solution: the kind attribute. 

When you create a Character, if you pass in the kind argument to it, this will cause it to inherit all of the attributes of the argument’s value, except for those that you overwrite. (That is to say, by passing in kind, you’re defining what type of Character this is. It won’t make your characters any nicer; you’ll have to update your script to do that).

Here’s a simple demonstration of how we can create the above three Characters using kind:

default alice = Character("Alice", who_color="#6f73ff", what_color="#29248f", what_slow_cps=10, what_size=32, what_text_align=0.5, what_font="gui/GothicFont.ttf")

default alice_strange_woman = Character(kind=alice, name="Strange Woman")

default charlie = Character(kind=alice, name="Charlie")

 

As you can see, alice_strange_woman and charlie don’t need any new attributes passed into them other than their name attribute - all of the rest will be taken from alice. But what if we wanted Charlie to have smaller text, since she’s more timid than Alice? Too easy:

default charlie = Character(kind=alice, name="Charlie", what_size=28)

 

By knowing when to inherit attributes, we can cut down on extra text in our code, making it easier to read and to understand what a Character will utilise.

Conclusion

The scenarios listed here may be a little niche, but nevertheless, if you’ve made it this far I’m assuming that it’s helped you in some way, so thanks for reading! I’m a big fan of making code more readable (you’ll notice that I named the Character variables after the full name of the characters, rather than using the first letter of their names, as the Ren’Py docs often do), and cutting down on unnecessary clutter is just one way to do that.

Do you have any questions about how to change Character displays? Does anything in this tutorial not make sense, or do you have suggestions on how it could be easier to read? You can drop me a line on the contact page, or via our Discord, and I’ll get back to you as soon as possible. Until then, happy coding!


Related News