A few newbie question on renpy...

Vanderer

Active Member
Game Developer
Dec 8, 2017
738
2,467
Hello guys, i decided to create my own game.

I already some of the writing and art done and now i need to implement it on Renpy.

It's going well so far and the start of the game, wich is a simple VN with choice and a one variable is nearly done.

But now i am doing the main part of it, and i was perhaps a little bit overamitious for a guy who knew only a little bit of htlm/php. But fuck it, you learn better by doing and i have no interest in doing a simple VN with branching story.

I have a few question tough, and i hope you will excuse me if i use some terms incorrectly. But i don't want to spend hours searching for things that cannot be done in Renpy so i you would help be i would be very thankful. The documentation online on renpy is very dry for beginner....

Beside, i cannot write and animate my scenes until i know for sure it will be doable, that would be an enormous loss of time.

1/ Can you use conditional statements with imagebuttons? I want to have greyed out locations until a flag is set to True. I intend to do that by replacing the image of my buttons who make up my "map" when a flag is set on True. Basically until the flag is set on true, or a variable reach a certain numerical value, the image is a greyed out version of the location. I would also put the properity "insensitive " of course.

It is doable? It is a good way of doing that? If yes, would one of you could point me to some code that use conditional statements in that context. So i see how it look like. The synthax a*still cause me problems...

2/I want to have the imagebutton of the location the mc is currrently in to be innactive and displaying another image (a version of the base image with an icon on it). But i am not sure how to do it.

The best way i could come with is : i would set a flag to True when inside the location, and to False when i leave it. Depending on the flag the location would display the appropriate image. So, when you click on the menu choice to leave the location, the flag is set to False. And set it to True when you click on the imagebutton of the location (or dismiss the map).

Is there a better way?


3/ I intend to have several love interests. Each one will have a variable associated to her representing her "level". I intend to use that so you cannot jump too far ahead in the story and have scenes who don't make sense.

Example: Lea has her first sex scene at level 6. Elisabeth at level 7 . If Lea is at level 6 but Elisabeth only at level 2, the threesome scene will not be avaiable. Same for the main story, both characters would have to be at a certain level for the next event in the main story to become avaiable.

It's something that i can code at my level, i think.

Is it a good way to structure my game? Can i do it in a better way?



And on that, i am going to work after a night trying to wrangle renpy and python. My boss id not going to be happy. Oh well....:D

Thank you very much in advance and i apologize for the bad english. Not an native speaker.
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,963
16,203
1/ Can you use conditional statements with imagebuttons? I want to have greyed out locations until a flag is set to True.
Yes you can :
Code:
screen whatever:
    [...]
    imagebutton:
        auto "thisButton_%s.png"
        insensitive "thisButton_greyed.png"
        sensitive myFlag == True
        [...]

2/I want to have the imagebutton of the location the mc is currrently in to be innactive and displaying another image (a version of the base image with an icon on it). But i am not sure how to do it.
The default answer is "in the exact same way than above". But then you'll have a conflict since you'll end with two different images for the insensitive state.
So either you have a simple if/else to decide if the button is greyed or not, and use sensitive to change the button when the MC is present.
Code:
screen whatever:
    [...]
    if thisLocationEnabled == True:
        imagebutton:
            auto "bedroom_%s.png"
            insensitive "bedroomWithMC.png"
            sensitive locationMC == "bedroom"
            [...]
    else:
        imagebutton:
            idle "bedroom_greyed.png"
            action NullAction()
Note that It will also insensitive the button when the MC is present, but since he's already here, I assume that the player don't need a sensitive button.
But if your intent is to have the button sensitive, then inverse the condition for if and sensitive, and replace the action by something else than NullAction().


It's something that i can code at my level, i think.
You think right. Among other possibilities, you've those :

Python:
# ALWAYS use this way to declare variable, it preserve the save compatibility
default leaLove = 0
[...]
label whatever:
    [...]
    menu:
        "be rude":
            $ leaLove -= 1
            [...]
        "be charming":
            $ leaLove += 1
            [...]
[...]
label anotherLabel:
    if leaLove >= 5:
        lea "Hey, do you want a BJ ?"
    else:
       lea "It's a sunny day today."
[...]
label yetAnotherLabel:
    menu:
        "Compliment Lea":
              [...]
        # Will be shown to the player only if leaLove is >= 10
        "Ask for sex" if leaLove >= 10:
             [...]
[...]
label ohLookALabel:
     [...]
     if leaLove <= 8:
          jump somewhereElse
          # Alternatively you can use /return/ if you /call/ the labels
    lea "I really like you. Do you want to come home for a coffee ?"
    mc "With pleasure."
    [...]

Is it a good way to structure my game? Can i do it in a better way?
It's the usual one, and it works.
 

Vanderer

Active Member
Game Developer
Dec 8, 2017
738
2,467
Anne O'nymous thank you very much. That helped me a lot.

Easier to understand things when you see code rather than a manual.

Thank you very much Ma'am/sir.
 
  • Like
Reactions: anne O'nymous

Vanderer

Active Member
Game Developer
Dec 8, 2017
738
2,467
Just one more question about one comment you made: "# ALWAYS use this way to declare variable, it preserve the save compatibility"

I cannot use use define or $myVariable then? Why? Not that i don't trust what you said, you evidently know your shit, just curious and wanting to learn.

Also, when is the best time to define variables? Before the "label start:" (init phase i think it's called) or anytume/anywere is fine? What's best practice?
 
Last edited:

Porcus Dev

Engaged Member
Game Developer
Oct 12, 2017
2,582
4,705
Just one more question about one comment you made: "# ALWAYS use this way to declare variable, it preserve the save compatibility"

I cannot use use define or $myVariable then? Why? Not that i don't trust what you said, you evidently know your shit, just curious and wanting to learn.

Also, when is the best time to define variables? Before the "label start:" (init phase i think it's called) or anytume/anywere is fine? What's best practice?
"define" is usually used for constants, not for variables; for example, names are usually assigned with "define" since they arent usually going to be changed.


During the evolution of the game you will use "$ myvariable += 1" for example, but first it have to be in the game using "default"; if you don't, renpy you will get error.

Example, v0.1:
Code:
default olivia_love = 0

label start:
    o "Am I pretty?"
    menu:
        "Yes":
            "Oh, you're so kind"
            $ olivia_love += 1
        "No":
            "Fuck you!"
            $ olivia_love -= 5
    ...........

If you want to add a new variable in the next version, add it by "default" before using it

Example, v0.2:
Code:
default olivia_love = 0
default katia_love = 0   ### It's good to have a section where you can add all the new variables with "default"

label start:
    o "Am I pretty?"
    menu:
        "Yes":
            "Oh, you're so kind"
            $ olivia_love += 1
        "No":
            "Fuck you!"
            $ olivia_love -= 5
    ...........

    k "And me?"
    menu:
        "Yes":
            "Thanks, you wanna go fuck?"
            $ katia_love += 1
        "No":
            "What?"
            $ katia_love -= 5
    ...........

BTW, after the options in a menu (in this case after the lines that give or take points) you can use "pass" to continue with the next line out of the menu, or "jump" if you want to jump to a specific label.

NOTE: I'm sure anne O'nymous will explain it better when he comes by :ROFLMAO::ROFLMAO::ROFLMAO:
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,963
16,203
I cannot use use define or $myVariable then? Why?
You can, but each way have its own particularity.

  • define

    It will create the variable and assign the value, right before the game start, and right before the load of a saved game. But the variable will be saved only if its value change. Which is fine when the value is a number or a string, but not if it's an object.
    Python:
    # myVar will not be saved
    define myVar = 12
    # myObject will not be saved
    define myObject = object()
    [...]
    
    label whatever:
        [...]
        # The value change, /myVar/ will be saved now.
        $ myVar += 1
        [...]
        #  Only the value of /anAttribute/ have changed. /myObject/ still have the same 
        # value. Therefore, /myObject/ will still not be saved.
        $ myObject.anAttribute = 12
    Technically it mean that you can use define for string or number. But it's always better to not take this habit. If one day you start using object, you'll pass time wondering why it's not saved, before remembering that it's because of define.
  • $ myVariable

    It create the variable, assign the value and declare the variable as to save. But it can be used only in a label. Therefore if the player load a saved file he will not necessarily have the change.
    Imagine that you have :
    Python:
    label start:
        # Present since the first release of the game
        $ leaLove = 0
        $ myVariable = 0
        # In the 5th update of the game, you add a girl named Maria
        # And you give her a variable
        $ mariaLove = 0
        [...]
    Anyone starting a new game will have all the variables. But like they are created in the start label, anyone that will use a saved game will not pass through this label... and so mariaLove will never be created for them.
  • default

    Like define it create the variable and assign it the value right before the game start, and right before the load of a saved game. But it will also make the variable savable from the start ; this whatever if its value have changed or not.

In conclusion, default have the advantages of both define and $ myVariable, but without their disadvantages.


Also, when is the best time to define variables? Before the "label start:" (init phase i think it's called) or anytume/anywere is fine? What's best practice?
default is an "init statement". It mean that it will be proceeded at init time whatever where it is located in the code. But it's generally preferable to place them in top of the file, simply because it's easier to find them.


NOTE: I'm sure anne O'nymous will explain it better when he comes by :ROFLMAO::ROFLMAO::ROFLMAO:
You did it fine.
 

Vanderer

Active Member
Game Developer
Dec 8, 2017
738
2,467
Thanks to the both of you it is very clear: Always use "default" to set the initial value of a variable, at least in ren'py. If not, the variable will only be set if the code is executed, so if you load a save after "define" or "$ myVariable " that variable will not be set and cause bugs. Easy.


But then i may ask, what the point of "define" and "$ myVariable ". Why they exist at all?

Variables thtt are only use once in the same block perhaps? But i still don't see the point of them, why not have a spearate file with all your variables, it's more easy that way, no?
 

Porcus Dev

Engaged Member
Game Developer
Oct 12, 2017
2,582
4,705
Yes, you can use a file just to have all your variables there with "default".

The usual operation is that with "default" you assign the initial value, then with "$" you alter that value according to your convenience.

Assign the initial value:
default myvariable = 0

Subtract or add points to that value:
$ myvariable += 2
$ myvariable -= 5

Change directly to the desired value:
$ myvariable = 10
 

Vanderer

Active Member
Game Developer
Dec 8, 2017
738
2,467
Oh yes, how stupid of me. Of course they are used to change the variable. Brain fart.

Anyway, thank you guys, you were very helpful.
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,963
16,203
Oh yes, how stupid of me. Of course they are used to change the variable. Brain fart.
It's not stupid at all.
You had in mind the creation of the variable, it's the whole subject of the discussion since few messages. And because of this you just forgot that $ myVar = x can also be simply a change in the value. It happen to all of us, more often that we are ready to admit.

As for the difference between define and default, like mgomez0077 said, define is designed for the constants. Therefore, it's more a convenience, to not make the save files overgrow without reason ; everything that is constant don't need to be saved, and less to save mean smaller files.
It's also because not everything can be effectively saved. But you don't have to bother with this, it's really advanced coding and unless you intend to create a really complicated frameworks, you'll never encounter this kind of situation.
 
  • Like
Reactions: Vanderer

Vanderer

Active Member
Game Developer
Dec 8, 2017
738
2,467
Thank you anne O'nymous, you are very kind.

And it make sense to keep the save files smaller. Especially if on the mobile version where save space can be a problem.
 

Rich

Old Fart
Modder
Donor
Respected User
Game Developer
Jun 25, 2017
2,566
7,381
And it make sense to keep the save files smaller. Especially if on the mobile version where save space can be a problem.
True. And what's not obvious is that your variables get stored lots of times in a save file. Ren'py stores rollback information in your save file, both so that a player can (possibly) roll back after a restore, but also as its way of re-syncing itself if there's a change in an .rpy file right near where someone makes a save. If memory serves, by default, it stores something like 100 previous states, and for each of those states it stores the values of all of your variables.

For the technical among us, the variables you create with default and $ var = 1 are made members of a Ren'py object named store, and each time Ren'py does an "interaction," (waits for player input) it "pickles" (Python for "convert to something that can be saved in a file") the store and saves it along with what's on the screen and where it is in the .rpy script. That all gets pushed onto a stack for rollback purposes, and the rollback stack becomes part of the save. So every variable that you add to your game has something like 100 copies of it stored in each save file.

That being said, this isn't something that you normally have to be overly paranoid about - most variables just aren't that huge (even when you add all the stuff that surrounds them in the pickle format) so even 100 copies of them aren't exactly huge. So you don't usually have to sweat the "should I add a variable or not" question. (It's usually MUCH more of a pain when you forget to add a variable to remember a branch that you took three versions ago and now want to make something dependent on it.)

But if you were somehow going to use VERY large data structures, you might want to avoid having them end up in the store. Maybe have them be constants (define) and refer to them using simpler variables. But that's a more advanced topic for another day.
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Donor
Respected User
Jun 10, 2017
10,963
16,203
For the technical among us, [...]
To go deeper on the technical part, all the variables are put in store, even the ones created by define and the ones purely internal to Ren'py.
You can also find in store the modules used by Ren'py, behind store.renpy., so there's no need to import them again like some do. It don't use really more space in the RAM, but it keep the store more clean ; it's enough of a mess like that with the possibility to write things like store.renpy.display.screen.renpy.store.myVar to access store.myVar ;)

As for the stack used for rollback purpose, it rely on a set named ever_been_changed, that is part of the "store" object, but not directly available. You'll find it as attribute of renpy.python.store_dicts["NAME OF THE STORE"].
It's initially filled by all the default statements, then updated each time Ren'py perform an assignation after the start of the game ; therefore, each time a variable have "ever been changed".
The set being itself part of the rollback, it will be saved 30|100 times (I more or less remember that PyTom reduced the default value) among your own variables.
Which also talk in favor of using define for everything that is constant. Not only you'll not save the value 30|100 times, but you'll also not save its name 30|100 times. And when it's something like define roundedPiValue = 3.14, the name of the variable take more place than its value.

It's the same set that is used by the Ren'py's variable viewer (and mine). So at anytime during your creating process you can ensure that a variable will be effectively saved. Either by using the said "variable viewer", to see it the name is among the list, or by looking directly if the name is in the ever_been_changed set. From the console:
"NAME OF THE VARIABLE" in renpy.python.store_dicts["store"].ever_been_changed
and it should show you True if the variable will be saved.

On a side note, there's more than one store, and you can create your own ones. I don't remember where it's said in the doc, but you can find an example of use in "renpy/common/00console.rpy". And like each store have a ever_been_changed set, the variables in your own store will still be saved if needed.
But I warn all modders around there, it's not something to use in a mod. It corrupt the save files, because at load time Ren'py will expect to find the store. I learned it the hard way.


That being said, this isn't something that you normally have to be overly paranoid about [...]
I second that. When working on my Extended Variable Viewer, I saw games with ton shit of variables, some with lists over 5 KB, but I never saw a save file reaching 1 MB.
 
  • Like
Reactions: Rich

lancelotdulak

Active Member
Nov 7, 2018
556
557
All you people providing Vanderer help are awesome .

Vanderer i hope you get your game finished and are proud. If its your first 'real' programming project you'll remember this the rest of your life (i still remember fondly a pageflipping DnD character generator on an atari 400 and the 3d program i wrote on an 8088 clone from scratch in c).

It sounds like youre about to move beyond python.. not that python wont do pretty much anything for a vn.. but for your next project can i suggest you move to unity or UE4? Yes the Can be complex etc but they do simple things (like your button etc ) Incredibly easily and they allow you infinite room to grow. Again.. nothing wrong w renpy. Unity is stunningly simple to use and very powerful. With UE4 you can build anything from a simple vn to a AAA game.

You said "at my level". I stopped counting languages at 10. YOu know the difference between us? Time. That's pretty much it. If you can learn python, or vb, or perl, or c.. you can learn c++.. or anything else. All languages are the same at their core .
Ive actually considered writing something on here explaining classes, structures and arrays simply on here because i think it would SERIOUSLY help a lot of creators here (theyre incredibly useful and powerful) but.. well honestly there are more than a few .. not so competant people who come here to be cancer and its not worthit.
 
  • Like
Reactions: Vanderer

Vanderer

Active Member
Game Developer
Dec 8, 2017
738
2,467
You are very nice Lancelot, and i appreciate your support very muchn but i don't know about "move beyond python".

I have already a hard enough time trying to learn how to use lists and tuples....