[Solved] Defining and calling custom functions in game and screens

Discuss how to use the Ren'Py engine to create visual novels and story-based games. New releases are announced in this section.
Forum rules
This is the right place for Ren'Py help. Please ask one question per thread, use a descriptive subject like 'NotFound error in option.rpy' , and include all the relevant information - especially any relevant code and traceback messages. Use the code tag to format scripts.
Post Reply
Message
Author
User avatar
ComputerArt.Club
Veteran
Posts: 423
Joined: Mon May 22, 2017 8:12 am
Completed: Famous Fables, BoPoMoFo: Learn Chinese, Santa's workshop, Cat's Bath, Computer Art Club
Location: Taiwan
Contact:

[Solved] Defining and calling custom functions in game and screens

#1 Post by ComputerArt.Club » Sat Jul 13, 2019 11:24 pm

I have a lot of repetition in my games, and to reduce the code and make things more efficient and make it easier to change large sections at once, I would like to learn how to do functions in game and in screens.

For example I'd like to make a function here with say, two or three arguments, that would create a screen that replaces all instances of those arguments. E.g.

Code: Select all

screen find1: # the screen name might be made irrelevant by a function
    add "background"
    text _("Where is the [argument 1]?") xalign 0.5 yalign 0.03
    imagebutton:
            idle "[argument 1]"
            xalign 0.5
            ypos 1000
            action Return("[argument 1]") # assets would be named appropriately

    imagebutton:
            idle "[argument 2]"
            xalign 0.5
            ypos 800
            action Return("[argument 2]")
And then how would I call it?

Similarly, can I do something in the script like call a function with arguments that replace the image names and certain text with the arguments?

Like:

Code: Select all

show [argument 1]
show [argument 2]
voice "prefix[argument 1]" # I suppose there might be instances where prefixes or suffixes would be necessary.
call screen [argument 1] # Basically, the arguments would be used in a variety of situations.
if result =="[argument 1]"
	"Well done! You found the [argument 1]"
	jump found [argument 1]
Basically, I am an elementary school teacher and a father and I want my games to target younger readers, so there is a lot of repetition. My understanding is that the best way to manage such repetition would be to use functions. Does anyone have any thoughts, suggestions or ideas?

Thanks for taking the time to read this.
Last edited by ComputerArt.Club on Mon Jul 15, 2019 3:27 am, edited 1 time in total.

User avatar
ComputerArt.Club
Veteran
Posts: 423
Joined: Mon May 22, 2017 8:12 am
Completed: Famous Fables, BoPoMoFo: Learn Chinese, Santa's workshop, Cat's Bath, Computer Art Club
Location: Taiwan
Contact:

Re: defining and calling custom functions in game and screens

#2 Post by ComputerArt.Club » Sun Jul 14, 2019 6:25 am

Checked the patreon entry on creator defined statements and the wiki and a the two threads here that I could find on defining custom functions, and the tutorial on mad libs but still haven’t figured it out, none of them seem to be tackling the same type of problem :/

User avatar
xavimat
Eileen-Class Veteran
Posts: 1446
Joined: Sat Feb 25, 2012 8:45 pm
Completed: Yeshua, Jesus Life, Cops&Robbers
Projects: Fear&Love, unknown
Organization: Pilgrim Creations
Github: xavi-mat
itch: pilgrimcreations
Location: Spain
Contact:

Re: defining and calling custom functions in game and screens

#3 Post by xavimat » Sun Jul 14, 2019 10:09 am

Creator defined statements are too advanced stuff for this, relatively simple, question.
I haven't understood exactly what you need. But I guess some of these can be useful for you:

1. You can use labels and call them to repeat some renpy code. Labels will behave similar to functions. You can pass arguments to them too. At he end of the label put return to return to the point where you called the label.

Code: Select all

default myvar = 1
label start:
    while myvar < 5:
        call somelabel(myvar)
        $ myvar += 1
    "End of game."
    return
    
label somelabel(myvar2):
    "Count" "I count to [myvar2]. Hahahahahaha."
    return
    
2. You can use "expression" with variables and call, jump, show:

Code: Select all

$ myvar = "somestring"
show expression myvar  
call expression myvar
jump expression myvar 
3. You can use variables inside screens to add images, define imagebuttons, and use if/elif/else statements so your screen will do exactly what you want. You can also call your screens with arguments that will be used as local variables to the screen.

4. You usually don't need interpolation for many things you have shown in your example code:

Code: Select all

if myvar == othervar # not myvar == "[othervar]"
idle myvar # not idle "[myvar]"
Return(myvar). # not Return("[myvar]")
5. You can use also python functions, but usually they are better for calculations (although they can also show images and screens, use say lines and nearly everything that labels can do, but in less readable code).

The best way to achieve what you want depends on your specific needs. There are many ways of doing the same thing, it depends on the "big pictures" to give you useful answers. I suggest you to break down your question in small ones, to get better answers.
Comunidad Ren'Py en español: ¡Únete a nuestro Discord!
Rhaier Kingdom A Ren'Py Multiplayer Adventure Visual Novel.
Cops&Robbers A two-player experiment | Fear&Love Why can't we say I love you?
Honest Critique (Avatar made with Chibi Maker by ~gen8)

User avatar
Alex
Lemma-Class Veteran
Posts: 2501
Joined: Fri Dec 11, 2009 5:25 pm
Contact:

Re: defining and calling custom functions in game and screens

#4 Post by Alex » Sun Jul 14, 2019 1:03 pm

ComputerArt.Club wrote:
Sat Jul 13, 2019 11:24 pm
I have a lot of repetition in my games, and to reduce the code and make things more efficient and make it easier to change large sections at once, I would like to learn how to do functions in game and in screens. ...
As xavimat said "The best way to achieve what you want depends on your specific needs.".
Some other thing that might help you.
1. If you need some similar screens with different content, you could create a screen and fill it with the staff (arguments) from a list, like

Code: Select all

image img_1 = "img_1.png" # etc.

screen find(): # the same screen will be shown in different parts of game
    add "background"
    
    for item in my_list:
        if item["to_find"]:
            $ goal_name = item["txt"]
    
        imagebutton:
                idle item["img"]
                xalign 0.5
                pos item["pos"]
                if item["to_find"]:
                    action Return("win")
                else:
                    action Return("lose")
                sensitive can_click

    text _("Where is the [goal_name]?") xalign 0.5 yalign 0.03


    
# The game starts here.

label start:
    "..."
    $ my_list = [ {"img":"img_1", "txt":"argument 1", "pos":(100, 100), "to_find":True},
    {"img":"img_2", "txt":"argument 2", "pos":(200, 200), "to_find":False},
    {"img":"img_3", "txt":"argument 3", "pos":(800, 500), "to_find":False},
    ]
    "Let's play a game..."
    call my_game
    "Ok."
    
    $ my_list = [ {"img":"img_1", "txt":"argument 1", "pos":(100, 100), "to_find":False},
    {"img":"img_3", "txt":"argument 3", "pos":(800, 500), "to_find":True},
    ]
    
    "And once again..."
    call my_game
    "Great!"
    return
    
    
    
label my_game:
    $ can_click = False
    
    show screen find

    label my_loop:
        $ can_click = True
        $ res = ui.interact()
        $ can_click = False
        if res == "win":
            "Well done!"
            hide screen find
        else:
            "Nope... Try again."
            jump my_loop
        
    return

2. You can use python equivalents of Ren'Py statements to pass values to them from variables.

Code: Select all

$ renpy.jump(var_label_name)
$ renpy.show(var_img_name)

3. You can create some functions and use them as an action for buttons, etc. using Function action - https://www.renpy.org/doc/html/screen_a ... l#Function

4. You can create your own actions for buttons - copy/paste code for existing action from renpy_folder/renpy/common/00action_xxx.rpy, give this action an unique name and customize it the way you like.

User avatar
ComputerArt.Club
Veteran
Posts: 423
Joined: Mon May 22, 2017 8:12 am
Completed: Famous Fables, BoPoMoFo: Learn Chinese, Santa's workshop, Cat's Bath, Computer Art Club
Location: Taiwan
Contact:

Re: defining and calling custom functions in game and screens

#5 Post by ComputerArt.Club » Sun Jul 14, 2019 9:44 pm

Thank you Alex and Xavimat. Alex, your first example looks like what I was hoping for.
Do you think it will be possible for me to translate the arguments? Is there anything I should do to flat it for translation?

Code: Select all

label start:
    "..."
    $ my_list = [ {"img":"img_1", "txt":"argument 1", "pos":(100, 100), "to_find":True},
    {"img":"img_2", "txt":"argument 2", "pos":(200, 200), "to_find":False},
    {"img":"img_3", "txt":"argument 3", "pos":(800, 500), "to_find":False},
    ]
    "Let's play a game..."
    call my_game
will "argument 1" "argument 2" and "argument 3" show up for translation? Thank you again for all your help!!!

User avatar
ComputerArt.Club
Veteran
Posts: 423
Joined: Mon May 22, 2017 8:12 am
Completed: Famous Fables, BoPoMoFo: Learn Chinese, Santa's workshop, Cat's Bath, Computer Art Club
Location: Taiwan
Contact:

Re: defining and calling custom functions in game and screens

#6 Post by ComputerArt.Club » Mon Jul 15, 2019 3:09 am

Alex wrote:
Sun Jul 14, 2019 1:03 pm

1. If you need some similar screens with different content, you could create a screen and fill it with the staff (arguments) from a list, like

Code: Select all

image img_1 = "img_1.png" # etc.

screen find(): # the same screen will be shown in different parts of game
    add "background"
    
    for item in my_list:
        if item["to_find"]:
            $ goal_name = item["txt"]
    
        imagebutton:
                idle item["img"]
                xalign 0.5
                pos item["pos"]
                if item["to_find"]:
                    action Return("win")
                else:
                    action Return("lose")
                sensitive can_click

    text _("Where is the [goal_name]?") xalign 0.5 yalign 0.03


    
# The game starts here.

label start:
    "..."
    $ my_list = [ {"img":"img_1", "txt":"argument 1", "pos":(100, 100), "to_find":True},
    {"img":"img_2", "txt":"argument 2", "pos":(200, 200), "to_find":False},
    {"img":"img_3", "txt":"argument 3", "pos":(800, 500), "to_find":False},
    ]
    "Let's play a game..."
    call my_game
    "Ok."
    
    $ my_list = [ {"img":"img_1", "txt":"argument 1", "pos":(100, 100), "to_find":False},
    {"img":"img_3", "txt":"argument 3", "pos":(800, 500), "to_find":True},
    ]
    
    "And once again..."
    call my_game
    "Great!"
    return
Thank you!!!! I really appreciate your hard work! Modified and tried this out and it is working very well so far, doing exactly what I was hoping to do. I will test again later to see whether I can get the arguments for text fields in screens to translate.

Thank you Xavimat for your time, too. I really appreciate it.

User avatar
ComputerArt.Club
Veteran
Posts: 423
Joined: Mon May 22, 2017 8:12 am
Completed: Famous Fables, BoPoMoFo: Learn Chinese, Santa's workshop, Cat's Bath, Computer Art Club
Location: Taiwan
Contact:

Re: defining and calling custom functions in game and screens

#7 Post by ComputerArt.Club » Mon Jul 15, 2019 3:27 am

With a little further modification it looks like I have it working for translation!

Code: Select all

$ my_list = [{"txt":_("example1"), ...
put the text in parenthesis with the underscore before it as in screens and it will be marked for translation.
Thank you everyone!

Post Reply

Who is online

Users browsing this forum: ammonoids, Google [Bot], PlantMan, Vib Tardius, zombiehead