Defining and calling user-defined functions?

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
Rosstin
Veteran
Posts: 368
Joined: Mon Jan 31, 2011 5:43 pm
Completed: Rex Rocket, Kitty Love, King's Ascent
Projects: Road Redemption, Queen At Arms
Organization: Aqualuft Games
Contact:

Defining and calling user-defined functions?

#1 Post by Rosstin »

So, I'm writing a game in Renpy that includes a battle system. My problem is that I want to be able to call and return functions, which will perform certain actions and then return to the label they originated from and then continue.

From what I understand of labels, labels act as a sort of "GOTO". After the label finishes executing, it simply jumps to the next label it is given, rather than returning to the label that called it.

For example, I want the LABEL- BATTLE 1 to execute, call a function that displays the main character's attack menu, then call a function for the enemy that the main character is fighting.

Is there a way I can define and call user-defined functions in Renpy? Is it user-friendly? If not, what is a sensible alternative to what I am trying to do?

Image Image
Image

Megaman Z
Miko-Class Veteran
Posts: 829
Joined: Sun Feb 20, 2005 8:45 pm
Projects: NaNoRenO 2016, Ren'Py tutorial series
Location: USA
Contact:

Re: Defining and calling user-defined functions?

#2 Post by Megaman Z »

Okay, bear with me on this one, there's a handful of answers for this:

First off, Ren'Py is Python-based. all Python statements outside of a python: block must be preceded with the $ character. You CAN define actual functions inside Python blocks (I advise using init python: blocks for these). You can call functions either as normal in python blocks or outside them by preceding them with the $ character.

Secondly, Labels can act as GOTO or CALL, depending on what command you use to get to the label.
Jump <label> will go to the label. Under most circumstances, you will not use the return command on a label you jump to.
while Call <label> will go to the label AS A SUBROUTINE, and the return command will bring you back to where the call was done. If you have a called label and you jump from that label to another one, you can STILL use the return command as if you had not jumped.

So, if you're somewhere in label Label_A...
...and you CALL Label_B...
...and then JUMP to Label_C...
...and then use the RETURN command in Label_C...
...you will be back NOT in Label_B but in Label_A, since that's where the last call occurred from.

Fair bit of warning: if you have not done a Call Label command, the Return command will end the game and bring you back to the main menu.

in other words, yes, you can also fake a function definition using labels and the Ren'Py call command. I'd advise going the first route (actual Python) if you're familiar enough with the language to do so (and most of us will help if you're not).
~Kitsune Zeta

User avatar
Rosstin
Veteran
Posts: 368
Joined: Mon Jan 31, 2011 5:43 pm
Completed: Rex Rocket, Kitty Love, King's Ascent
Projects: Road Redemption, Queen At Arms
Organization: Aqualuft Games
Contact:

Re: Defining and calling user-defined functions?

#3 Post by Rosstin »

Oh, beautiful! Thank you for the prompt and helpful answer! I'll investigate both of those options.

I'm all for getting deeper into Python-- I'll probably have to use it for work later anyway. I just want to be careful I don't stray too far from Renpy's design philosophy.
Image

User avatar
Rosstin
Veteran
Posts: 368
Joined: Mon Jan 31, 2011 5:43 pm
Completed: Rex Rocket, Kitty Love, King's Ascent
Projects: Road Redemption, Queen At Arms
Organization: Aqualuft Games
Contact:

Re: Defining and calling user-defined functions?

#4 Post by Rosstin »

OK, two more questions.

How can I define something like a STRUCT? For character data, for example.

And also: what do you recommend as a good database for Python/Renpy questions? I'm aware of the cookbook and other easy-to-find Renpy resources; is there something I'm missing? Actually, what would be really nice to find would be a clear, open-source example of a Renpy battle system. I'm not trying to do anything particularly complicated-- having an example to crib from would be wonderful.

Thanks so much!

Image
Image

Megaman Z
Miko-Class Veteran
Posts: 829
Joined: Sun Feb 20, 2005 8:45 pm
Projects: NaNoRenO 2016, Ren'Py tutorial series
Location: USA
Contact:

Re: Defining and calling user-defined functions?

#5 Post by Megaman Z »

In C++ (which I assume you're referring to with the struct question), a struct was a class with all members implicitly public (whereas a class has all of its members implicitly private), but in all other regards, the two are identical. In Python, a struct refers to something completely different (which I don't understand myself), but a class in Python is roughly equivalent to a struct in C++ (although the syntax for declaring one is different)

Questions regarding how to do things in Ren'Py do belong in this subforum. I'm not quite familiar enough with the language to get a sample battle system up (if someone else reads this and is comfortable enough to do a simple one, by all means, do so).
~Kitsune Zeta

User avatar
Rosstin
Veteran
Posts: 368
Joined: Mon Jan 31, 2011 5:43 pm
Completed: Rex Rocket, Kitty Love, King's Ascent
Projects: Road Redemption, Queen At Arms
Organization: Aqualuft Games
Contact:

Re: Defining and calling user-defined functions?

#6 Post by Rosstin »

Sorry to keep buggin' you-- I'm learning though. I've got a pretty kicking little demo of my battle system up.

I'm trying to figure out if there's a way to include multiple possibilities as triggers for an if statement right now.

IE: right now I have this little thing

Code: Select all

    if moll_currentattack is "facepunch":
        (do stuff)
Later the character gets an attack named "brassknuckle" which is nearly identical. So I want to say...

Code: Select all

    if moll_currentattack is "facepunch" or "brassknuckle":
        (do stuff)
Of course, that doesn't execute properly. Is there a way to do this without working around it? I figure at some point I will want to be able to use || type of statements.

I guess, like you were saying, I should probably just be working in straight python more.
Image

User avatar
SleepKirby
Veteran
Posts: 255
Joined: Mon Aug 09, 2010 10:02 pm
Projects: Eastern Starlight Romance, Touhou Mecha
Organization: Dai-Sukima Dan
Location: California, USA
Contact:

Re: Defining and calling user-defined functions?

#7 Post by SleepKirby »

asterazul wrote:

Code: Select all

    if moll_currentattack is "facepunch" or "brassknuckle":
        (do stuff)
Does that work if you make it

Code: Select all

if moll_currentattack is "facepunch" or moll_currentattack is "brassknuckle":
?
My thinking is that "brassknuckle" alone can't be an operand to a boolean operator like or.

Also, if you want to experiment with Python more, you could download a Python shell. You may be able to test simple Python code much more quickly this way, as opposed to having to run and re-run Ren'Py. More details here: http://lemmasoft.renai.us/forums/viewto ... 79#p117179

User avatar
KeyboardSan
Regular
Posts: 26
Joined: Sun Oct 05, 2014 5:38 am
Completed: A Sweet Meeting, SRZ, Flower Field
Contact:

Re: Defining and calling user-defined functions?

#8 Post by KeyboardSan »

Hey, I have made a small battle engine. I guess you can put it in 'python:' block inn ren'py code but you have to do something else to print the messages. I hope it helps.

Code: Select all

import random #import files for random numbers


print("Battle System"); #print 'Battle System'


##########################################################


#define a player object
class player(object):
    def __init__(self,name):
        self.name = name;
        self.health = 100;
        self.power = 50;
        self.xp = 20;
        self.weapon = "fist";
        self.luck = 2;

##########################################################


#define a monster object
class monster(object):
    def __init__(self,health,power,name,luck):
        self.name = name;
        self.health = health;
        self.power = power;
        self.luck = luck;



###########################################################


#create a function for a battle to happen between player and monster
def battle(pl,mon):
    while(mon.health>0): #battle loop while monster remains alive

        print("What will you do?"); #print message
        print("1.Attack   2.Do nothing"); #print choices


        x = input(">"); #take input


        if(x==1): #check choices if choice is to attack then>
            print("You used "+pl.weapon+" to attack the "+mon.name+"."); #print a message


            #now in this if statement I am just using my own method to check the
            #luck of the frog. You can use anyother method to check it :)
            if(random.randint(0,(20-mon.luck))<7): #check luck
                print(mon.name+" dodged your attack."); #monster dodged
            else:
                print(mon.name+" is hit."); #monster is hit
                mon.health-=pl.power/mon.luck; #decrease monster's health
                if(mon.health<=0): #check if monster has died due to attack
                    print(mon.name+" died");
                    break; #break the while loop if monster has died



        else: #else if choice is to do nothing or anything else then>
            print("You stood and did nothing");



        print(mon.name+" attacked you."); #now monster is attacking it will
        #always attack you no checking required. ;)

        if(random.randint(0,(20-pl.luck))<7):#checking player's luck
            print("You dodged.");

        else:
            print("You are hit.");
            pl.health-=mon.power; #if hit then reduce player's health
            if(pl.health<=0): #check to see if player has died
                print("You died.");
                break; #if player has died then break the while loop
            


#######################################################

#create a player object. I named my player 'law'
law = player("law"); #player(self,name)


#create a monster object. I created a frog
frog = monster(30,20,"frog",2); #monster(self,health,power,name,luck)


print("Would you like to battle?"); #print message
print("1.Yes   2.No"); #print choices


x = input(">"); #take input from user


if(x==1): #check input
    print("Battle begins!");
    battle(law,frog); #battle begins function is called if choice is 1.
else:
    print("No battle happens."); #no battle happens if choice is something else

#############################################################

Post Reply

Who is online

Users browsing this forum: No registered users