Organizing Renpy Code/Files/Scripts

fooslock

Newbie
Feb 15, 2020
65
25
Right, so, I'm about to start working on a project, and as an aid, I've pulled apart a few games to see how individuals more experienced than myself have organized theirs. In no particular order, I'd like to get some feedback and advice, hopefully from those who are also actively developing. I'm going to use Daz3d and Renpy as my mainstays. So here goes.

When it comes to organizing scripts and scenes, is there an ideal way to do it? I've seen some with script naming conventions like script1, script2, etc., and I've seen some games where the script is organized per scene. What do you think about this? If you are actively developing a game, how do you go about it? Are there things to consider when organizing files in these ways? I'd assume there's thinking behind it, like organizing by scene because it might be easier to debug, but does that not increase more work and introduce possible continuity bugs?

Do you go by planned releases when loading images and animations into directories? What would be the ideal way to do this? I've never worked on a large software project before, so any tips regarding this type or organization would be useful. in that vein...

Aside from really basic stuff like "Learn how to write Renpy" or "Watch Daz Tutorials," what are some things I should consider before doing my project? Are there specific topics or resources you would advise looking into before starting? Do you have any advice you might have learned regarding these topics as you developed your game? Again, I'd really like to see if any of the more experienced crowd has some tips regarding this. I've looked through the forums quite a bit now, but most of the stuff I see is either addressing niche topics like specific code/functions or very shallow when it comes to this.

Thanks for reading, I'd like to hear from you.
 

Winterfire

Forum Fanatic
Respected User
Game Developer
Sep 27, 2018
4,989
7,310
Aside from keeping in mind to split scenes in a way so that they can be easily replayed (Even if at the moment you aren't considering this), it is meaningless and up to you. I'd get lost if I had the whole game in a single script, so I split them up. I even go further by splitting them into folders (releases), and then each folder has the scenes in order.
However, this doesn't make the game run faster or anything like that... It is simply my preference, if you prefer to have a big single script, it's completely fine, there is no right way.

As for images, I kept all definitions in a single file (cg.rpy), and all images in a single folder (images/CG), in this case naming was important. If I needed a definition for a CG, I knew right away where to check, and with a good naming/ordering, I could quickly find it.
Again, naming is what works best for you... You could have an increasing number 0001_title, 0002_title, 0003_title, ... or if you want to split them by release, have something like EP1_001_Title, EP1_002_Title, ...
It depends on how you want to organize it, and what works for you, there's no right way in this either.

Due to your existing experience, and how forgiving Ren'Py is, the only advice I can give you is to keep learning by doing.
You know and did enough research to start a project, and if it is a simple one, even easily complete one. You might encounter an issue or two, but that's when you'll do the learning bit.
General advice I can give is to never delete/edit variables after releases, and keep a list of variables in a file, outside of anything, as to be able to support old saves... Even if you end up not using a variable, leave it there.
Use WebP/WebM and remember that if you need full colors, you can define them as such: image background = "#rrggbb", no need to waste disk space by having an actual image.
 
  • Like
Reactions: fooslock

fooslock

Newbie
Feb 15, 2020
65
25
Hey, thanks for showing up and for the advice; I'd have gotten back to you sooner, but I had to take care of the tykes for a bit.

so I split them up. I even go further by splitting them into folders (releases), and then each folder has the scenes in order.
So the directory chain looks something like release_1 > scene_001.rpy, scene_002.rpy, and inside of those are scripts? Would it be a good idea to have scripts paired for each scene and then just jump or call as necessary? I saw a few devs had it go really deep like that and, while more complicated, it seemed like it might be easier to locate bugs or just keep track of information. Building on the shoulders of giants, gonna throw them a few bucks when I get the funds again.

I kept all definitions in a single file (cg.rpy), and all images in a single folder (images/CG), in this case naming was important. If I needed a definition for a CG, I knew right away where to check, and with a good naming/ordering, I could quickly find it.
So I'm aware you can define characters but are you basically defining anything you want to quick reference? like I see you can call images fat out, but you say you define them? If so, whats the advantage of that? Easier code? Like instead of super_long_image_name.png you can just show "slin" which is the shorthand for the image?

never delete/edit variables after releases, and keep a list of variables in a file, outside of anything, as to be able to support old saves... Even if you end up not using a variable, leave it there.
Yea, I've seen that mentioned elsewhere. Does it tend to bork saves or something, adding and removing variables? what's the deal behind that?

Again, thanks for your time.
 

GNVE

Active Member
Jul 20, 2018
654
1,131
First off start with a couple of small projects. It's better to make big mistakes in small projects. Big mistakes in big projects end projects. When you have a couple made you can move onto big projects.

When naming things you need to ask yourself the following question: "If I come back to this in a year, do I still know what all this stuff does easily?"
So "label day1amybreakfast:" is a lot more informative to you than "label scene1:" or "label d1abf:"
I'd suggest you also keep the image names similar to the label name. Again "day1amybreakfast-001.png" is a lot more informative then "0001.png"
As for how you group script files it depends on the size of updates. You want to find things in a script file (though labelling stuff correctly does wonders for that as well). So If you can't find stuff easily and quickly the script file was to large.
 
  • Like
Reactions: fooslock

fooslock

Newbie
Feb 15, 2020
65
25
Hey, thanks for coming and sharing.
First off start with a couple of small projects. It's better to make big mistakes in small projects. Big mistakes in big projects end projects. When you have a couple made you can move onto big projects.
I can feel that yea. I was going to work on a small project, maybe a backstory for a main LI as standalone content, so I can practice with animations and Daz and whatnot. Maybe throw it back into a big game later or release it as a standalone later on or whatever.

When naming things you need to ask yourself the following question: "If I come back to this in a year, do I still know what all this stuff does easily?"
So "label day1amybreakfast:" is a lot more informative to you than "label scene1:" or "label d1abf:"
I'd suggest you also keep the image names similar to the label name. Again "day1amybreakfast-001.png" is a lot more informative then "0001.png"
Oh def. I was throwing out placeholder names, but my naming conventions usually follow easy-read standards, if nothing else, because I can barely remember what I ate yesterday versus variables from a year ago. Memory of a goldfish, I tell you.

As for how you group script files it depends on the size of updates. You want to find things in a script file (though labelling stuff correctly does wonders for that as well). So If you can't find stuff easily and quickly the script file was to large.
When you say labeling, are you alluding to something Renpy-specific or simply labels in general? I still have a lot more to learn about Renpy; I'm mainly just diving in and dicking around right now while I train my Daz skills.
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Respected User
Donor
Jun 10, 2017
10,265
15,074
When it comes to organizing scripts and scenes, is there an ideal way to do it?
Yes, there is an ideal way to do it: The one you feel the most at ease with.

This being said, should be avoided the fact to put everything in a single file, and anonymous names ("flag01", "flag02", "kissingScene01", "action02", etc.) for the label, variables, whatever.
What matters is that you (and if it apply the persons working with you) understand the organization and can find relatively easily what you (or they) are looking for.

Making a game, especially as hobby and therefore on your free time, need time, a very long time that will spread over years. During all that time, there will be low moment, when you are over saturated and just want to throw the game to the trash. For this reason, it's important that you don't have to struggle more than necessary.

Let's say that you need to use the variable that tell you if the first kiss between the MC and a girl happened in the park or in the coffee shop.
Ideally, the name of the variable should be explicit enough for you to remember it. But let's be honest, whatever how explicit you named the variable, after not having to used it for months, you'll not remember it. Therefore, you should know in what file you'll have to search for it, as well as, globally, at what place of that file you'll find it. And the name should be explicit enough for you to recognize it when you see it.

Be noted that explicit names also help you to understand your code. You'll look back at something you wrote months ago, see if whateverVariableName == "42", and the name, as well as the value, should be enough for you to remember what you are testing.
It's why anonymous names are to avoid at all cost. It's what make the difference between:
Python:
label park052:
    [...]
    if flag07 == 3:
       GIRL1 "Do you remember, what happened here two years ago ?"
   [...]
and:
Python:
label girl1McParkReminiscent:
    [...]
    if girl1FirstKiss == "park":
       GIRL1 "Do you remember, what happened here two years ago ?"
   [...]
In the first case, you know that it's a scene in the park, and will need to read the dialog to find what the condition mean. In the second, you know precisely what scene in the park happen, and just reading the condition tell you what it mean.
It's time saved, and struggling avoided. As insignificant it can seem to save few seconds that way, when it happen 100 times a day, it starts to make sens.


I'd assume there's thinking behind it, like organizing by scene because it might be easier to debug, but does that not increase more work and introduce possible continuity bugs?
There will be bugs anyway. Therefore what matters isn't much, "oh, I should do like this, it should reduce the number of bug", than, "I should do like that, it will be easier to find the bugs".

It's Wednesday afternoon, you just come back from works. You're excited, because you released the new update last night, and want to know what people think about it.
You open your Patreon page, your game thread here, or whatever other media where you can get feedback.
And then you see people saying that "hey, in the coffee scene, after the second girl leaved, there's few time where it's not the right person that say the dialog line". Ideally someone give you the lines and you can just do a search... But we don't live in an ideal world, people will rarely say more that what I put in quotation marks.
Knowing in what label you'll find the said "coffee scene after the second girl leaved" will make life way easier for you, than if you've to browse the whole "update5" label to find when is the scene.

So, yes, as you think it's easier to debug. What is false in your assertion is to believe that it will prevent continuity bugs. Unless you make a Kinetic Novel, you'll have embedded menus, and if structures, possibly up to ten levels. You'll quickly lost track of where you are and where you should go next:
Python:
label whatever:
    menu:
        "choice 1":
           if condition1:
              if condition2:
                  menu:
                     "choice 1":
                         if condition3:
                         else:
                     "choice 2:"
              else:
                  menu:
                      "choice 1":
                      "choice 2":
           else:
                if condition 4:
                    menu:
                        "choice 1":
                        "choice 2":
                else:
                    if condition5:
                    else:
        "choice 2":
            [...]
compared to something more explicit:
Python:
label whatever:
    menu:
        "choice 1":
           jump whateverChoice1
        "choice 2":
           jump whateverChoice2

label whateverChoice1:
    if condition1:
        jump whateverChoice1Condition1
    [implicit "condition 1 is false"]
    jump whateverCommonAfterCondition1

label whateverChoice1Condition1True:
    if condition2:
        jump whateverChoice1Condition1Then2
    [implicit "condition 2 is false"]
    jump whateverCommonAfterCondition1Then2
[...]
It also limits the code you have to write, because there's part of the code that will apply to more than one context:
Python:
label whatever:
    menu:
        "choice 1":
            [specific to choice1]
            if condition1:
                [common part]
            else:
                [specific to choice 1]
            [specific to choice1]
        "choice 2":
            [specific to choice2]
            if condition2 and condition3:
                [common part]
            else:
                [specific to choice 2]
            [specific to choice2]
compared to:
Python:
label whatever:
    menu:
        "choice 1":
            $ temporaryValue = "choice 1"
            jump whateverChoice1
        "choice 2":
            $ temporaryValue = "choice 2"
            jump whateverChoice2

label whateverChoice1:
     [specific to choice1]
     if condition1:
         jump whateverCommonPar
     else:
        [specific to choice 1]
     jump whateverChoice1Continue

label whateverChoice2:
    [specific to choice2]
    if condition2 and condition3:
         jump whateverCommonPar
    else:
        [specific to choice 2]
     jump whateverChoice2Continue

label whateverCommonPart:
     [common part]
     if temporaryValue = "choice 1":
         jump whateverChoice1Continue
     else:
         jump whateverChoice2Continue

label whateverChoice1Continue:
    [specific to choice1]
    jump whateverAfterChoice

label whateverChoice2Continue:
    [specific to choice2]
    jump whateverAfterChoice
You wrote the common part only once, what mean less works for you, less risk of errors, and less risk for forgot to correct one occurrence of the code because you forgot that it appear twice.


Aside from really basic stuff like "Learn how to write Renpy" or "Watch Daz Tutorials," what are some things I should consider before doing my project?
Firstly you must know the whole story, from starts to stop.
Not all the dialog lines for all the scenes, but all the key points and their order. And by "knowing" I don't mean "in your head", it must be wrote somewhere. That way you know where you're going, even in a far future, what permit you to stay consistent and to anticipate the future.

If a girl is planing a surprise birthday party for the MC, she don't do it when the update containing the party is released. She starts doing it days, if not weeks, before. This have an impact on her attitude, and this should be visible (but not necessarily understandable) for the player.
In Triple Ex by example, the sister is now pregnant. Two update before we learned it, her behavior started to change. The player didn't noticed it in the first update ; she was eating more and never visible early in the morning. In the second update, the player caught her sick in the morning ; those who thought about it, adding the fact that she eat more, had a strong clue regarding the reason. Then finally appear the update where her pregnancy was announced to the player.
This is only possible if you know beforehand that she'll be pregnant, and that it will be announced in "that scene".

It's why you need to know your whole story, and all the impacting element in it, before you starts writing. Whatever how good your story is, and how good you are at writing, your game will feel better thanks to this. Even if the player don't get the clue, when the situation will finally happen he'll be "oh, so it's why [whatever]... Well played dev, well played".


Secondly, you must code all your game mechanism before you starts your game.
Even if it's something that will not appear before the tenth update, you must have the code before the very first release. You'll struggle to make it works, it's mandatory, even me would struggle. So, it's better to struggle before you have the player pressure on your shoulders.
It also avoid false promises. Whatever game mechanism you promises, you know that you'll be able to do it, because it's already done. This permit to not have a game with a smartphone icon, and a "Will come soon" that appear when you click on it, this while it's obvious that the game will be finished soon.


Thirdly, you must already know what assets you'll use for each elements of the game.
You don't necessarily need to get them right from the starts, but know what you'll use will be time saver ; there's tons of assets, searching for the right one can take full day.
Plus, when you put this in perspective with the first point, it permit you to anticipate. "Hey, you know, my uncle have a beach house. If I ask him nicely, I'm sure that he would let me use it. It's big enough, we could all pass a week-end there". This is great, but only if you don't end using a small hut for the said beach house, something clearly too small for everyone to fit in during a whole week-end.
 
  • Like
Reactions: fooslock

Winterfire

Forum Fanatic
Respected User
Game Developer
Sep 27, 2018
4,989
7,310
So the directory chain looks something like release_1 > scene_001.rpy, scene_002.rpy, and inside of those are scripts? Would it be a good idea to have scripts paired for each scene and then just jump or call as necessary? I saw a few devs had it go really deep like that and, while more complicated, it seemed like it might be easier to locate bugs or just keep track of information. Building on the shoulders of giants, gonna throw them a few bucks when I get the funds again.
I used jump, from a scene to another.
It is considered kind of "dirty", but I never had any issue with it as long as I cleaned the stack from time to time... However, if you want to do it the clean way, return and then call the next scene.


So I'm aware you can define characters but are you basically defining anything you want to quick reference? like I see you can call images fat out, but you say you define them? If so, whats the advantage of that? Easier code? Like instead of super_long_image_name.png you can just show "slin" which is the shorthand for the image?
Defining a character is different than using images of that character...
When defining a character, you are defining the speaker (The font it uses, the color of their text, of their name, if they have an outline, and so on), as for the images, yes. It is particularly useful if those are also animations, so you can apply the mask once, then use the image with a short name whenever you need it.

Definition: Image character_smiling = Movie(path of movie, path of mask)
Usage: show character_smiling


Yea, I've seen that mentioned elsewhere. Does it tend to bork saves or something, adding and removing variables? what's the deal behind that?

Again, thanks for your time.
Ren'Py will try to load something, but fails because that something no longer exists, making the saves incompatible and people very angry.
 
  • Like
Reactions: fooslock

fooslock

Newbie
Feb 15, 2020
65
25
Anne, thanks for stopping by and coming off the top ropes to body my noob self; appreciate all you do for this community.

Yes, there is an ideal way to do it: The one you feel the most at ease with.
I feel it. I'm trying to establish that now so it flows easier as I go.

and anonymous names ("flag01", "flag02", "kissingScene01", "action02", etc.) for the label, variables, whatever.
I've seen this while looking through others' code. I chalked it up to some sort of attempt to obfuscate code to deter modders or cheaters, but I guess it could just be nonadherence to human-readable programming standards. Dunno why anyone would try to obfuscate code (aside from keeping people like me from filching it :D) in single player games but yea.

(and if it apply the persons working with you) understand the organization
I don't plan on that but who knows, we'll see if that time comes. It's already enough work as is doing it all by alone. Another pair of hands would be nice; I just lack the resources to entice others to play ball.

Making a game, especially as hobby and therefore on your free time, need time, a very long time that will spread over years. During all that time, there will be low moment, when you are over saturated and just want to throw the game to the trash. For this reason, it's important that you don't have to struggle more than necessary.
I hear that. For what it's worth, I can hopefully use this knowledge later after I graduate with my software engineering degree, so it's not all time wasted for nothing. I can say I worked on this project under a NDA and just highlight bulletpoints for the resume, so there is some benefit aside from telling a story for its own sake.

Let's say that you need to use the variable that tell you if the first kiss between the MC and a girl happened in the park or in the coffee shop.
Ideally, the name of the variable should be explicit enough for you to remember it. But let's be honest, whatever how explicit you named the variable, after not having to used it for months, you'll not remember it. Therefore, you should know in what file you'll have to search for it, as well as, globally, at what place of that file you'll find it. And the name should be explicit enough for you to recognize it when you see it.
When it gets so complex, do people keep track of variables alone through Excel, or what?

Be noted that explicit names also help you to understand your code. You'll look back at something you wrote months ago, see if whateverVariableName == "42", and the name, as well as the value, should be enough for you to remember what you are testing.
It's why anonymous names are to avoid at all cost.
Again yea, I tend to be comment and doc-heavy for, if nothing else, my own lack of ability to memorize simple things.

There will be bugs anyway. Therefore what matters isn't much, "oh, I should do like this, it should reduce the number of bug", than, "I should do like that, it will be easier to find the bugs".
Yea good point. It's why I was contemplating making each scene its own script so I can easily reference it for testing. I use VS code; aside from the ren'py linter, how do people bug test? Is there any secret method to it or is it just trial and error and the linter?

You wrote the common part only once, what mean less works for you, less risk of errors, and less risk for forgot to correct one occurrence of the code because you forgot that it appear twice.
Yea it's a good point. Feels like a lot of this can be reused for heavy if/else statements.

Firstly you must know the whole story, from starts to stop.
Not all the dialog lines for all the scenes, but all the key points and their order. And by "knowing" I don't mean "in your head", it must be wrote somewhere. That way you know where you're going, even in a far future, what permit you to stay consistent and to anticipate the future.
I currently am at the "in my head" phase and slowly moving down to the "per act" phase, followed shortly by "per scene" phase, if any of that makes sense. Like, I got an idea of what I want to accomplish but it needs more fleshing out. Definitely scratching my creative itch.

Secondly, you must code all your game mechanism before you starts your game.
Even if it's something that will not appear before the tenth update, you must have the code before the very first release. You'll struggle to make it works, it's mandatory, even me would struggle. So, it's better to struggle before you have the player pressure on your shoulders.
I see. I don't intend to be too heavy into game mechanics; I'm going for a branching VN, not a full-on "game"; I don't feel confident enough for that large of scope yet.

Thirdly, you must already know what assets you'll use for each elements of the game.
You don't necessarily need to get them right from the starts, but know what you'll use will be time saver ; there's tons of assets, searching for the right one can take full day.
Ain't that the truth. Just making the characters stretches time, nonetheless, everything they need.

Thanks again for all the input, you're awesome.
 

fooslock

Newbie
Feb 15, 2020
65
25
I used jump, from a scene to another.
It is considered kind of "dirty", but I never had any issue with it as long as I cleaned the stack from time to time... However, if you want to do it the clean way, return and then call the next scene.
Is that dirty? Jump doesn't clean the stack? I watched a 4-part "Ren'py master course" I found on Youtube but mostly I'm working off my experience from playing around abit, prior python knowledge, and digging through others' Renpy code, so that's the bulk of my knowledge for now.

Definition: Image character_smiling = Movie(path of movie, path of mask)
Usage: show character_smiling
Good to know, I'll keep that in mind, thanks.

Ren'Py will try to load something, but fails because that something no longer exists, making the saves incompatible and people very angry.
Yeah, I saw another post by anne O'nymous about how-to variables and read through that, and it did mention that, yeah. I'm slowly saving references for rereading, so it's nice to have all this to pin to my bookmarks as well. Again, thanks for coming by and being wonderful, and I appreciate the effort you put into the community.
 
  • Red Heart
Reactions: Winterfire

Winterfire

Forum Fanatic
Respected User
Game Developer
Sep 27, 2018
4,989
7,310
Is that dirty? Jump doesn't clean the stack? I watched a 4-part "Ren'py master course" I found on Youtube but mostly I'm working off my experience from playing around abit, prior python knowledge, and digging through others' Renpy code, so that's the bulk of my knowledge for now.
Not automatically, no. However, back when I was learning Ren'Py and discovered about this, and made a thread about it, the result is that it hardly makes a difference.
I wouldn't worry about it too much, as I've said before, Ren'Py is quite forgiving so if you make a mistake or two it might not even be noticeable.

If I were to use Ren'Py again, I'd just return everytime I am done with a scene, and then jump to a new one. This way, I won't have to worry about it, but back in my old project I had just plugged the cleaning in a function that I had to call often anyway (since it was a sandbox), so it worked just as fine.


-edit-
Something important to remember is the difference between show and scene, that's huge and very important.
I know you've said that you have watched many tutorials, but very often people still make this mistake, and unlike the previously mentioned stuff, this does affect game's performance.
 

noping123

Well-Known Member
Game Developer
Jun 24, 2021
1,483
2,385
Not automatically, no. However, back when I was learning Ren'Py and discovered about this, and made a thread about it, the result is that it hardly makes a difference.
I wouldn't worry about it too much, as I've said before, Ren'Py is quite forgiving so if you make a mistake or two it might not even be noticeable.

If I were to use Ren'Py again, I'd just return everytime I am done with a scene, and then jump to a new one. This way, I won't have to worry about it, but back in my old project I had just plugged the cleaning in a function that I had to call often anyway (since it was a sandbox), so it worked just as fine.


-edit-
Something important to remember is the difference between show and scene, that's huge and very important.
I know you've said that you have watched many tutorials, but very often people still make this mistake, and unlike the previously mentioned stuff, this does affect game's performance.

Just to clear this up - jump doesn't add stuff to the stack. Call does, but jumping doesn't. The reason you likely had trouble is because of the sandbox elements you included.

(Example: in my current release, I have free roam sections, as well as optional minigames available during those freeroams. I found early in testing, if I didn't clear the stack at certain points, then if certain steps were followed involving the minigames, the script would eventually return to earlier points when it shouldn't.)

But if *all* you do is jump, you'll never run into stack issues.

In fact, if all you do is jump and never call anything - and then add a "return" somewhere, you'll just go to the main menu. Return on an empty stack acts as an end to the game and bumps you back to the menu - and if all you ever do is jump, the stack doesn't grow.

The majority of the time, you want to jump - you generally want to avoid calls in renpy unless you have a REASON to call. Jump literally does what it sounds like - it jumps to wherever you direct it, and essentially "forgets" where it was. (Not quite, thanks to rollback and all of that, but whatever). Call makes it a point to remember where you were, hence the stack. You'll often see "real programmers" hate on stuff like jump, because of it's similarity to "goto" which tends to be near universally hated, but in renpy jump is usually the correct answer.

That's why it's referred to as the "Call stack" - whenever you call, it makes a note of where you were, so you can return to that point. Jump doesn't do that, so there's no "cleaning" necessary.
 

fooslock

Newbie
Feb 15, 2020
65
25
Not automatically, no. However, back when I was learning Ren'Py and discovered about this, and made a thread about it, the result is that it hardly makes a difference.
I wouldn't worry about it too much, as I've said before, Ren'Py is quite forgiving so if you make a mistake or two it might not even be noticeable.
Good to know, good to know. Seems pretty straight forward so far, not too complicated.

If I were to use Ren'Py again, I'd just return everytime I am done with a scene, and then jump to a new one. This way, I won't have to worry about it, but back in my old project I had just plugged the cleaning in a function that I had to call often anyway (since it was a sandbox), so it worked just as fine.
Yea, returning out is how I'm currently handling it.

Something important to remember is the difference between show and scene, that's huge and very important.
I know you've said that you have watched many tutorials, but very often people still make this mistake, and unlike the previously mentioned stuff, this does affect game's performance.
Many tutorials, not quite. I watched one 4-parter, got the general gist, and then jumped in to mess around. I learn by trial and error better than tutorials. Good to know, I'll give that a looksee.
 

Winterfire

Forum Fanatic
Respected User
Game Developer
Sep 27, 2018
4,989
7,310
Just to clear this up - jump doesn't add stuff to the stack. Call does, but jumping doesn't. The reason you likely had trouble is because of the sandbox elements you included.

(Example: in my current release, I have free roam sections, as well as optional minigames available during those freeroams. I found early in testing, if I didn't clear the stack at certain points, then if certain steps were followed involving the minigames, the script would eventually return to earlier points when it shouldn't.)

But if *all* you do is jump, you'll never run into stack issues.

In fact, if all you do is jump and never call anything - and then add a "return" somewhere, you'll just go to the main menu. Return on an empty stack acts as an end to the game and bumps you back to the menu - and if all you ever do is jump, the stack doesn't grow.

The majority of the time, you want to jump - you generally want to avoid calls in renpy unless you have a REASON to call. Jump literally does what it sounds like - it jumps to wherever you direct it, and essentially "forgets" where it was. (Not quite, thanks to rollback and all of that, but whatever). Call makes it a point to remember where you were, hence the stack. You'll often see "real programmers" hate on stuff like jump, because of it's similarity to "goto" which tends to be near universally hated, but in renpy jump is usually the correct answer.

That's why it's referred to as the "Call stack" - whenever you call, it makes a note of where you were, so you can return to that point. Jump doesn't do that, so there's no "cleaning" necessary.
Oh ok, I must have mixed up the two things then. Been years since I touched Ren'Py, I did use call as well.
 
  • Like
Reactions: fooslock

fooslock

Newbie
Feb 15, 2020
65
25
Just to clear this up - jump doesn't add stuff to the stack. Call does, but jumping doesn't. The reason you likely had trouble is because of the sandbox elements you included.

(Example: in my current release, I have free roam sections, as well as optional minigames available during those freeroams. I found early in testing, if I didn't clear the stack at certain points, then if certain steps were followed involving the minigames, the script would eventually return to earlier points when it shouldn't.)

But if *all* you do is jump, you'll never run into stack issues.

In fact, if all you do is jump and never call anything - and then add a "return" somewhere, you'll just go to the main menu. Return on an empty stack acts as an end to the game and bumps you back to the menu - and if all you ever do is jump, the stack doesn't grow.

The majority of the time, you want to jump - you generally want to avoid calls in renpy unless you have a REASON to call. Jump literally does what it sounds like - it jumps to wherever you direct it, and essentially "forgets" where it was. (Not quite, thanks to rollback and all of that, but whatever). Call makes it a point to remember where you were, hence the stack. You'll often see "real programmers" hate on stuff like jump, because of it's similarity to "goto" which tends to be near universally hated, but in renpy jump is usually the correct answer.

That's why it's referred to as the "Call stack" - whenever you call, it makes a note of where you were, so you can return to that point. Jump doesn't do that, so there's no "cleaning" necessary.
Thanks for stopping by and clearing that up, real informative, I appreciate it. I'm not going to go too crazy on my first run. I intend to start with a branching VN my first time, nothing too crazy.
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Respected User
Donor
Jun 10, 2017
10,265
15,074
I don't plan on that but who knows, we'll see if that time comes. It's already enough work as is doing it all by alone. Another pair of hands would be nice; I just lack the resources to entice others to play ball.
It's not just a question of planned help.
It happen less nowadays, or more precisely it's less visible because more diluted between the many game threads, but there's people helping to solve an issue, or a bug, in the game. The less they have to struggle to understand the code, the more they'll be ready to do it.
I know that personally there's time where I wanted to fix a bug for a dev, and just gave up because it was a total mess. I don't care passing ten minutes to solve someone else bug, but I'm not ready to pass a full hour just to find where the bug happen. And I'm sure that I'm far to be the only one in that case.


I hear that. For what it's worth, I can hopefully use this knowledge later after I graduate with my software engineering degree, so it's not all time wasted for nothing.
Even if in the end you don't release your game, because you don't have the time for, it will never be wasted time. Unlike most of what you're doing at school, it's a fully practical application of your knowledge. You'll not learn new algorithm, and probably not new way to apply what you already know, but you'll learn the difference between theory and practice... And god, there's a lot of differences.


When it gets so complex, do people keep track of variables alone through Excel, or what?
It totally depend on the person, and sometimes also of the context.
I know that one of the guy at works use a basic text file, while for a long time I used a homemade widget in Perl. For Ren'Py, I guess that most are just relying on their "variable.rpy" file, or the top bloc of their "script.rpy" file, where they declare all variables.
Here again there's no "good answer", just what you feel the most at ease with. And I'm tempted to say that this apply even more to you, since soon or later it will be your job. Use this opportunity to also experiment and find the ways that you're the more at ease with. When you'll have to pass 8 hours day codding, being at ease right from the starts is important.


Again yea, I tend to be comment and doc-heavy for, if nothing else, my own lack of ability to memorize simple things.
pro tip: Inline comments are sometimes way more significant that a full bloc of comment.
It's wrong to believe that a good code is self commenting (yet there's people to still say it). A good code tell you what it's doing, but not why it's doing it. And most of the time, it's the second question that will pop in your mind, especially when coming back to code you wrote months ago.


I use VS code; aside from the ren'py linter, how do people bug test? Is there any secret method to it or is it just trial and error and the linter?
Mostly a trial and error approach. Really few know that there's a linter, and even less understand why it's important (will yet being limited).
There's a lot of debugging tools in Ren'Py, both native and third party, but in the end they only show that there's an error, not why it happen. By example, label tracker is good to tell you that there's a return missing somewhere, but it will not help you to know where it should be. Same for the console, that can tell you that a variable is wrong, but will not help you know why it's wrong.
And of course, like most of the content is visual, either through the CGs or the dialog lines, the only way to know that a condition is wrong, is by playing the game and seeing that you don't have the expected image or dialog line.

I'm not sure to what extend it's effectively practical, but one approach can be to have secondary labels dedicated to debugging. Something like:
Python:
# A label used only for debugging purpose
label whatever_debug:
    menu:
        "Sarah route opened":
              $ sarahLove = 10
        "Sarah route closed":
              $ sarahLove = 0
    menu:
        "Kissed her in the park":
              $ firstKissSarah = "park"
        "Kissed her in the coffee shop":
              $ firstKissSarah = "coffee"
    jump whatever

[...]

label whatever:
    [...]
If you put the "whatever_debug" label in a "debug.rpy" file, it's easy to remove the debug content from the distribution.
That way, you can test all the possible variation of the "whatever" label just jumping to "whatever_debug" and making different choices. You'll see more easily if the game react as expected or not.
By ending "whatever_debug" by something like:
Python:
    menu:
        "update 2 bar scene":
            jump somewhere
        "update 2 movie scene":
            jump somewhereElse
You can extend those debugging capabilities.
But, as I said, in the end all rely on a trial and error approach. You have to witness by yourself if it works as expected or not. It's not like with more abstract code where you can just call a function and verify that the returned value is the one expected.


I currently am at the "in my head" phase and slowly moving down to the "per act" phase, followed shortly by "per scene" phase, if any of that makes sense. Like, I got an idea of what I want to accomplish but it needs more fleshing out. Definitely scratching my creative itch.
It totally make sense. Think about it in a more abstract way... It's how you already deal with code writing ; you want to make "this" program, therefore you need to do "that", and it's done "like this".
No one starts by writing a function, then wonder what other function can works well with it. You've the whole result in your head, then you decompose it, step by step, slowly removing a level of abstraction.
You starts with "load the data", pass by "select the file, read its content", and at the end you'll have the whole "open the file, read this, ensure it's correct, put it there, read that, ensure it's correct, put it here, close the file".

Pure writers would perhaps say that it's a bad way to do, but it's a way that works and you already have the habit to deal with it. Therefore there's no reason to change it.


I see. I don't intend to be too heavy into game mechanics; I'm going for a branching VN, not a full-on "game"; I don't feel confident enough for that large of scope yet.
I used the term as a generic concept. While there's not much development behind, it also apply to the use of variables like "girlLove". There's many games that have such value, but never ever use them.
Thinking beforehand how it will impact the story, and how to make this be seen by the player, is part of what I addressed. While it surely thing something relatively easy since you already have coding knowledge, it isn't as obvious as it feel, because it need to be able to handle parallel writing.
Python:
label whatever:
    [...]
    if girlLove > 10:
        GIRL "Hey, want to go see a movie ?"
        MC "sure, why not."
    else:
        # Oops, yeah, and now, what I do ? 
        # What the girl give as excuse to leave ? 
        # What the MC will do of his free time ?
Without necessarily having all alternative in mind right from the starts, you need to fully understand that anytime you'll have a "if whatever > some value", you need to give a counter part to the players who have followed another way.

There's too many games where it's just: "you've the scene" versus "you jump to the following shared scene".
It's not bad by itself, but you need to put a transition between the two, and many just forgot it. You need to apprehend beforehand the implication, because it lead to a different way to split the scene.

You're at the coffee shop with the girl, and hop, a second later you're at home in your room... This simply because you missed the whole part where you go to the movie, see the movie, then return home.
This mean that the storyboard isn't:
  • coffee scene
  • [optional] movie scene
  • bedroom scene

But more something like:
  • coffee scene
  • transition ; to movie scene or to bedroom scene
  • [optional] movie scene
  • bedroom scene

More globally, each scene should have at least three parts: The opening transition, the scene, the closing transition.
Both transition part being where the story change the most, depending what came previously for that player, and what he will do next.


Thanks again for all the input, you're awesome.
Don't give me such credits, I'm mostly a guy who talk too much ;)
 

fooslock

Newbie
Feb 15, 2020
65
25
I don't care passing ten minutes to solve someone else bug, but I'm not ready to pass a full hour just to find where the bug happen. And I'm sure that I'm far to be the only one in that case.
I get ya, makes perfect sense.

learn the difference between theory and practice.
I'm kinda hoping for that yeah. This scratches my creative itch while hopefully helping me get code practice in. Really just kind of exploring programming now and what path I want to pursue.

"variable.rpy" file,
I think I'll do this and keep compartmentalizing things. seems cleaner for large projects.

pro tip: Inline comments are sometimes way more significant that a full bloc of comment.
It's wrong to believe that a good code is self commenting (yet there's people to still say it). A good code tell you what it's doing, but not why it's doing it. And most of the time, it's the second question that will pop in your mind, especially when coming back to code you wrote months ago.
makes sense. I've heard that yeah but I like to err on the side of caution.

put the "whatever_debug" label in a "debug.rpy" file, it's easy to remove the debug content from the distribution.
That's a pretty good idea. Just leave it out of the package at the end.

writers would perhaps say that it's a bad way to do, but it's a way that works and you already have the habit to deal with it.
why would they say that? I'm not sure I follow.

parallel writing
good way to put it, and yea I hadn't considered that. Haven't given it much thought until now but looking back I have seen that.
 

79flavors

Well-Known Member
Respected User
Jun 14, 2018
1,561
2,183
Aside from really basic stuff like "Learn how to write Renpy" or "Watch Daz Tutorials," what are some things I should consider before doing my project?

Make sure all file names are lowercase. Scripts, images, etc. RenPy doesn't require it, but it'll make your life easier.

For example, RenPy imports all the names of image files as displayables. One thing that often gets overlooked though is that the resulting displayables are always lowercase. It can trip up some new developers who don't understand why their scene AirportApproach with dissolve doesn't work. Worse when those same developers add start explicitly adding unnecessary image AirportApproach = 'AirportApproach.jpg' code everywhere. RenPy will do all the heavy lifting for you... if you let it.
Edit: If you want to break up the words within your filenames, use underscores, never spaces. (there is a special case where spaces are preferable, but you can't really go wrong with underscores).


Likewise, make sure all variable names, screen names, label names, etc are lowercase (or at least consistent). If you have a programming background, use whatever names make sense to you. If you haven't... use lowercase everywhere. Some people would use default kissed_tessa_on_day1 = False, others would use default kissedTessaOnDay1 = False. Personally I'd use all lowercase and underscores ( ), but I understand the reason why other people prefer a mix of Capitalized words ( ). Traditionally, variables that actually start with a capital letter ( ) are for class definitions. Honestly, for home developed code as a single developer, it really doesn't matter too much as long as you are consistent.


Create variables using either default or define.

If a variable will change while the game is running... use default.
If a variable will never change while the game is running... use define.

Being a programming language, there will be exceptions... but you won't go wrong if you at least start with that as your mantra.
You'll find games where they create variables within an init: block. It'll either be an older game or a developer who's just copying code from an older game.
Normally you'd position all those default and define statements together the top of the script (or the top of each script file). RenPy doesn't require it, but it'll make your life much easier when you're trying to find them if they'll all consistently at the top. (That includes using something like variables.rpy).


If you use pause or $ renpy.pause() always specify a time.

For example... pause 1.0 or $ renpy.pause(10.5).
Most developers seem to think of pause as being "stop and wait for the player" without giving thought to players who use [Auto] / AutoAdvance. The worst examples are usually animations, where the developer thinks the player will watch the full animation before continuing, without realizing that sometimes RenPy will advance automatically after only a fraction of a second. If your animation is 6 seconds, pause for 5.5 or something.


Never use hard pauses.

Again, in part because $ renpy.pause(hard=true) is not STOP. I've seen numerous games where a developer will do something like show screen house_navigation() folllowed by $ renpy.pause(hard=True) thinking that that hard pause will stop the player advancing until player picks an action shown on the screen. It doesn't work with autoadvance. The game will wait the default amount of time and the continue. Bad things then happen. btw. the correct solution is call screen house_navigation() instead of show screen ... - since call screen will wait until the player interacts with the screen.
Some devs will use hard pauses because they absolutely want the player to see something within the game or because they are worried the player will miss something. Usually some animation they put all their blood, sweat and tears into. Hard pauses just annoy players though. If the player wants to skip something you spent all weekend working on... let them.
 
Last edited:

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Respected User
Donor
Jun 10, 2017
10,265
15,074
why would they say that? I'm not sure I follow.
Because writing (like in books writing) is more of a linear process, and generally take place in less time. Globally speaking an average writer will finish his book in three/four months.
Therefore, still globally speaking, their works process tend to be at the opposite of the one I described ; it's the story that progressively tell them what are the key points. They starts to write, and slowly discover what the story is.
When you write a book, you just write what you mind tell you to write. Of course you already have an idea of the story, knowing how it will end, but the journey is something that you discover will writing it.

So, to keep my example, a writer would make the sister eat more, then he would make her appear late in the day. It's not a conscious decision he made, it's something that happened. He felt that she need to eat more. Then felt that she need to be sick, but in an imprecise way, she can just have a cold.
Then, there only one conclusion to this, unconsciously he decided that she need to be pregnant.

I know it can looks strange, but like a famous writer (I forgot his name) once said: "I write because I'm like my readers, I want to know what will happen next".

But of course, this works for book writing, because, as I said, it's a relatively fast process and the only thing you've to do is to write and think about what you write.
Something that don't apply to game making, even just a basic VN with some interactivity, because you're constantly distracted by the CG that you've to create, the code (as basic as it is) that you'll have to write.
You'll be working on a dialog, and while you'll make the girl say this, you'll have her image that come to your mind ; she need to looks like this at that moment. Boom, you're out of your writer state, you need to build that scene, or at least write its description for later.
The same goes for the code. You'll be writing something, thinking about what will happen next, and boom, "I know, I'll handle it that way". Again you're out of your writer state, thinking about code instead of the story.
It's because of those constant small distractions that you need to have what a writer don't really need, a kind of story board.
 
  • Like
Reactions: fooslock

fooslock

Newbie
Feb 15, 2020
65
25
Hey thanks for coming and putting in.

Make sure all file names are lowercase.
Likewise, make sure all variable names, screen names, label names, etc are lowercase (or at least consistent). If you have a programming background, use whatever names make sense to you.
Yea that's a good point. I originally started with Java and Camelcase but have moved to snakecase recently but still good to remember.

If a variable will change while the game is running... use default.
If a variable will never change while the game is running... use define.
That's interesting. Any more small things like this? I have yet to fully deepdive in the Renoy documentation but that's coming on real soon. Any other smaller areas in regards to Renpy where going over it with a fine tooth comb will save problems later?

If you use pause or $ renpy.pause() always specify a time.
Most developers seem to think of pause as being "stop and wait for the player" without giving thought to players who use [Auto] / AutoAdvance.
Good point, I didn't consider this.

Never use hard pauses.
If the player wants to skip something you spent all weekend working on... let them.
Yea I'm of the same mind. Like I get I might have put time into it but maybe someone's just not that into something, which is cool too.
 

Cenc

Well-Known Member
Game Developer
Jun 22, 2019
1,580
2,721
just to add, if you do use show screen (instead of Call) (there are some cases when you would), you can add:

Python:
$ _skipping = False
To prevent the player from skipping past that screen, just remember to enable it again once they have moved past the screen. (But honestly, use call and return for screens if you can).

You can also consider adding code for repetitive actions, for example if you have a point based system that awards points based on an action, that also displays a message to the user - instead of repeating everything each time you can use something like:

Python:
init python:

    def change_stat(stat, amount):
            if rel_notify:
                if amount > 0:
                    renpy.notify("Your relationship has increased!")
                else:
                    renpy.notify("Your relationship has decreased!")
            stat += amount
            return stat
And in your script you would just use:

Python:
$ POINT_VARIABLE = change_stat(POINT_VARIABLE, 1)
POINT_VARIABLE is your specific variable for the points, the 1 can be any number, even a negative to reduce points.
 
  • Like
Reactions: fooslock