Classes and extending Characters

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
Formedras
Regular
Posts: 40
Joined: Sat Oct 04, 2008 3:11 am
Projects: Ninja TK
Contact:

Classes and extending Characters

#1 Post by Formedras » Tue Oct 21, 2008 3:39 am

Please note: This is more of a Python-related thread than purely Ren'Py. It's perfectly relevant to Ren'Py, but I doubt that any code examples given aren't going to start with "init python:". Just a warning to the non-programmers here.

First, how do I give default values to variables in classes? I know that this should be pretty damn simple. Heck, it probably actually is. But I don't quite get it, nor do I understand the _init_ routine inside the class. I know that it runs when a variable of the class' type is created, but the specific timing and the usage of it kinda confuses me.

Second, is it possible to pass classes to python routines? I know that the answer is probably "yes," but I don't want to write or rewrite 200 lines of code just to find out that you can't pass classes or that doing so has so many issues that it's not worth doing.

Third, is it possible to extend the Character class, so that I can give it extra variables that I can treat as if in the class? (This directly relates to the second question: I want to give RPG-style stat variables to a Character and be able to just pass the Character into my routines to make the code a lot cleaner and readable.) If so, how?

I know that these questions are probably findable somewhere in the Python documentation, but it took me a week to just find a fraction of what I needed about lists and matrices. Finding what you want in that thing is like finding a needle in a needlestack. (NCIS fans should now quote DiNozzo and then I quote Ziva.)
I've been making for myself a couple of Test projects to work on my code before I actually try to implement it, so I'll be trying to find these answers out on my own. I doubt I'll be able to get my own answers before the community can, though.
http://www.google.com/profiles/tizalka
Current Project:
Ninja TK

User avatar
Wintermoon
Miko-Class Veteran
Posts: 701
Joined: Sat May 26, 2007 3:41 pm
Contact:

Re: Classes and extending Characters

#2 Post by Wintermoon » Tue Oct 21, 2008 3:50 pm

Formedras wrote:First, how do I give default values to variables in classes?
Assign them in __init__.
Formedras wrote:But I don't quite get it, nor do I understand the _init_ routine inside the class. I know that it runs when a variable of the class' type is created, but the specific timing and the usage of it kinda confuses me.
When you create a new instance of a class by calling that class:
  • Python creates a blank object of the class you want.
  • Python call that object's __init__ method, passing along any arguments that you passed to the class. At the time when this happens, the object already exists.
Formedras wrote:Second, is it possible to pass classes to python routines?
Yes. Classes, modules, functions and bound methods are all first class objects in Python.
Formedras wrote:Third, is it possible to extend the Character class, so that I can give it extra variables that I can treat as if in the class? (This directly relates to the second question: I want to give RPG-style stat variables to a Character and be able to just pass the Character into my routines to make the code a lot cleaner and readable.) If so, how?
Don't do that. Character objects aren't saved.

User avatar
Aenakume
Regular
Posts: 182
Joined: Mon Aug 11, 2008 4:38 am
Projects: Arts... i hate arts -_-
Contact:

Re: Classes and extending Characters

#3 Post by Aenakume » Tue Oct 21, 2008 5:10 pm

Wintermoon wrote:
Formedras wrote:Third, is it possible to extend the Character class, so that I can give it extra variables that I can treat as if in the class? (This directly relates to the second question: I want to give RPG-style stat variables to a Character and be able to just pass the Character into my routines to make the code a lot cleaner and readable.) If so, how?
Don't do that. Character objects aren't saved.
Not only that, Character objects aren't really logically compatible with actual characters in the sense Formedras means. For example, if you were making a game with Eileen, and she was at school one scene and at home the next, you would probably find it more natural to make two different characters - one in school uniform and one in normal clothes, each with its own set of expressions. The more different versions of Eileen you have (beach, formal dress, naughty-naughty), the more Character objects you might create... even though it's all just one character - Eileen. i think of Characters as characters in a scene, not actual unique characters.

So you'd probly be better off to just make your own stats class, and not bother extending the Character class.
“You can lead a fool to wisdom, but you cannot make him think.”

User avatar
delta
Epitome of Generic
Posts: 525
Joined: Sat Dec 22, 2007 12:59 pm
Projects: yes
Contact:

Re: Classes and extending Characters

#4 Post by delta » Tue Oct 21, 2008 6:15 pm

Aenakume wrote:For example, if you were making a game with Eileen, and she was at school one scene and at home the next, you would probably find it more natural to make two different characters - one in school uniform and one in normal clothes, each with its own set of expressions. The more different versions of Eileen you have (beach, formal dress, naughty-naughty), the more Character objects you might create... even though it's all just one character - Eileen. i think of Characters as characters in a scene, not actual unique characters.
what
Not that characters are really multipurpose characters and can or should be used as such, but what you just said doesn't make sense either. A Ren'Py Character is pretty much just a very elaborate text formatting device, nothing else. Actual character graphics have nothing to do with it except in some very, very far-fetched ways.
The rest is left as an exercise for the reader.

User avatar
Aenakume
Regular
Posts: 182
Joined: Mon Aug 11, 2008 4:38 am
Projects: Arts... i hate arts -_-
Contact:

Re: Classes and extending Characters

#5 Post by Aenakume » Tue Oct 21, 2008 8:03 pm

delta wrote:
Aenakume wrote:For example, if you were making a game with Eileen, and she was at school one scene and at home the next, you would probably find it more natural to make two different characters - one in school uniform and one in normal clothes, each with its own set of expressions. The more different versions of Eileen you have (beach, formal dress, naughty-naughty), the more Character objects you might create... even though it's all just one character - Eileen. i think of Characters as characters in a scene, not actual unique characters.
what
Not that characters are really multipurpose characters and can or should be used as such, but what you just said doesn't make sense either. A Ren'Py Character is pretty much just a very elaborate text formatting device, nothing else. Actual character graphics have nothing to do with it except in some very, very far-fetched ways.
i guess you don't use side images?
“You can lead a fool to wisdom, but you cannot make him think.”

User avatar
delta
Epitome of Generic
Posts: 525
Joined: Sat Dec 22, 2007 12:59 pm
Projects: yes
Contact:

Re: Classes and extending Characters

#6 Post by delta » Wed Oct 22, 2008 4:56 am

Nobody uses side images, because it's not the default. The like three people using side images should know what they are doing.

Apart from that, the side image is an example of a way that I would consider far-fetched. You either have to use a dynamic displayable (which has nothing to do with Characters directly) or create one Character per image, which is totally beside the point of Characters.
The rest is left as an exercise for the reader.

User avatar
herenvardo
Veteran
Posts: 359
Joined: Sat Feb 25, 2006 11:09 am
Location: Sant Cugat del Vallès (Barcelona, Spain)
Contact:

Re: Classes and extending Characters

#7 Post by herenvardo » Wed Oct 22, 2008 5:25 pm

Formedras wrote:Please note: This is more of a Python-related thread than purely Ren'Py. It's perfectly relevant to Ren'Py, but I doubt that any code examples given aren't going to start with "init python:". Just a warning to the non-programmers here.
That got me interested on the thread :P
Formedras wrote:First, how do I give default values to variables in classes? I know that this should be pretty damn simple. Heck, it probably actually is. But I don't quite get it, nor do I understand the _init_ routine inside the class. I know that it runs when a variable of the class' type is created, but the specific timing and the usage of it kinda confuses me.
Wintermoon's reply above is quite correct, but I thought you might better see it with some simple example:

Code: Select all

class MyClass:
    def __init__(self, stuff, whatever="something"): # this block defines the __init__ method
        self.stuff = stuff # initialize each relevant field with the provided parameters
        self.whatever = whatever # just like above
        self.money = 0 # The objects will always start with 0 money
        # The constructor call can't affect this value, because it's not based on any of the arguments
# ... later on the script:
MyObj1 = MyClass("stuff1", "what1") # this creates an object with the initial values:
    # MyObj1.stuff = "stuff1", MyObj1.whatever = "what1", MyObj1.money = 0
MyObj2 = MyClass("stuff2") # now the whatever argument is omitted, and the default value will be used:
    # MyObj2.stuff = "stuff2", MyObj2.whatever = "something", MyObj2.money = 0
Hope this (together with Wintermoon's explanation) helps you understand the workings of __init__. For further doubts, don't hesitate to ask ;)
Wintermoon wrote:
Formedras wrote:Second, is it possible to pass classes to python routines?
Yes. Classes, modules, functions and bound methods are all first class objects in Python.
That's most of it. However, I think it's worth to point out that you should pass to a routine what it expects. If a method wants a function or callable object and you feed it a tuple of modules Python is very likely to spit a TypeError at your face. But it's perfectly possible to define a method that takes a class, or a tuple of modules, or (almost) anything you can imagine, and (assuming you don't mess something up on the method itself) it can perfectly work ;)
And, of course, you can also pass objects and "normal" values (such as numbers or strings) as well ;)
Formedras wrote:Third, is it possible to extend the Character class, so that I can give it extra variables that I can treat as if in the class? (This directly relates to the second question: I want to give RPG-style stat variables to a Character and be able to just pass the Character into my routines to make the code a lot cleaner and readable.) If so, how?
This, in theory, can't be done on ren'py, mostly because Character objects are not saveable (despite Ren'py has actually succeed at saving/loading them everytime I tried, it's still not advisable because it's not supposed to work). However, if you are like me (and I have a good reason to think you are), a "can't be done" won't be enough of an answer for you. Actually, I faced a very similar problem, for a very similar purpose (that's why I think you are like me :P): I wanted to reuse my RPG-ish characters as Ren'py characters because I was completelly sure I'd end up messing with variable names if I tried to define them separately, and because it makes sense: they represent different aspects (RPG-ish stats vs. text displaying behavior) of the same object.
The solution was to define a RPGish character class (I called it Creature on my project) with all the RPGish stuff, plus all the stuff needed to define a Ren'py Character object. Then added a __call__ method that generates a Character object, based on this data, on the fly; and finally calls such object with the given arguments to produce the "say" effect: voilà, I got a saveable object that stores all my RPG-ish stuff and doubles as a Ren'py Character clone ^^
Of course, I didn't figure out how to do this on my own, but I had to ask for help on these forums. I strongly advise you to take a look on that threat, found at http://lemmasoft.renai.us/forums/viewto ... f=8&t=4097.
Aenakume wrote:i guess you don't use side images?
It's worth to mention that my Creature class' approach could easily allow for side images, despite I don't use them (at least not currently): the actual Character objects are very short-lived, they only last for a single say statement, and a new object is generated for the next use; so it's easily possible to store the different side images for each creature as a list on the class, keep track of which scene we are on, and add some logics on the __call__ method to chose the appropriate image.
Even with "normal" Character objects, I don't think it's impossible to have different side images for a single character object: ConditionSwitch can do wonders ;)
delta wrote:Nobody uses side images
Wrong: apparently Aenakume does :P


HTH
I have failed to meet my deadlines so many times I'm not announcing my projects anymore. Whatever I'm working on, it'll be released when it is ready :P

User avatar
Aenakume
Regular
Posts: 182
Joined: Mon Aug 11, 2008 4:38 am
Projects: Arts... i hate arts -_-
Contact:

Re: Classes and extending Characters

#8 Post by Aenakume » Wed Oct 22, 2008 8:21 pm

herenvardo wrote:
Aenakume wrote:i guess you don't use side images?
It's worth to mention that my Creature class' approach could easily allow for side images, despite I don't use them (at least not currently): the actual Character objects are very short-lived, they only last for a single say statement, and a new object is generated for the next use; so it's easily possible to store the different side images for each creature as a list on the class, keep track of which scene we are on, and add some logics on the __call__ method to chose the appropriate image.
Even with "normal" Character objects, I don't think it's impossible to have different side images for a single character object: ConditionSwitch can do wonders ;)
Impossible, no - but when you get a longer and more detailed story, things start to add up. Let's say you have a single character that changes outfit 4 different times, with 5 different expressions for each outfit - that's already a 20 condition ConditionSwitch, and that's not really that many expressions and it doesn't include lip flapping. In short order you can find yourself with a 100+ condition ConditionSwitch, for a major character in a long game.

For minor characters like creatures - like what you're talkin about - there's no real problem, of course.
herenvardo wrote:
delta wrote:Nobody uses side images
Wrong: apparently Aenakume does :P
*shrug* Well apparently i'm nobody, and doing "very, very far-fetched" things in Ren'Py... so i guess i don't count, eh?
“You can lead a fool to wisdom, but you cannot make him think.”

User avatar
herenvardo
Veteran
Posts: 359
Joined: Sat Feb 25, 2006 11:09 am
Location: Sant Cugat del Vallès (Barcelona, Spain)
Contact:

Re: Classes and extending Characters

#9 Post by herenvardo » Thu Oct 23, 2008 6:44 am

Aenakume wrote:
herenvardo wrote:
Aenakume wrote:i guess you don't use side images?
It's worth to mention that my Creature class' approach could easily allow for side images, despite I don't use them (at least not currently): the actual Character objects are very short-lived, they only last for a single say statement, and a new object is generated for the next use; so it's easily possible to store the different side images for each creature as a list on the class, keep track of which scene we are on, and add some logics on the __call__ method to chose the appropriate image.
Even with "normal" Character objects, I don't think it's impossible to have different side images for a single character object: ConditionSwitch can do wonders ;)
Impossible, no - but when you get a longer and more detailed story, things start to add up. Let's say you have a single character that changes outfit 4 different times, with 5 different expressions for each outfit - that's already a 20 condition ConditionSwitch, and that's not really that many expressions and it doesn't include lip flapping. In short order you can find yourself with a 100+ condition ConditionSwitch, for a major character in a long game.
I didn't say ConditionSwitch was the best approach, not even that it'd be a good idea. I just mentioned it as a possibility.
Aenakume wrote:For minor characters like creatures - like what you're talkin about - there's no real problem, of course.
I'm not sure if you really know what I'm talking about :P. Sure, I have some Creature objects representing minor characters, such as random encounter ork parties; but main characters on FoJ are also Creature objects. Now that I think it better, it's even possible to do some of this tinkering directly on Character objects (as long as you can do everything from within init blocks, of course): You can add an attribute named "sides" or something like that to the object, and make it a list of lists of sprites (a.k.a. a 2D jagged array of sprites), then you can access each side-image sprite with an expression like:

Code: Select all

myChar.sides["school_outfit"]["happy"]
The advantage of using a custom class is that you can trivially add logics to the __call__ method, so the side-image is chosen on the fly based on mood, outfit, or whatever, for each say statement. And, of course, these "state" factors can also be stored on the object (that wouldn't work for Character objects because that "state" would need to be saved).
Currently, all the creature sprites (both "history-mode" character sprites and combat effects and animations) in my project are being referenced from their Creature objects... it's just a matter of time I get them working directly with show statements :twisted:. And it's true that I'm not currently changing outfits (that'd probably be too much for trecevidas to draw), but the code could handle that trivially (after all, I'm changing name's colors based on mood and state: choosing an image is absurdly easy compared to manipulating colors on the HSL space :P).

Well, in summary, with a bit of imagination and a good deal of headaches, the sky is the limit! ^^
I have failed to meet my deadlines so many times I'm not announcing my projects anymore. Whatever I'm working on, it'll be released when it is ready :P

Post Reply

Who is online

Users browsing this forum: Bing [Bot], Ocelot, Sergei Falcon