Pervy Rogues are creating a Ren'Py-Trainer Framework
Whenever developers want to create their own trainer game, they have to code work-arounds for the Ren’Py software in order to create the necessary systems for the game, as the initial Ren’Py software isn’t designed for something like a trainer game. A lot of time and effort spent when initially creating a new trainer game isn’t devoted to actually making the game itself, but instead on creating the base framework that the rest of the game can operate around. This is both labor intensive and time consuming, with too much time spent retracing the same steps that other developers have already done.
Developing a game in any capacity is often an incredibly difficult, stressful, thankless job. By creating a system which allows development to be more accessible and easier to understand for trainer games and Ren’Py as a whole, more time can be spent on developing the actual game, rather than just the base systems for the game. This means that more developers will be able to focus on the parts of trainer games that they actually want to work on without having to slog through developing their own systems while dealing with the Ren’Py software.
The Ren’Py-Trainer framework aims to remove the initial hassle of working on a trainer game, by instead providing a set of base systems to make trainer games (and games similar to trainer games) work. This will allow us and other creators to rapidly make the kinds of games that you enjoy, by reliving some of the initial difficulty that comes from working with Ren’Py’s limited function.
These include, but are not limited to:
An expanded character class with added functionality for trainer games.
A functioning and optimized paper-doll creator that can work with the stats provided by the new character class.
A location system, allowing for new locations to be quickly added.
An events system allowing for events based on conditions, location, characters, story events, etc. to run when needed instead of needing to follow a linear styled storyline.
A party system for characters following the player or each other.
A random dialogue response system to add variety and life.
For a trainer system, from what I've tried in the past, I would be concerned that the trainer system does not work alone, it needs to integrate across other systems. But I'm glad to see you outline some of these other systems
I haven't figured out how to make the composite image system any simpler or more intuitive than it already is, at least not without moving to C# with more intelligent coding IDE's or creating the code/date using a dedicated tool. I'm interested to know what you mean by 'creator' in this case
I'm used to breaking the world down into nodes/zones for other systems, but for ren'py I haven't been convinced that such a system is needed since most of the thought process can be emulated by jumping/calling to different scenes. As someone who has more of a programming background, willing to interpret how I code using abstraction perspective is normal for me, but I imagine most dev's who use ren'py but don't heavily explore programming concepts will find location systems useful, only being confused because abstraction is abstract. The only time I've really considered using such a system was for AI that could navigate the world... but I didn't stick to renpy for prototyping that. but if location system contributes to the trainer system in some way I hadn't thought of (mainly I would thick event triggers being the most common, ie forced to walk outside without certain clothing items would feed data to the trainer system)
those seemed like the three big systems to me, the other systems are also big, but I imagine they will come later (I haven't bother working on making any sort of party system before since I had no interest in that sort of mechanic). but I will say the modifiable system for sex scene will probably be the trickest, as in my experience when you make something 'modifiable' that means you are laying layers of abstractions on top of abstractions. IE the dev's have to learn how you decided to approach the problem of 'describing a sex scene.' For a lot of my ideas, I try to think about how to make it into a tool rather than an API since I don't expect to make anything amazing or popular, but if I want others to be able to use it, a tool is easiest for casual devs and non technical devs... but then most of the work is spent on making the tool, not solving problems. I'd be interested to hear how this project of yours develops and to see how you go about trying to make a system usable for others, be it just python code/classes, or if you go all ham and make dedicated tools. I haven't tried interfacing any sort of tool with renpy, so I don't know how easy or sub optimal the idea of tool generation would be, but I've seen others make editors inside of ren'py but nothing as nuanced as what could be made from scratch or in other game engine editors (ex unity plug ins with custom editor windows).
For a trainer system, from what I've tried in the past, I would be concerned that the trainer system does not work alone, it needs to integrate across other systems. But I'm glad to see you outline some of these other systems
Let me outline a few things that will hopefully help you understand the approach. First off, we are utilizing creator-defined statements; in other words we are making our own Ren'Py statements for creators to use. Statements are like menu: blocks in the basic Ren'Py script but, ours are for making all these trainer systems more accessible and less abstract. As you pointed out, abstraction is one of the harder things for junior developers to conquer and are going to be a foreign concept for many creators.
One of the things you mentioned as a reason to have 'locations' is something we already built out: Events! We have a functional event system with events that can be triggered in a number of ways including scripted events, location events, conditional events, scheduled events, and more. This was one of the reasons we started making our own custom statements.
Locations: currently our locations include data on the background, accessibility, characters in location, ownership, how public it is, and I can't think of more off the top of my head. What it also includes is what it connects too, allowing creators and mods to quickly add a new location to the 'graph' of locations. They can also link to a label if needed, and are part of the event system to allow for location based events. Using this concept is more 'concrete' than having to abstract out a location system, something I hope will make world-building a much easier exercise for creators.
Paper-doll: Currently in progress because the logic on this one is hell. But, the idea is fairly simple now: I am basing paper doll off of the layeredimage system which utilizes 'image-like displayable's. It's a really interesting concept and not at all an easy task. What I am seeking to do is replace layered image with something that is completely able to be tied to variables, specifically variables in our TRNCharacter class (which I will speak about in a moment). The hellish part of designing this system is being able to let the creator define the amount and order of layers that make up any given paper doll while still working for what ever pose is specified and allowing for easy changing of emotion in the face by both statement and variable. Oh yes, this one is painful to design.
TRNCharacter: You asked if we are just using OOP or 'going full ham'. The answer is YES. We are making classes, we are making tools, we have helper functions but, most importantly and crazily, we are making it all look like an extension of Ren'Py! TRNCharacter is an extension of Ren'Py's ADVCharacter class, giving it access to and all the functionality of a character you would normally create. It's even created the same way, just define kind='trn' when creating a new character, like this: define t = Character("Test", kind='trn')
Doing this will automatically build you a new character to the specified values in trainer_options.rpy, which is where you can specifiy what default stats characters should have, and a ton of other options.
The end result, we hope, of all of this is a framework you can just drop in that acts like a fork of Ren'Py made specifically for creating trainer style games.
it definitely sounds like you're deep in the sauce, working with a deeper understanding of ren'py's framework than what I've been exposed to, so it doesn't sound like I'll be able to offer or contribute much, but it definitely sounds like an awesome project.
So the goal is to make it seem like a ren'py extension, expanding ren'py's functionality by staying inside the familiar ren'py development environment, working similar to how ren'py works, such as with using statements. I will say I have had fun with renpy due to its high level approach to things thanks to its interpretive language. But then there are some cases where you do need to be more detailed, or low level code. I've too had to explore making a datatype that is meant to be highly customizable by users/modders/others, and "replace layered image with something that is completely able to be tied to variables" defiantly sounds like a familar problem I've ran into. Its basically a problem of 'a datatype that is undefined (not pre compiled by a file) but assembles itself at runtime' which interpretive languages are perfect for solving... and by that I mean, I often see the system is solved by figuring out an architecture (ie the system that allows layers and logic to be added on in any order), but rather than just leaving it as an API for devs, the system gets wrapped in a sort of smarter API, with the two most extreme case being interpretive languages (python, ren'py), or if its for really general system then a declarative language is made (that's a deep hole to fall into).
I'm not sure how deep you are into the code/framework of ren'py, I don't even know if renpy was coded using python or straight C like many python systems are (artifical intelegence stuff hook into python C engine for direct driver control of GPU's), but I would imagine that if you are already exploring the idea of taking advantage of user statements like renpy (such as the type "screen"), then it sounds like you are already exploring the tool sets you need to pull off the paper doll system, in the case that you need to go as far as develop a second interpretive engine just to wrap up your framework. I wasn't really comfortable with python and the black box of ren'py (I've been doing C# for years in comparison), so I was more willing to jump into the black hole that is declaritive language development.
All in all it doesn't sound like a pipe dream, it sounds like things have slowly started coming together and you're at the cusp of a comprehensive view of how everything may work... you just need to get the different systems/sub-systems made to see if and how it can come together. Sounds super promising and impressive, even with what you've managed to explore so far.
The hellish part of designing this system is being able to let the creator define the amount and order of layers that make up any given paper doll while still working for what ever pose is specified and allowing for easy changing of emotion in the face by both statement and variable. Oh yes, this one is painful to design.
Sorry to say it, but if it's a hellish and painful design, then you are doing it wrong. So, stop, move your hands far from the keyboard, and think again about what you want to achieve and what Ren'Py and Python provide you to do it.
You want a paper doll ?
Well, you'll have body parts, it will be your starting point.
What body parts need to be displayed ? An image, coordinate (x, y and of course z because they need to appear in the right order) and finally a rotation angle. Well, it's five variables, so your body part class don't need more than five variables at first.
Hmm... It's a bit limiting, isn't it ? It will have a dict of image, this will permit to customize the doll, giving it tan, tattoo and whatever. It also need constraints, the body parts can't rotate to the infinite.
Final touch, since it will move, but is part of an ensemble, we probably need to keep a copy of the coordinate relative to the body position.
Well, there's a bit more variables, but not this much more.
[Note: It's pure theoretical approach, thought and wrote on the fly. So for once I'll only comment what isn't understandable. If you (reader) do not understand what isn't commented, it mean that you still don't have the knowledge (Ren'Py/Python/codding) needed to extend this and add the missing parts.]
Python:
# where the magic happen.
def dynamicTransform( host ):
def inner( trans, st, at ):
trans.xpos = getattr( host, "x" )
trans.ypos = getattr( host, "y" )
trans.rotate = getattr( host, "rotation" )
return None
return Transform( function=inner )
class BodyPart( renpy.python.RevertableObject ):
def __init__( self, zorder, x, y, min, max, elements = {} ):
self.zorder = zorder
self.xOffset = x
self.yOffset = y
self.x = self.xOffset
self.y = self.yOffset
self.minAngle = min
self.maxAngle = max
self.rotation = 0
self.elements = elements # Key is the nickname ("default", "tattoo", "tanned", ...)
# Value is the image (you can proceed it if you want
self.selected = "default" # Currently selected kind of image you want
self.transform = dynamicTransform( self )
def reset( self ):
self.x = self.xOffset
self.y = self.yOffset
self.rotation = 0
# Pass from one kind of image to another, therefore from "default" to "tattoo" by example
def change( self, kind ):
self.selected = kind if kind in self.elements else "default"
# Display the image for this body part accordingly to the whole configuration.
@property
def show( self ):
renpy.show( self.elements[self.selected], at_list=[self.transform] )
def rotate( self, step ):
rotation = self.rotation + step
if rotation < self.minAngle:
self.rotation = self.minAngle
elif rotation > self.maxAngle:
self.rotation = self.maxAngle
else:
self.rotation = rotation
def moveX( self, step ):
self.x = self.x + step
def moveY( self, step ):
self.y = self.y + step
Saki_Sliz I guess that my /dynamicTransform/ will interest you, and not just for its dynamic creation of a transform.
Well, it's a good starts.
Thirtish lines, plus the seven for the transform, and we have a body parts that is displayed accordingly to the body modification we want, in the position we want, and with the rotation we want.
There's still works to do, because actually each body part is totally independent, what is wrong. It need the addition of a "linkedTo" value (reference to other BodyPart objects). Then when rotating or moving the parts, you can call the child body part to make it move accordingly.
But it's not something impossible. It need a "width" and "height" value, that will be used to compute the new boundary box for this body part. Boundary box that you'll pass to the child, up to it to adjust its own position. What mean that "xOffset" and "yOffset" need an additional value telling to which angle of the box they refer. Add a ratio, and you can deduct the position of the body part with from the boundary box of its father.
But, as I said, body parts are not randomly floating, they are part of a body. And here it's even simpler. The body need only three information. It's coordinate, and a list of the parts its made of. Later it will also need a list of available clothes, and which one is actually wore ; I'll add them already.
Python:
class PaperDoll( renpy.python.RevertableObject ):
def __init__( self, body, clothes ):
self.bodyRaw = body # list of BodyPart
self.bodyIndexed = { k:v for k, v in self.bodyRaw }
self.clothes = clothes # dict of ClothesSet (similar to PaperDoll, relying on ClothePart similar to BodyPart)
self.currentSet = None # What clothes set to use
# Display the paper doll
def __call__( self ):
for bp in sort( self.bodyRaw, key = lambda x: x.zorder ):
bp.show
if self.currentSet: self.clothes[self.currentSet]()
# Apply the change either to the whole body: obj.change( "tanned" )
# Or only to a body part: obj.change( "armLeft", "tattoo" )
def change( self, *args ):
if len( args ) == 1:
for bp in self.bodyRaw:
bp.change( arg[0] )
else:
self.bodyIndexed[arg[0]].change( arg[1] )
# An example of interface with all the body parts and clothes sets
def rotate( self, what, step ):
self.bodyIndexed[what].rotate( step )
for cs in self.clothes:
cs.rotate( what, step )
Now, note the important point:
Displaying the whole doll, clothes included, in the right order, at the right position, and with the right angle need three lines in "PaperDoll", and only one in "BodyPart" ; plus two and one for "ClotheSet" and "ClothePart".
How you'll link the parts together, how you move them, what moves are permit, is something secondary in my demonstration. The main point I wanted to address was this one.
Seven lines is all you need to display the whole clothed doll as it need to currently looks like. If your actual design need more lines than this, it's something over complicated. Not that being over complicated is bad in itself, but it turn the design into a living hell and open way more doors to breaking or subtle bugs.
And, because the way you talk about this give me the feeling that you expect to impress with this framework, over complicated code is never impressing. What is impressing is to be able to do in 50 lines, what others need two pages just to theorize it.
Sorry, but I have to stop you there.
It's just how Ren'Py is intended to be used. Reason why the lexer is directly addressable, and regularly extended outside of what Ren'Py itself need, and why the renpy.register_statement function exist. But, well, glade to see that we will finally have something else than my that will correctly extend Ren'Py.
Sorry, again, but this is ridiculous.
The ADVCharacter class is intended to handle the dialogs, and only the dialogs. Wanting to extend it is useless and the only benefit is to have only one object to deal with instead of two. But in the same time it impose constraints that are not needed.
And this is part of the reason why I have this feeling that you search to impress, more than you search to extend Ren'Py capabilities. There's really no need to extend the ADVCharacter class, especially for make it do something totally unrelated to its design and intent. At least no need except to say "hey, look what I did".
So the goal is to make it seem like a ren'py extension, expanding ren'py's functionality by staying inside the familiar ren'py development environment, working similar to how ren'py works, such as with using statements.
I'm not sure how deep you are into the code/framework of ren'py, I don't even know if renpy was coded using python or straight C like many python systems are
All in all it doesn't sound like a pipe dream, it sounds like things have slowly started coming together and you're at the cusp of a comprehensive view of how everything may work... you just need to get the different systems/sub-systems made to see if and how it can come together. Sounds super promising and impressive, even with what you've managed to explore so far.
We already have quite a few of the systems put together in a working state. Some of them need statements crafted for them still and we are continuing to identify more of the pieces needed and how to best make them available to the normal user.
Sorry to say it, but if it's a hellish and painful design, then you are doing it wrong. So, stop, move your hands far from the keyboard, and think again about what you want to achieve and what Ren'Py and Python provide you to do it.
I'm just going to address your behavior right off: you seem to be a toxic commenter seeking to overtake the thread and I have no wish to discuss with you, please do not come back to this thread with this kind of behavior. Frankly, it is completely inappropriate to approach developers with this attitude, attempting to flagrantly show off because you believe you have high knowledge and better design, even if you did, you would be the first person I would look to remove from a team because you lack social skills.
I have no reason to accept your vitriolic attack and remind developers to remain civil when interacting with each other. However, I will expound on a number of the things said in your post for the understanding of other readers.
Well, you'll have body parts, it will be your starting point.
What body parts need to be displayed ? An image, coordinate (x, y and of course z because they need to appear in the right order) and finally a rotation angle. Well, it's five variables, so your body part class don't need more than five variables at first.
Hmm... It's a bit limiting, isn't it ? It will have a dict of image, this will permit to customize the doll, giving it tan, tattoo and whatever. It also need constraints, the body parts can't rotate to the infinite.
This design is completely against the concept and out of scope. What is being described above is closer in nature to a Live2D sprite than that of a typical layered paper doll. Is there an actual need for parts of the paper doll to move and is that artistically desirable? The artists on the team have said no, nor do our requirements call for moving parts.
What is called for is a system that layers static images of the same size into a single container, is able to be controlled by variables, and if possible should accept arguments from show(). If this sounds suspiciously like Ren'Py's layeredimage statement, that would be due to layered image seeking to solve almost the same problem. You can check out that system's documentation
You must be registered to see the links
. Unfortunately, layered image was designed for a visual novel approach and includes no way to tie it's state to variables as the documentation states:
Creating this to the requirements, while using as much of the base code of Ren'Py, and crafting it for use by a normal Ren'Py user with limited or no python or coding experience is what raises the difficulty of this design. Thankfully, the Ren'Py team has given us a decent, if poorly documented, example to work from in layered image. The idea is to create pieces that are associated to a specific layer, a specific character, and a value. We believe we can take something like a single piece of clothing for a character and create a single object that represents it, using that object for each pose that a character has. We also want to represent these pieces in different states; a piece may be 'opened' or pulled 'up'. And most importantly, we need to be able to do this without knowing any information about the doll at the time of writing the code. It is very difficult to design because we need to allow creators to define their own dolls, what layers they use, how they are put together, what values they should depend on, etc, and still be consistent.
For this we decided to base this off of layered image. With this we won't be needing RevertableObject for it nor any of the usual suggestions for displaying images such as a composite image or even displayable. Instead, we will be crafting image-like displayables, wrapping them to look like an image, and holding them in a Container object, specifically a Fixed type MultiBox. What we need is an object which contains proper information for an image, which is just a valid image name or function to produce such a name, and the attribute or method _duplicate as seen in
You must be registered to see the links
. While it would be nice if this functionality was better documented, it was clearly only intended to be used by the Ren'Py team internally.
In addition to this, we should be able to quickly change a character's state for things like faces; one of the best ways to do this is to accept arguments from show(), allowing writers to change expressions without needing to call a function. Again, we can borrow heavily from how layered image implements this, and though I did consider simply using layeredimage to make this part I came to the conclusion it would still be better to be able to tie this a variable as well.
So yeah, all-in-all it is a difficult piece to design well.
Sorry, but I have to stop you there.
It's just how Ren'Py is intended to be used. Reason why the lexer is directly addressable, and regularly extended outside of what Ren'Py itself need, and why the renpy.register_statement function exist. But, well, glade to see that we will finally have something else than my that will correctly extend Ren'Py.
While yes, we are utilizing the register_statement() function, creating proper parsers and well designed statement blocks is extending Ren'Py, as opposed to the typical solution of simply doing everything in python directly for a particular game.
We are also adding a lot of functionality to Ren'Py, like an events system, and keeping these additions inline with how the Ren'Py team executed things. In general I would consider this an extension of Ren'Py.
Sorry, again, but this is ridiculous.
The ADVCharacter class is intended to handle the dialogs, and only the dialogs. Wanting to extend it is useless and the only benefit is to have only one object to deal with instead of two. But in the same time it impose constraints that are not needed.
ADVCharacter was clearly meant to be extended, and variations made of it, as we can see in both its factory method design and the manner in which it is extended for
You must be registered to see the links
. As Python, Ren'Py, and the class in question have no inherent interfaces for us to use for polymorphism, we will need to inherit ADVCharacter in order to look like an ADVCharacter. Plus, this just makes sense: our characters should have all the functionality provided by ADVCharacter anyways and there is no need to completely rewrite a character just for this. Nor would composing, or storing an ADVCharacter object inside our new character object, be desirable; we should still be able to call our character in script with just its variable and expect it to work for displaying dialogue and the character image. This makes inheritance the optimal path to giving the object for our character the ability to have things like stats, inventory, or even a wardrobe, all while maintaining compatibility with both the way Ren'Py already works and with the ease users are looking for.
(Yes, I do know about all the ways to implement interfaces in python but, Ren'Py doesn't use them and we do not want to be editing Ren'Py itself so to keep this as a drop-in module. Plus, Ren'Py often uses inheritance often in place of those methods of implementing interfaces so we will be keeping inline with Ren'Py here.)
And this is part of the reason why I have this feeling that you search to impress, more than you search to extend Ren'Py capabilities. There's really no need to extend the ADVCharacter class, especially for make it do something totally unrelated to its design and intent. At least no need except to say "hey, look what I did".
Again, I am going to call out your attacks. The behavior you are claiming here is the exact behavior you are showing with your post. The examples you crafted were meaningless to the stated requirements of this framework project and your attempt to hijack the thread obvious.
What I do hope is that the things I addressed in this post help other developers understand more about the approach we are taking with this framework and to perhaps pique the curiosity of developers into looking more into this project.
You totally missed the point.
When I said that "how you'll link the parts together, how you move them, what moves are permit, is something secondary in my demonstration", it implicitly imply that they don't need to move, and that they don't need to be independent, nor strictly to exist.
They were needed to the demonstration that, no, unlike what you said the design is not hellish. There were only four lines that was important, and even while I pointed them, you totally missed their importance.
Instead we will be crafting image-like displayables, wrapping them to look like an image, and holding them in a Container object, specifically a Fixed type MultiBox.
What the hell are you trying to do ? You mix terms that have nothing in common.
When you're talking about crafted image-like displayable, it's referring to something like:
Python:
class PaperDoll( renpy.Displayable ):
[...]
def attribute( self, *args ):
self.selectedAttributes = *args # you can also just replace at part level if you want, not too complicated.
def render(self, width, height, st, at):
retVal = renpy.display.pgrender.surface( ( self.width, self.height ), True)
for part in [ o in sort( self.bodypart, key = lambda x: x.zorder ) if o.name in self.selectedAttributes ]:
surf = renpy.display.im.cache.get( part.img )
retVal.blit( surf, ( part.x, part.y )
return retVal
[...]
# in before you discard it without reason...
def newPaperDollExecute( t ):
( doll, attributes ) = t
setattr( store.dolls, doll, PaperDoll( attributes ) )
renpy.register_statement( 'new paper doll', parse=NotShown, execute=newPaperDollExecute )
[...]
def showPaperDollExecute( t ):
( doll, attributes ) = t
getattr( store.dolls, doll ).attributes( attributes )
renpy.show( getattr( store.dolls, doll ) )
renpy.register_statement( 'paper doll', parse=NotShown, execute=showPaperDollExecute )
new paper doll girl1:
head:
default:
"images/character/girl1/head.png"
( 30, 0 )
0
smile:
"images/character/girl1/smile.png"
( 30, 0 )
0
body:
default:
"images/character/girl1/body.png"
( 0, 40 )
-1
tanned:
"images/character/girl1/body_tanned.png"
( 0, 40 )
-1
dress:
"images/character/girl1/dress.png"
(0, 30 )
30
[...]
label whatever:
paper doll girl1 dress smile jean
But then you talk about fixed multibox, what is more referring to something like:
Python:
screen doll( doll ):
fixed:
for part in [ o in sort( doll, key = lambda x: x.zorder ) if o.name in doll.selectedAttributes ]:
add part.image pos( part.x, part.y )
But, well, it's your problem, not mine. One of Ren'Py's strength is that there's always many way to achieve the same result. You've now three for the hellish design you want to achieve.
ADVCharacter was clearly meant to be extended, and variations made of it, as we clearly see in both its factory method design and the manner in which it is extended for
And as we also see by the fact that, when passed arguments, it recreate a copy of itself...
Oh wait, what am I saying. No, it show the opposite since it lost all the additional arguments you can have added, while all the additional attributes will return to their default values.
[the third and fourth lines of ADVCharacter.__call__ meta method]
Of course, strictly speaking it's not an issue here. Those additional arguments and attributes are not needed during the short time where this copy will exist and be used. Yet it's the undeniable proof that, unlike what you think and claim, the class is clearly designed to not be extended.
You struggle because you want to put a square into a round hole. You pass your time repeating that what you want to design will looks like layered images, but in the same time what you are describing is a Frankenstein monster made from pieces that don't even match.
Where have you seen that layered images are linked to a character by something else than image arguments, that is nothing more than a tag telling Ren'Py what image it need to address and will be used for a renpy.show call ? Where have you seen that they need a special way to change an attribute ? Yet it's what you describe as being your paper doll.
You want to do something similar to layered images ? Then do it like layered images are done, not by creating a ADVCharacter child that will handle both dialogs and displayables.
Again, I am going to call out your attacks. The behavior you are claiming here is the exact behavior you are showing with your post. The examples you crafted were meaningless to the stated requirements of this framework project and your attempt to hijack the thread obvious.
Sorry to say it, but if it's a hellish and painful design, then you are doing it wrong. So, stop, move your hands far from the keyboard, and think again about what you want to achieve and what Ren'Py and Python provide you to do it.
Yus!
I have seen and heard of the basic transform having some limitations, I'll have to look into this more to see how much power this dynamic transformer thingy can give me. I've seen more advance users create what is essentially a side scroller using transforms and considering I'm still exploring mechanics and environment art I've been exploring this idea as well.
Pervy Rogue Sounds like the details for both the paper doll system and adapting the ADVCharacter class sounds scary. I'm the type of simpleton dev were I hate trying to work with other people's systems. Sure I love to figure out how they work, but after that I would rather code everything from scratch. Why worry about details such as 'image like displayables' and 'fixed multi box' and trying to get various systems to work together (which as far as I know could be like pushing a square peg through a round hole, but I can't see inside the pitch black box), when instead I can just start off with clean objects/classes that cleanly mesh with one another. Sure its slow cuz I'm remaking the wheel, slow to add features that didn't already exist, but tend to be a lot easier to get working and fix issues because I'm familiar and comfortable with the system (and i can read the code... which acts as its own documentation since I like coding that seems like language), and I can modify it and rebuild it to my heart's content. Where trying to make use of an existing code or framework, its as Anne describes "Frankenstein monster," where often instead of being able to do things properly, everything has to be patched on or use work arounds, which often limits how much the system can be extended after the fact. Think of a black box, trying to put in the new round peg you just made for the secret round hole... but to get the peg in you have to reach in, get your hands around the gears and high voltage power lines, before you can slip the piece it to place, with the gears and high voltage powerlines being all the patches and unknown code that you can't mess with. But if you think you can extend ren'py while working within whatever restrictions such an endeavor may pose, I'd be super impressed just because i know its not nice working with someone else's system (since I tend to avoid it like the plauge).
Now for off topic tangent time! I could talk about my ideas for paper doll systems, or my own philosophy about code extensibility and the use of inheritance.
I will probably delete this thread in a month or so, after giving some time for the few people with questions, seeing as this thread has become about the view point of one person aggressively trying to peddle their own stuff. Unfortunately f95 has no tools for us to moderate our own threads and does not act to prevent thread takeovers.
Documentation is, like many developers, one of my bigger weakpoints; so yes, I agree with you. We'll be updating the README soon but for now I point you to the
I often think of Anne being more of a manager or senior engineer, the kind that know their stuff, but they are also the type that make for horrible professors because they will give the answer to a student's questions, but not the best at explaining it and can't understand why all the smooth brain students don't understand it. I've been part of other discussions where Anne gives the answer for why something doesn't work... and it takes the rest of us a week or two before the rest of us figure out the problem, understand it (attach 'meaning' to the words), and realize that its exactly what Anne said.
People like this are not 'managers' or 'senior', they are a detriment to teams; worse, they have incorrect information but shout loudest so others think they are correct. When called out on this, they deflect or get more aggressive. And looking through his 'tutorials' and information about renpy, he doesn't even have basic if/else trees in the correct order. It is absolutely terrible that this thread is all about him and that he keeps derailing any proper conversation with his 'examples' that don't solve anything in the given scope and that include features not desired. This individual would be removed from most teams I have worked with due to their lack of social skills and toxicity.
Sounds like the details for both the paper doll system and adapting the ADVCharacter class sounds scary. I'm the type of simpleton dev were I hate trying to work with other people's systems. Sure I love to figure out how they work, but after that I would rather code everything from scratch. Why worry about details such as 'image like displayables' and 'fixed multi box' and trying to get various systems to work together (which as far as I know could be like pushing a square peg through a round hole, but I can't see inside the pitch black box), when instead I can just start off with clean objects/classes that cleanly mesh with one another. Sure its slow cuz I'm remaking the wheel, slow to add features that didn't already exist, but tend to be a lot easier to get working and fix issues because I'm familiar and comfortable with the system (and i can read the code... which acts as its own documentation since I like coding that seems like language), and I can modify it and rebuild it to my heart's content. Where trying to make use of an existing code or framework, its as Anne describes "Frankenstein monster," where often instead of being able to do things properly, everything has to be patched on or use work arounds, which often limits how much the system can be extended after the fact. Think of a black box, trying to put in the new round peg you just made for the secret round hole... but to get the peg in you have to reach in, get your hands around the gears and high voltage power lines, before you can slip the piece it to place, with the gears and high voltage powerlines being all the patches and unknown code that you can't mess with. But if you think you can extend ren'py while working within whatever restrictions such an endeavor may pose, I'd be super impressed just because i know its not nice working with someone else's system (since I tend to avoid it like the plauge).
To be blunt: why are you using Ren'Py at all then?
This is a classic example of amateur/student/junior developer thinking and one of the great traps. Its a trap of always rebuilding the wheel because you haven't learned to work with other developers; the outcome of such development is poorer because of that stance. For example, you ask why worry about something like an 'image-like displayable' and the answer to that is simply because doing so affords us the ability to use everything that Ren'Py is offering us. Maybe you have noticed that many games restrict or disable Ren'Py's rollback feature but have you ever asked why? If you asked why you would find out that its because those developers took the same stance of reinventing the wheel and their new code no longer works with the history system, or it may not become a `node` in Ren'Py, or it can no longer be predicted correctly, or it doesn't refresh properly, or, or, or.
Why are you working in an engine if you aren't going to use it? And our project specifically states that it will be fully compatible with Ren'Py, which means that no, its not a 'Frankenstien' and no, it won't restrict anything. Written properly, as we are striving to do, it could be adopted straight into renpy without adversely affecting the engine.
That is the whole point of doing this! We seek to create a system so that other developers, most of whom have little to no programming knowledge, can use our system to create these kinds of games using the same scripting style that they are already learning in renpy.
When you go to something like Unity or Unreal, what do you do? Do you re-code the entire engine or do you adopt and build upon their code and classes? Well, if you are using their engine, you do the latter, quite literally inheriting their base classes for everything you do so that you get all the functionality they have already built! This is what we are doing with `renpy-trainer`. By inheriting `ADVCharacter` we gain not only everything for utilizing the say screen, we also gain the history system, prediction, display tags, etc. All the things we want to have with our characters we can have and without needing to reinvent anything or copy any code.
Plus, by utilizing an 'image-like displayable' we forgo the need to write our own render, which in turn means that we reduce the number of renders being performed on our paper-doll: Ren'Py's system cycles screens often:
"
You must be registered to see the links
"
Ren'Py will run a screen multiple times, as it deems necessary. It runs a screen as part of the image prediction process, before the screen is first shown. As a result, if a screen has side effects, those side effects may occur at unpredictable times.
Because of this behavior, Ren'Py will always re-render those homebrew classes that have been proposed. But, by utilizing the method I described before, our image will only update when needed or when we specify, in part because we are using `_duplicate()` instead of `render()`. Thus, when screens containing our paper doll are active and being re-run by the engine, it will treat our paper doll as a static image and thus not subject to being re-built multiple times per frame.
None of this is meant as a quick and dirty solution to a single problem. By integrating everything with Ren'Py properly, we avoid the issues most developers seem to have with those 'pure python' solutions. Nothing is restricted by adding such a framework except maybe some naming being reserved for the framework.
Now for off topic tangent time! I could talk about my ideas for paper doll systems, or my own philosophy about code extensibility and the use of inheritance.
Again, why are you using Ren'Py? You are certainly not the first person to come to me with all this animation stuff but it still doesn't make sense. Ren'Py supports old-school style animating where you show one image, then another, and so on; and it supports Live2D. If these do not meet your requirements, find a tool that does. Unity for example.
`renpy-trainer` does not, and will not, seek to add animation mechanics to this visual novel engine. A functioning paper-doll system, which renpy already has a basic version of via `layeredimage` is completely supported by the layered nature of Ren'Py. But please remember, Ren'Py is not a fully featured game engine nor will it ever be. Its a great introductory engine to making simple games, which is the whole reason so many of these porn game are made in it. But a fully-featured game engine will never be made in Python due to the overhead of using an interpreted language.
Dynamic variable network what? Look, this is probably simpler design wise than you are thinking and here is our solution: The user sets things up via a doll statement. Its really that simple in design, let creators tell us what layers and in what order make up a given doll, done. We have the creator/user use a `doll` or whatever statement. That statement has some parts to it, starting with deciding if its a general doll or specific to a character, then an optional keyword for poses so we can craft additional dolls for each pose, then a set of layer statements from bottom layer to top layer, each layer having additional parts.
Essentially you tell us what doll this is, what type this is, is this a pose for a doll, what layers and in what order they are for the doll, what variable to use for each layer, what naming format you want to use (or our default), and everything will accept tranforms as well since all we have to do is pass those along. Programming the CDS for all of this just takes time and a lot of logic work.
First off, Python does not natively support the concept of Interfaces. Secondly, while we do want to use composition when possible, that does not equate to never inherit. I have already describe above what we are getting by inheriting 'ADVCharacter`; mind you, we would not get those benefits through just composition as yes, we do want to use polymorphism here and have our new class be seen as an `ADVCharacter`, which is the intended manner of making a new character class as seen with `NVLCharacter`.
Lets look at how a 3D game engine works, something like Unreal since I've already mentioned the other U twice. In Unreal, what is almost everything in the 3D space? Its an `Actor` which is a class, a class you often inherit and in fact UE documentation often starts by making a new class of type `Actor`. Why is this the method of adding anything to Unreal though? Thats pretty simple: its because that is what gives you access to the engine! All the methods and required data fields for damn near anything in the game space is right there in the Actor class.
Game engines are meant to be extended. They provide the basics, you inherit that and then build upon them. Can you make your own? Of course. But then, why are you bothering to use the game engine if you aren't going to use anything in it?
Overall, Saki_Sliz, I really do appreciate your interest and questions, I am more than happy to explain the thought and design of what we are trying to do as well as to take constructive, thoughtful criticism. So jump onto our discord and ask away! But I am annoyed and thoroughly fed up with how off track this thread became thus I will likely be deleting it in the not so far future.
I took a look and unfortunately, it does not fit our needs. However, it has some great stuff in there and is far better developed than a lot of renpy solutions I have seen. Thank you for linking it lobotomist!
Yes, unfortunately forum posts can be both a boon and a bust at times. Though it was fun to talk a bit of code, I didn't see a section on the discord server that really went into this topic.
Considering how off topic things went, looking at the initial post, I'm guessing you more or less wanted to introduce the project you/you guys have been working on, sort of a project landing page.
I've seen some games have a main post for their game, where rando's can talk, and a separate dev thread, but in both cases the threads are just long chains of conversations overtime (like what I'm doing right now), not really kept clean, so forums act as a poor landing page. Some dev's go as far as making websites, but that's a whole endeavor on its own. The only time I've seen good landing pages is when a project can defer a lot of the conversations to its own subform, but one can't simply set a forum up. Discord servers do have some similarity to forums for organizations, but you may need a new server (sub server? channel?) just for the "Ren'Py-Trainer Framework" once it gets released as its own topic for discussion (like what you tried to do here). But as I mentioned I don't see much on the server other than a link to this post.
Until then, I've seen some devs make mock home pages for projects using google docs or sheets, something static that they can show off but prevents people from adding off topic comments, a basic form of moderation, as you mentioned is missing from forum sites. I don't know if I've ever seen forums implement good moderation to users with in their own posts.
Best of luck, I'll keep tabs on updates from the server
Yes, unfortunately forum posts can be both a boon and a bust at times. Though it was fun to talk a bit of code, I didn't see a section on the discord server that really went into this topic.
Considering how off topic things went, looking at the initial post, I'm guessing you more or less wanted to introduce the project you/you guys have been working on, sort of a project landing page.
. . .
Best of luck, I'll keep tabs on updates from the server
To be able to see more, including our dev section, you have to at least make a post or two in the discord and be assigned a role by the bot. More than half the discord server is hidden.
Yes, this thread was intended to be solely about the project, its goals, and any features requested for implementation. Really something just to see if other developers would be interested in a module for Ren'Py that would enable them to make these kinds of games faster and simpler without the need to know actual programming, OOP, and things like that.