RenPy beginner questions

HopesGaming

The Godfather
Game Developer
Dec 21, 2017
1,701
15,270
Then I think you are underestimating the code a bit.
And not something that can be easily explained here.

Check these guides instead;

And


The last one was what I used to create my navigation system.
 

Lyka

Member
Game Developer
Aug 31, 2018
252
376
i'm through with the first link. i read it weeks ago.
i have a map running (newest is a bus travel between 2 maps), serval locations , sleeping, shop, day night sycle, even random stuff works allready

the 2nd link is nice, maybe i can use it on another project in the far far future.

my problem is the timed story quests. the conditions are "storArc == x Day == x variablex == x -> start quest"


and i need some little codes for this:

if variablex == 5 AND NOW 10,15,20,25 and so on
or steps like 5,10,17,26...

right now im using this code to solve it:
elif variablex == 5 or variablex == 10 or variablex == 15 or variablex == 20:
but if i go on like this this line will be gigantic long
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Respected User
Donor
Jun 10, 2017
9,944
14,546
1st: storyArc is a variable and should need a $ or am i wrong here?
You're neither right nor wrong, it's your premise that's wrong. The leading "$" doesn't mean, "what's following is a variable", but, "what's following is a line in Python language".
You don't have permission to view the spoiler content. Log in or register now.


2nd: would it be a problem if the "$ storyArc +=1" is before the "jump event" ?
Not only it's not a problem, but it's mandatory. The code I gave as example was based on . It mean that, at some point, the game would have returned to this part of the code, and then incremented storyArc. But if you use instead, then you need to increment the value before the jump. This because the game will never come back where you jumped, and so will never play the line following the jump statement.
You don't have permission to view the spoiler content. Log in or register now.


3rd.: i use 2 variables and since i couldn't test it, does it work with 2 "and" (if ... and...and...: )?
An if statement is followed by a condition, and this condition can be (almost) whatever you want.
You don't have permission to view the spoiler content. Log in or register now.


how the fu.... can i jump into "label something:" ?
im going nuts right now.
Sorry, I really not sure that I understand the question.


(going to write it here so please ignore tabs)
Try to take the habit to only use spaces when writing code for Ren'py and Python. I know, it's a pain in the ass... But it will prevent an accident when one day you'll end with real tabulation characters in your code ; what both Ren'py and Python really hate.


BUT HOW DO I GET HERE:
By doing this ?
Code:
label something:
    if storyArc == 0 and day >= 5 and variablex >=4:
        jump park

with my current knowlegede i could get it to work if i wrote mostly everywhere "if storyArc == 0 and day >= 5 and variablex >=6:" but that cant be the solution.
Effectively, it can't be the solution. Like you're making a free roaming game it will all rely on the main design of your code, and there's many way to design the code for this.
The solution that look the most obvious here is to split the code and use a Ren'py label as a function with the help of the (not so greatly documented) statement :
Code:
#  This label MUST be called, and can be called from many different
# places in your code.
#  Like I explained before, it will pass all the conditions for all the
# events, and stop at the first condition that pass.
#  When a condition pass, it will return the name of the label
# corresponding to the event. Note that it MUST be a string.
#  If all condition fail, it will return the None value ("there's nothing for you").
label eventTesting:
    if storyArc == 0 and day >= 5 and variablex >=6:
        return "parkFirstEvent"
   elif storyArc == 1 and day >= 7:
        return "parkSecondEvent"
   # All other condition have failed, so there's no event actually
   else:
        return None

label something:
    [...]
    # Time to see if an event is triggered.
    call eventTesting
    # If the label return something else that None.
    if not _return is None:
        #  Play the event by jumping to the label named according to
        # the value of '_return'.
        jump expression _return
    # Here, do what you'll have done if there were no event...
    # because there were no event :D
    [...]

label anotherLabel:
    [...]
    # Time to see if an event is triggered.
    call eventTesting
    # If the label return something else that None.
    if not _return is None:
        #  Play the event by jumping to the label named according to
        # the value of '_return'.
        jump expression _return
    # Here, do what you'll have done if there were no event...
    # because there were no event :D
    [...]
It's just one of the way to do it, but it's a way that works ;)
Note that you need to return the value. You can not jump from the 'eventTesting' label. This label is called, if you don't return from it, it will mess with the game flow and can lead to many problems.
There's way to deal with these problems, but you're too young with Ren'py for this. First understand the difference between jumped labels and called ones, then learn to use them correctly.
Knowing how to mess with them, to call, jump, then return, or to force Ren'py to forget there were a call, can wait that you master the control of the game flow first.
In the same way, you need to call the said 'eventTesting' label. It's the only way you have to return where you were in the game, if there's no events.


sorry but right now i'm getting frustrated, i could get stuff to work i never thought about and i allways get stuck with this particular problem
No need to be sorry. If you knew the amount of times I have passed trying to do this, or that, with Ren'py... sometimes to finally discover, after many headache, that there were an easy way to do it. And I'm sure that it's also the case for anyone here.


let me guess there is something like a "check label something" command
Well, yes there's but it don't do what you expect. It's the () function. But it only check if the given label exist or not.
And this lead to an improvement to the code I gave :
Code:
label anotherLabel:
    [...]
    call eventTesting
    if not _return is None:
        if renpy.has_label( _return ):
            jump expression _return
        else:
            $ renpy.notify( "Something goes wrong, label "{}" is missing. Sorry for the inconvenient.".format( _return ) )
If you forgot to create the label for the event, or misnamed it, it will not break the game. A warning will be displayed to the player, letting you know that there's a problem, but the game will continue like if there wasn't an event to play at this moment.
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Respected User
Donor
Jun 10, 2017
9,944
14,546
[sorry for the double post]
right now im using this code to solve it:
elif variablex == 5 or variablex == 10 or variablex == 15 or variablex == 20:
but if i go on like this this line will be gigantic long
Then don't do it like this.
It will need that you call the label (see my comment right above), but you can delay the condition later. To not lost you, I will reuse the code I explained above, and the example you gave for the park label:

Code:
label eventTesting:
   if storyArc == 0 and day >= 5:
       return "parkFirstEvent"
   elif storyArc == 1 and day >= 7:
       return "parkSecondEvent"
   else:
       return None

label something:
   [...]
   call eventTesting
   if not _return is None:
       # Note that now you CALL the label, instead of jumping to it
       call expression _return
   # You reach here either if there were no event, and if the event
   # is now finished.
   [...]

label parkFirstEvent:
   # The second part of the condition are not reached.
   # Return instead of playing the event.
   if variablex != 5 and variablex != 10 and variablex != 15 and variablex != 20:
       return
    scene park
    menu:
        "walk around":
            $ time += 1
        "jump in the water":
            [whatever]
    # Here is the problem with this method. You NEED to return, it's MANDATORY
    return
Like I said, this structure imply that you return from every single called label. So it will complicate a little the way you'll write your events. But in the same time, it will really ease the main structure of the code.
 
  • Like
Reactions: Lyka

Lyka

Member
Game Developer
Aug 31, 2018
252
376
[Knowing how to mess with them, to call, jump, then return, or to force Ren'py to forget there were a call, can wait that you master the control of the game flow first.]

"return and call" i have to start with this now.... or next week :)


Just a test if i'm on the right page now.
"label testing" is where every event start time condition goes in and send me from there to the next label
"call eventTesting" let the code check if there is a a event inside for usage and if there isn't
then this line "if not _return is None:" send it back and let the player be able to sleep ect.

Now i could hammer the conditions in "label eventTesting" while i only add this 2 lines "call eventTesting" and
"if not _return is None:" to all my locations. after that it won't matter where i go since it will be testet everywhere

Code:
default storyArc = 0

label eventTesting:
   if storyArc == 0 and day >= 5 and variable >5:
      return "parkFirstEvent"
   elif storyArc == 1 and day >= 7 and variable >10:
      return "parkSecondEvent"
   else:
      return None
 
###random location
label inn:
   call eventTesting
   if not _return is None:
    scene bar
    play music "<loop 6.333>sfx/inn.mp3"
    menu mainMenu0:
         "sleep":
            [....]


about this what i think is pretty cool:
to run this is another call required or? "call anotherlabel and if not _return is None:"

Code:
label anotherLabel:
   [...]
   call eventTesting
   if not _return is None:
       if renpy.has_label( _return ):
           jump expression _return
       else:
           $ renpy.notify( "Something goes wrong, label "{}" is missing. Sorry for the inconvenient.".format( _return ) )



that means the" return" at this point would hinder me to get into the park if the variablex condtion isn't fulfilled?


Code:
label parkFirstEvent:
   # The second part of the condition are not reached.
   # Return instead of playing the event.
   if variablex != 5 and variablex != 10 and variablex != 15 and variablex != 20:
      return
   scene park
   menu:
       "walk around":
           $ time += 1
       "jump in the water":
           [whatever]
   # Here is the problem with this method. You NEED to return, it's MANDATORY
   return
 

Maid Lain

Well-Known Member
Modder
Game Developer
Apr 4, 2018
1,888
16,215
@anne O'nymous
Code:
label something:
   call eventTesting
   if not _return is None:
       # Note that now you CALL the label, instead of jumping to it
       call expression _return
What is this '_return' black magic? I'm assuming it has to be value of the last thing that was returned. But not directly evaluating the return value of the label feels dirty.

Edit: Okay here's how I would do it.
Code:
default day = 6

label start:
    jump park

label park:
    call event_testing
    "bye"
    return

label event_testing:
    if day >= 5:
        call expression "parkFirstEvent"
        return
    elif day >= 7:
        call expression "parkSecondEvent"
        return
    else:
        return

label parkFirstEvent:
    "hi"
    return
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Respected User
Donor
Jun 10, 2017
9,944
14,546
What is this '_return' black magic? [...]
Wouldn't something like this work?:
I'll answer both at once because the questions are deeply linked.

Normally a coding programming language works with the help of a stack. Basically it looks like this :
  • You call a function ;
  • The actual position is stored in the stack ;
  • The parameters sent are stored in the stack ;
  • The code pointer is changed from "actual position" to "start of the function" ;
  • The parameters are retrieved from the stack ;
  • The function is played ;
  • The previous "actual position" is retrieved from the stack ;
  • The returned values are stored in the stack ;
  • The code pointer is changed from "position in the function" to "retrieved 'actual position'" ;
  • The returned values are retrieved from the stack.

But, still basically, Ren'py works like this :
  1. Ren'py look at dontRememberWhat.next to know what's the next statement ;
  2. Ren'py play this statement ;
  3. Ren'py loop in 1, unless the statement is a return, call (and few many).
If the statement is a call then :
  • Ren'py store the actual statement in the stack ;
  • Ren'py store the parameters in store._args and store.__kwargs ;
  • Ren'py put the position of the called label in dontRememberWhat.next ;
  • Ren'py raise a "CallException" exception ;
  • Ren'py intercept the said exception ;
  • Ren'py loop in the 1 of above.
If the statement in a return then :
  • Ren'py store the returned value in store._return ;
  • Ren'py retrieve the position stored in the stack and assign it to dontRememberWhat.next ;
  • Ren'py loop in the 1 of above.

Technically a call statement neither pass parameters nor return a value. I don't know why Tom chose this design, since it already have a stack, but it's probably the easiest anyway. I mean, you need a statement to explicitly call a label, so your code should be :
Code:
label park:
    if call event_testing not None:
        call expression call event_testing
Note that you forgot the second call in the second line.

Which can be read :
statement condition_is_a_statement
statement expression_is_a_statement
instead of the actual :
statement condition
statement expression
The nested statement imply a way more complicated mechanism behind the scene.

In the same time, Ren'py works with objects. A statement is just an object with an "execute" method. Like calls are done with the help of an exception, the game quit the current flow and will never return to the "execute" method. So, using the stack to store the returned value mean that a call statement should have been split in two parts : Firstly the object that represent the call itself, then the object that will retrieve the returned value from the stack, and assign it to [whatever said the code].
Add this to the nested statement needed and in the end you've :
IF_statement
CALL_call_statement
CALL_assign_statement
condition_test:
CALL_call_statement
CALL_call_statement
CALL_assign_statement
expression_built
CALL_assign_statement
Which give me headache just by writing it ;) And yet I haventt tried to think about all the other case where a call can be nested :D


Don't really know it my explanation were clear, but I tried ; sorry if I failed.
 
  • Like
Reactions: Maid Lain and Lyka

Lyka

Member
Game Developer
Aug 31, 2018
252
376
your explanations are a thousend times better then most tutorials out there!!
---

and whats my problem now?

simple_expression not found
call expression -> call event_testing

Code:
label eventTesting:
   if storyArc == 0 and day >= 5 and activity >5:
      return "eve1"
   elif storyArc == 1 and day >= 7 and activity >10:
      return "eve2"
   else:
       return
############### INN ###################
label inn:
 if call event_testing not None:
    call expression call event_testing
    scene emptybartable
    play music "<loop 6.333>sfx/inn.mp3"
    menu mainMenu0:
        "Work 1 shift":

ehm i'm having a bit of a problem:
i have menu with some options and one of it is "gamling" how can i make it that this one works only once a day?
 
  • Like
Reactions: anne O'nymous

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Respected User
Donor
Jun 10, 2017
9,944
14,546
Code:
############### INN ###################
label inn:
 if call event_testing not None:
    call expression call event_testing
    scene emptybartable
    play music "<loop 6.333>sfx/inn.mp3"
    menu mainMenu0:
        "Work 1 shift":
Yeah, but no. The code given by @Maim Lain was theoretical, it will never works. Sorry, it's our fault, we got a little too much carried by the subject. Ren'py just don't know how to deal with this.

What you need is this :

Code:
label inn:
    call event_testing
    if _return not None:
    call expression _return
    scene emptybartable
    play music "<loop 6.333>sfx/inn.mp3"
    menu mainMenu0:
        "Work 1 shift":
One think you should probably do is to stop working in your project for few days. But it will not be wasted time.
Start a new project, and play with call, jump and return. No need for complex code, try things like :
Code:
label start:
   call calledLabel( 1, 3 )
   "it returned [_return]"

label calledLabel( a, b ):
    $ retVal = a + b
    return retVal
or
Code:
label start:
   call calledLabel
   "I came back here"

label calledLabel:
   "I'm in the called label"
   call expression "once" + "Again"
   "Oh, I'm back in the first called label"
   return

label onceAgain:
    "Still in a called label"
    return
Just let you imagination play, don't hesitate to go wild, and try many things. I doesn't care if some failed. You'll learn to control the flow of your game, you'll understand it better, and it will be all benefit for the code of your game.
 
  • Like
Reactions: Lyka

Lyka

Member
Game Developer
Aug 31, 2018
252
376
yea it's a good idea to test and learn this it in a new project. right now im running from one error in another i tried it now with those 3 lines and get something about an SyntaxError: unexpected eof while parsing (if _return not None:)

as always thousand thanks!
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Respected User
Donor
Jun 10, 2017
9,944
14,546
(if _return not None:)
Oops. My bad. Focused too much on the 'call' problem and forgot to check the rest. It should be "if not _return is None".
The "not" mean, "reverse the result", and the "is" is the relation between the two entities, which mean "is strictly equal to". So, here it's the opposite of _return is strictly equal to the none value ; said otherwise, _return is not strictly equal to None.
The "is" relation is to use with None, True, False.
 

Maid Lain

Well-Known Member
Modder
Game Developer
Apr 4, 2018
1,888
16,215
@Lyka Yeah I would probably take some time to learn a bit more about RenPy like anon said.

I wrote a couple tutorials recently and one of them is about coding a typical 'dating sim' type of adult game that you might want to check out:



It might be a bit advanced though idk. (and feel free to criticize my tut @anne O'nymous since you're the renpy genius)
But it does events this way:
Code:
    if heather.location == "room" and day >=5:
        jump expression heather.current_event

You code your game using the 'evaluating _return' way that was mentioned. You could Or you could Or you could do it the way above. There's lots of ways to code things, and some ways might make more sense to you than others.
 
  • Like
Reactions: anne O'nymous

Lyka

Member
Game Developer
Aug 31, 2018
252
376
i come this far in less then 15 days (ok i read about python before but not practical)
maybe a good point for a break and learn some stuff now.
this is the breaking point for the game. the story must work flawless.
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Respected User
Donor
Jun 10, 2017
9,944
14,546
and feel free to criticize my tut @anne O'nymous since you're the renpy genius)
Don't know if I'm really a genius, just someone that had (sometimes) too much free time and pass it with Ren'py. As for your tuts, I have really few things to say about them.
Regarding the "sim date" :
Code:
default a_events = ["null", "a_event_1", "a_event_2", "a_event_3"]
I would have used None instead of "null", but it's a question of personal taste. The problem I see here is not that, but the fact that you didn't explained why the "null". Few lines to explain/remember that array index start at 0, while the level start at 1, should be enough.
Else, I fear that someone not familiar with coding can be lost and think that "null" is an effective label and that it should be different for all girls.

Also, you should perhaps use more different names for the events, like "a_park_event", "a_pool_event", etc. It will mark more the difference between the labels. Because with this "a_event_[level]" form, you don't need an array, this is enough :
Code:
    def __init__(self, name, base_event):
        [...]
        self.base_event = base_event
    def level_up(self):
        [...]
        self.current_event = self.base_event.format( self.level )
    [...]

default alice = Girl("Alice", "a_events_{}" )
You can even start with pure string names and the code that use the array, then as an example of "how to tweak", use the code with the "a_event_{}" form.
You can even go further :
Code:
        self.current_event = "{}_event_{}".format( self.name[0].lower(), self.level )

As for the farm code, except the "== True/False" that I would have wrote "is True/False" (again a question of personal taste), I saw only two things.
Firstly, the use of "global". By default, and if it's part of a .rpy file, Python code is played with store as global namespace, so everything in store is already global to the code. Which make your global useless. You don't even need to prefix the variable. The only exception is when you directly assign a value ; in this case Python is a little lost and will see the variable as local. So, it lead to :
Code:
def end_day_cows():
   for num in range(0, len(cow_list)):
       if cow_list[num].is_pregnant:
           cow_list[num].days_pregnant += 1

           if cow_list[num].days_pregnant >= 3:
               store.baby_cows += 1
               cow_list[num].is_pregnant = False
               cow_list[num].days_pregnant = 0
   return
The only direct assignation is when you increase baby_cows. So it's the only thing that need to be prefixed.

The second thing is the fact that you increase the number of day for the pregnancy. Personally I would have decreased it. This open the possibility to have pregnancy that are more or less longer. In the case of four element trainer it doesn't mater since all the "cows" are of the same specie. But if you mix species, you don't have to make exception or to write a pregnancy check for each species.
Something like :
Code:
class Cow():
   def __init__(self, has_been, is_preg, preg_duration, specie ):
       [...]
       self.preg_duration = preg_duration
       self.specie = specie

   def breed(self):
       [...]
       self.days_pregnant = self.preg_duration

def end_day_cows():
   for num in range(0, len(cow_list)):
       if cow_list[num].is_pregnant:
           cow_list[num].days_pregnant -= 1

           if cow_list[num].days_pregnant == 0:
               baby_cows[cow_list[num].specie] += 1
               cow_list[num].is_pregnant = False
Note that this time, baby_cows is not a direct assignation. You assign a value to an entry of the dictionary. So you don't need to prefix it.

With inheritance you can even end with :
Code:
class Animals():
   def __init__(self, has_been, is_preg ):
   [...]

   def breed(self):
       [...]
       self.days_pregnant = self.preg_duration

class Human( Animals ):
   def __init__(self, has_been, is_preg ):
       super( Human, self ).__init__( has_been, is_preg )
       self.preg_duration = 3
       self.specie = "human"

class Alien( Animals ):
   # You can even do it in a way that don't care of the effective parameters
   def __init__(self, *args ):
       super( Alien, self ).__init__( *args )
       self.preg_duration = 5
       self.specie = "alien"

def add_animal(type, specie):
   if type == 'fresh':
       cow_list.append(specie(False, False))
   if type == 'used':
       cow_list.append(specie(True, False))
   if type == 'pregnant':
       cow_list.append(specie(True, True))
   return

label buyAFreshHuman:
    $ add_animal( "fresh", Human )


There's lots of ways to code things, and some ways might make more sense to you than others.
i come this far in less then 15 days (ok i read about python before but not practical)
maybe a good point for a break and learn some stuff now.
You see, what Maim Lain said is probably the most useful things you'll learn. Ren'py present the advantage to let you do things in many ways. Some are really advanced, other really bad, but as long as it works, you need to use the one you feel the most at ease with. This just because, the more you understand it and the more it feel natural for you, then the more you'll see when you make an error ; so, the less you'll make errors :D
That's why you need to take a break, time to time, and just mess with the code. It's the best way to tame it, and feel at ease with it.
 
  • Like
Reactions: Maid Lain

Maid Lain

Well-Known Member
Modder
Game Developer
Apr 4, 2018
1,888
16,215
Thanks for reviewing my stuff. I made changes to the tutorial improving some of the things you mentioned.

Regarding the "sim date" :
Code:
default a_events = ["null", "a_event_1", "a_event_2", "a_event_3"]
I would have used None instead of "null", but it's a question of personal taste. The problem I see here is not that, but the fact that you didn't explained why the "null". Few lines to explain/remember that array index start at 0, while the level start at 1, should be enough.
Else, I fear that someone not familiar with coding can be lost and think that "null" is an effective label and that it should be different for all girls.
Yeah None is better than "null", and I should have added, 'The reason the first item in the event lists is empty is so that "self.current_event = self.event_list[self.level]" in the level_up() method works. This way event #X will play when your relationship level is X.'


Also, you should perhaps use more different names for the events, like "a_park_event", "a_pool_event", etc. It will mark more the difference between the labels.
You can even go further :
Code:
        self.current_event = "{}_event_{}".format( self.name[0].lower(), self.level )
The type of event progression I had in mind while making the tut is how Mythic Manor and Harem Hotel do events. If you haven't played those basically it goes -> girl is level 1 -> do relationship event 1 with girl -> girl becomes level 2 -> do relationship event 2 with girl -> girl becomes level 3, etc. That's why I had the array since events are completely linear and things like pool/park events are more side events in those games where the logic for triggering those non-relationship level events is at the pool/park/etc.
But the "self.current_event = f"{self.name[0].lower()}_event_{self.level}" you mentioned is really smart and what I'm going to change it to.


Firstly, the use of "global". By default, and if it's part of a .rpy file, Python code is played with store as global namespace, so everything in store is already global to the code. Which make your global useless. You don't even need to prefix the variable. The only exception is when you directly assign a value ; in this case Python is a little lost and will see the variable as local. So, it lead to :
Code:
def end_day_cows():
   for num in range(0, len(cow_list)):
       if cow_list[num].is_pregnant:
           cow_list[num].days_pregnant += 1

           if cow_list[num].days_pregnant >= 3:
               store.baby_cows += 1
               cow_list[num].is_pregnant = False
               cow_list[num].days_pregnant = 0
   return
The only direct assignation is when you increase baby_cows. So it's the only thing that need to be prefixed.
Ahhhh, thank you! I was completely lost as to why RenPy could read variables but then it would say the variable wasn't declared when trying to assign values to them. That is pretty weird that you only need to write "store." when directly assigning but adding to and changing objects in lists and dicts doesn't need it.


The second thing is the fact that you increase the number of day for the pregnancy. Personally I would have decreased it. This open the possibility to have pregnancy that are more or less longer.
With inheritance you can even end with:
class Animals():
The pregnancy and inheritance are also both good ideas. I'll add both of those things to the tutorial.

Thanks for the feedback!
 
  • Like
Reactions: anne O'nymous

Lyka

Member
Game Developer
Aug 31, 2018
252
376
hope you aren't hungry :)

am i right with the code?

Code:
label start:
   call pizza_luigi
   "you are in LABEL START"

label pizza_luigi:
   "now luigi is called!"
   call expression "pizza_toni"
   "BACK FROM PIZZA TONI AND NOW IN PIZZA LUIGIs LABEL"
   return

label pizza_toni:
    "best pizza only here: pizza toni"
    call expression "pizza_hut"
    "BACK FROM PIZZA HUT AND NOW IN PIZZA TONIs LABEL" # back from pasta
    return #jump pasta

label pizza_hut:
    "cheap pizza at pizza hut"
    jump pasta # after changing return to jump

label pasta:
    "pasta"
    return # it skips label pizza_hut: because no "call expression"?

[Code]
 
  • Like
Reactions: anne O'nymous

Maid Lain

Well-Known Member
Modder
Game Developer
Apr 4, 2018
1,888
16,215
@Lyka
Code:
label start:
   jump pizza_luigi

label pizza_luigi:
   "1"
   call pizza_toni
   "7 - The end."
   return

label pizza_toni:
    "2"
    call pizza_hut
    "6"
    return

label pizza_hut:
    "3"
    call pasta
    "5"
    return

label pasta:
    "4"
    return
You can just write call label_name instead of call expression "label_name" if you're just writing the label name to call.

Pasta doesn't return to Pizza_Hut because you jumped to pasta instead of calling it. You call if you want to return to the label you were at.

And notice how I jumped to Luigi_Pizza instead of calling it. I don't want to return to the start label, so I use jump instead of call.
 
  • Like
Reactions: anne O'nymous

Lyka

Member
Game Developer
Aug 31, 2018
252
376
thank you for that.

but there is one thing i don't understand.
if i go back to my original game then i have to use call to let the condition check and bring me to the events.

but how do i decide what is better call or jump?
and what does it mean for the pc: does call storage all the progress and fill the ram and jump wont?
 

anne O'nymous

I'm not grumpy, I'm just coded that way.
Modder
Respected User
Donor
Jun 10, 2017
9,944
14,546
but how do i decide what is better call or jump?
I would say that "you'll know it", but it's part of the truth. You'll know it but only after you've gained more experience.
Basically, you call a label only because you'll have to return to your starting point. So, it can be because the label is conditional ; like the example I gave above, where part of the condition is put inside the label itself. It can also be because the label do a recurring task, like the one that check for the events, or a label that reset value at the start of each day by example.
In all the other case, you jump. And remember, what you tried demonstrated that you can have this :
Code:
label something:
    call calledLabel
    "blablabla"

label calledLabel:
    jump jumpedLabel

label jumpedLabel:
    return
The return statement is mandatory, since it's what make you return to the starting point, but it isn't necessary that it's put in the label you initially called. What matter is that, at the end of the chain, you have a return.
I know, it's a bit abstract for now, but it will come naturally after some practice.


and what does it mean for the pc: does call storage all the progress and fill the ram and jump wont?
Only the return point is stored, but it don't really use memory space. You can chain 500 call in a row, you'll still use less space that a single picture that Ren'py put in the memory cache. Anyway, once the game found a return, then what was stored is removed from the memory. So basically a game that make a massive (and correct) use of call should use what ? 1 Ko of RAM that isn't used with a game that just jump.
 
  • Like
Reactions: Lyka