I have been working a lot on making revisions to the Kuroi Games manga engine and it got me thinking about the ATL. It seems that while the Renpy script system works really well for most games, the majority of the more heavy modding of Renpy to create things such as battle engines, manga systems (like mine *shameless plug*), ect... must be doing using python. However, since there is no way to create ATL code programatically, I fear that in the long run the more python heavy projects may lose out on some of the more shiney features enabled by the ATL.
I'm not ready to say that this is a problem but I'd like to hear other people's thoughts on the manner. Perhaps it's not an issue at all and there are some very inventive ways to use the Transform function which would enable it to do everything that the ATL does or something like that.
Anyway, does anyone else have thoughts about this?
the effect of ATL on Renpy customisation
- kuroi
- Regular
- Posts: 129
- Joined: Fri Jun 29, 2007 10:50 am
- Location: Albuquerque, New Mexico, USA
- Contact:
the effect of ATL on Renpy customisation
President, Planner, and Programmer for Kuroi Games!
- PyTom
- Ren'Py Creator
- Posts: 16096
- Joined: Mon Feb 02, 2004 10:58 am
- Completed: Moonlight Walks
- Projects: Ren'Py
- IRC Nick: renpytom
- Github: renpytom
- itch: renpytom
- Location: Kings Park, NY
- Contact:
Re: the effect of ATL on Renpy customisation
Anything you can do with ATL, you can do with Transforms, using an appropriate Python function. This is 100% guaranteed, as ATL actually uses Transform internally to do its thing.
Now, it might be easier to do something in ATL than in Python. But that's the whole point of ATL, making this sort of thing simpler and more flexible. I'll also note that ATL transforms can take parameters. It's hard to think of code-generated ATL that wouldn't conform to a fairly strict template, such that one can get away with parameterized ATL.
Now, it might be easier to do something in ATL than in Python. But that's the whole point of ATL, making this sort of thing simpler and more flexible. I'll also note that ATL transforms can take parameters. It's hard to think of code-generated ATL that wouldn't conform to a fairly strict template, such that one can get away with parameterized ATL.
Supporting creators since 2004
(When was the last time you backed up your game?)
"Do good work." - Virgil Ivan "Gus" Grissom(When was the last time you backed up your game?)
Software > Drama • https://www.patreon.com/renpytom
Re: the effect of ATL on Renpy customisation
...and lint complains about them, thinking transforms with parameters are actually functions it can't evaluate.PyTom wrote:I'll also note that ATL transforms can take parameters.
Re: the effect of ATL on Renpy customisation
Since it hasn't actually been mentioned yet: yes, you use the 'function' parameter of the Transform object to do pretty much all the cool functionality you can write in ATL statements.kuroi wrote: Perhaps it's not an issue at all and there are some very inventive ways to use the Transform function which would enable it to do everything that the ATL does or something like that.
If you want to have a thing which fades in over the course of the first second, and then moves to the right from xpos=200px to 400px over the course of the next second, you could write your transform function to look something like (off the top of my head) this:
Code: Select all
def myTransformFunction(tran, st, at):
if (st >= 0 and st <= 1):
tran.alpha = st
return 0
elif (st > 1 and st <= 2):
tran.xpos = 200 + ( (st - 1) * 200)
return 0
return 999999
myTransform = Transform(xpos=200, function=myTransformFunction)
Code: Select all
transform myTransform:
xpos 200
alpha 0.0
linear 1 alpha 1.0
linear 1 xpos 400
The problem here is that the documentation doesn't really make this particularly clear, and in fact includes statements like "There is no way to create ATL code programatically", which gives people the opposite impression. (I know it's not what you meant, but it's how a lot of people are likely to read it, IMO.)PyTom wrote:Anything you can do with ATL, you can do with Transforms, using an appropriate Python function. This is 100% guaranteed, as ATL actually uses Transform internally to do its thing.
Unless I'm missing something quite drastic, the only way to do most of the cool stuff with Transform is by implementing your own transform functions, but the documentation doesn't really make it clear how to use that facility.
- When exactly will the transform's function will be called? Will it definitely be called with an st of 0 when the Displayable is first shown? Will it definitely be called when the Displayable is first hidden and have a chance to delay the hide? We presume that the answer to these questions must be 'yes' only if we've already been told that the Transform method can do everything ATL can, but the docs only say 'before the Transform is rendered', which doesn't even account for the 'hide' case at all.
- How does one then subsequently get their Transform hidden again? Is it just by setting hide_request to True and hide_response to True? Can one do this even if no hide statement or call to renpy.hide was made, to remove an item from the scene list?
How should one return from the transform function if the transform is effectively finished, if '0' makes it render again next frame? I used a very high number in the example above, but maybe -1 would be more appropriate? It doesn't say.
- How should the Transform's 'child' member be used? Is it possible to put another Transform in there and if so, what happens? I know the answers to these last two questions only because I was curious and tried it, but the correct answer isn't even implied in the docs for the second one of those.
If the answers to any of those questions are actually written in the docs, I didn't see them.
Something I still don't know about Transforms: when someone writes a complex ATL transform involving show and hide events and timed property modifications and so on, do you have a stock of plug-together functions that you construct and pass in, or do you do code generation to create a function on the fly which fulfils their requirements? I expect it's probably the latter, because after a bit of flexibility it possibly becomes the simpler thing to write, but if it's the former, is there any reason other people shouldn't use the same functions for their programmatically-generated Transforms?
And presuming you're using code generation or some other internal trick, it's still not really that plausible to programmatically-generate transforms, because you can't take parameters or user input or situational state and generate a transform that does cool ATL stuff dependent on that, because you have to write a function which does exactly what you want. (Well, you could get away with it by using a lot of generic methods and some currying, I expect, but that's a long way beyond most amateur programmers' abilities.)
Server error: user 'Jake' not found
- PyTom
- Ren'Py Creator
- Posts: 16096
- Joined: Mon Feb 02, 2004 10:58 am
- Completed: Moonlight Walks
- Projects: Ren'Py
- IRC Nick: renpytom
- Github: renpytom
- itch: renpytom
- Location: Kings Park, NY
- Contact:
Re: the effect of ATL on Renpy customisation
Yes, in both cases. In the latter, there's the hide_request/hide_response method. (This has been augmented in 6.11 to have a replaced_request/replaced_response pair, as well.)Jake wrote: - When exactly will the transform's function will be called? Will it definitely be called with an st of 0 when the Displayable is first shown? Will it definitely be called when the Displayable is first hidden and have a chance to delay the hide? We presume that the answer to these questions must be 'yes' only if we've already been told that the Transform method can do everything ATL can, but the docs only say 'before the Transform is rendered', which doesn't even account for the 'hide' case at all.
Yes. Setting them to True will cause the Transform to stop rendering, and it will be automatically removed at the end of the interaction.- How does one then subsequently get their Transform hidden again? Is it just by setting hide_request to True and hide_response to True? Can one do this even if no hide statement or call to renpy.hide was made, to remove an item from the scene list?
None.How should one return from the transform function if the transform is effectively finished, if '0' makes it render again next frame? I used a very high number in the example above, but maybe -1 would be more appropriate? It doesn't say.
It actually shouldn't be used directly, but set_child should be used.- How should the Transform's 'child' member be used? Is it possible to put another Transform in there and if so, what happens? I know the answers to these last two questions only because I was curious and tried it, but the correct answer isn't even implied in the docs for the second one of those.
I am in the process of updating the docs, and hopefully I'll get this written up correctly. I do find this sort of feedback valuable - even if I don't get to it right away, it does slowly improve Ren'Py over time.If the answers to any of those questions are actually written in the docs, I didn't see them.
ATL actually works the same way as Ren'Py. We build up a syntax tree, and then traverse that syntax tree in order to evaluate the code. There's some fun stuff when it comes to the way that state is preserved between transforms, but it's fundamentally just a syntax tree.Something I still don't know about Transforms: when someone writes a complex ATL transform involving show and hide events and timed property modifications and so on, do you have a stock of plug-together functions that you construct and pass in, or do you do code generation to create a function on the fly which fulfils their requirements? I expect it's probably the latter, because after a bit of flexibility it possibly becomes the simpler thing to write, but if it's the former, is there any reason other people shouldn't use the same functions for their programmatically-generated Transforms?
I don't really want to document the details of the syntax tree, because I consider them to be an implementation detail rather than an API. I don't want to be stuck supporting the particular details into the future. (At some point, I may actually move to code-generation.)
One good way to do this is a Python object with a call method. I'm still not sure what generated-ATL can do that parameterized-ATL can't, however. If there was something, I'd consider extending ATL to address it.And presuming you're using code generation or some other internal trick, it's still not really that plausible to programmatically-generate transforms, because you can't take parameters or user input or situational state and generate a transform that does cool ATL stuff dependent on that, because you have to write a function which does exactly what you want. (Well, you could get away with it by using a lot of generic methods and some currying, I expect, but that's a long way beyond most amateur programmers' abilities.)
Supporting creators since 2004
(When was the last time you backed up your game?)
"Do good work." - Virgil Ivan "Gus" Grissom(When was the last time you backed up your game?)
Software > Drama • https://www.patreon.com/renpytom
Re: the effect of ATL on Renpy customisation
Sorry, I used the wrong word - I actually meant the 'child' parameter to the initialiser. (Which one presumes is meant to be used, since it's a parameter to the initializer... ;-)PyTom wrote: It actually shouldn't be used directly, but set_child should be used.
"Be dynamically generated from code" is the main thing, honestly. For example, in the battle engine I'm writing, I want to draw a guy moving from one square to another square over the actual square-to-square route taken... and at each step, he might change to a new animation (to show him walking in the new direction) which possibly-but-not-guaranteed has a transitional animation to show him rotating or whatever.PyTom wrote: I'm still not sure what generated-ATL can do that parameterized-ATL can't, however. If there was something, I'd consider extending ATL to address it.
If I knew exactly the path which character is going to take with what pan offset before runtime, I could easily encode this in an ATL transformation, leaving the main Ren'Py thread free to go off and do other things while he's walking. I could theoretically write code which performs this complex arrangement of movements and sprite changes in a Transform function at runtime, but I don't think I could do it with an ATL statement since I don't think there's any way I could encode the route the guy's taking as a parameter and actually make use of it. And honestly, I don't think it's worth trying to extend ATL to include stuff like that, you'd just end up having to create another turing-complete language for a tiny fraction of potential uses.
(And as it happens, I want to break the movement down into steps anyway, so other Fighters have the opportunity to interrupt a guy's movement with reaction-fire or whatever, so I'm happy enough to be doing it step-by-step in code anyway.)
Server error: user 'Jake' not found
Who is online
Users browsing this forum: No registered users