(SOLVED!) How to make User Interaction have precedence over SpriteManager event?

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
SypherZent
Veteran
Posts: 362
Joined: Fri Sep 02, 2016 3:14 am
Completed: Multiverse Heroes, Space Hamster in Turmoil
Location: Puerto Rico
Contact:

(SOLVED!) How to make User Interaction have precedence over SpriteManager event?

#1 Post by SypherZent »

Edit: I've been able to solve two other minor issue, but I still need help with this one.

User clicks do not have precedence as the Engine queues the Logic from its events.
However, if I modify a script with Reload on, Reloading is absolutely instant.
This means that Python is running fine, and it's not a Processing or RAM issue (game runs at less than 256 MB RAM).

Image

Ren'Py's internal way of queueing what it's going to show on screen, and the fact that it's doing update method's Logic faster than showing things, for some reason, takes precedence over User clicking buttons on a screen, and also takes precedence over user clicks in the SpriteManager's event.

It does not take precedence over Reloading the game, even if the sprites remain battling for a few seconds as Ren'Py begins to reload.

I don't really want to go hacking into Ren'Py itself, searching for the way it Reloads and somehow using Python to intercept this.
I'd very much prefer a Ren'Py-friendly way of giving the User's clicks precedence over queued events to be displayed.

Any help would be appreciated. It has been a few days.


---

Original Post

I'm having an issue where SpriteManager's update event running at 0.03 is queueing many things, and it lags response on UI buttons.
This only happens during the real-time combat phase.

I've already tried both of these methods:
A) Disabled image prediction
B) Enabled image prediction

Nothing changed.
My current, only solution is to simply remove the buttons (Pause and Speed Control) as nothing else is affected, which I would prefer not to do.
I'd like to give the player these options.


I'm still optimizing my custom Python, but this is the very first issue I've had with Ren'Py, in terms of clicking and responsiveness.
I feel like I am missing a simple detail. Perhaps something to do with ATL and SpriteManager? I am using both.

Everything is actually performing fine (extremely well, really impressed with the Engine tbh).
It just seems Ren'Py is queueing too many events to attend my click.
I was able to predict images properly. Tried turning them off.
The game is still lagging over 5-10 seconds before processing my clicks on simple buttons (like Pause) during Combat.

And it's only these buttons with issues. Nothing else lags.
I'd like to override whatever Ren'Py has queued when I click these buttons, without dropping Ren'Py's queue of activity for the sprites / spritemanager (so that battle outcomes are not affected...currently everything is balanced and working nicely).

Is there any other option available, that maybe I have missed?


Thanks,
SZ


Edit to Add:
Updated to Ren'Py 6.99.14.3135. Didn't help, sadly.
Last edited by SypherZent on Thu Feb 08, 2018 6:47 pm, edited 7 times in total.

User avatar
Remix
Eileen-Class Veteran
Posts: 1628
Joined: Tue May 30, 2017 6:10 am
Completed: None... yet (as I'm still looking for an artist)
Projects: An un-named anime based trainer game
Contact:

Re: Possible to Intercept SpriteManager for User Interaction?

#2 Post by Remix »

The predict parameter should hold the name of a function that returns a list (or set/tuple) of displayables...
When Ren'py looks ahead in the script (aka predicts) it calls the visit method of the displayable (in this case SpriteManager) and shuffles as many of the returned displayables into the cache as will logically fit.
The predict->visit->cache should be used wherever possible - do not turn that off - do not return an empty list - make sure it returns All images used and not just the ones at the start (i.e. If a Sprite changes from a defense pose to attack pose the list needs to contain both... for every sprite)

It concerns me a bit that you mention ATL along with SpriteManager... Care to elaborate? (It may be better to use a CDD or CDC instead. SpriteManager is mostly for movement and full image changes)
Frameworks & Scriptlets:

User avatar
SypherZent
Veteran
Posts: 362
Joined: Fri Sep 02, 2016 3:14 am
Completed: Multiverse Heroes, Space Hamster in Turmoil
Location: Puerto Rico
Contact:

Re: Possible to Intercept SpriteManager for User Interaction?

#3 Post by SypherZent »

For now, I ended up removing the buttons, and adding a secondary screen (invisible to user) to catch all excess clicks that were queued, so that they don't skip the Victory screen after combat.

I was able to solve SpriteManager and load up the sprites, too. ^^
The sprites are now predicting properly, but it did not solve the delay with the buttons.

I have a pre-optimization video available to show how I am using ATL with SpriteManager.

When the Wrench is thrown, and when the Knight's shield expands momentarily, that is the ATL transforming the sprites.
It's possible for me to write those in custom Python.
Do you think that may be the cause? :O

(Combat starts around 3:35)



Also, thanks for your answer, Remix!
Still exploring options on this, as I'd like to include those buttons and not leave them out.

Edit: Thinking on this more deeply, the ATL doesn't proc so often, and the lag in responsiveness is present from the beginning of the match.
Makes me feel like it is something else entirely that I'm missing. :S
The lag is also worse with more units on field.
Possibly it's just a need for optimization and higher time, instead of 0.03?
I might end up trying this next, since the first optimization improved responsiveness, but only slightly.
Let me know if anything comes to mind. Any and all info helps, as it gives me leads on what to attempt next.
Creator of Multiverse Heroes & Space Hamster in Turmoil

Want me to code your game?
Check my services thread!

User avatar
SypherZent
Veteran
Posts: 362
Joined: Fri Sep 02, 2016 3:14 am
Completed: Multiverse Heroes, Space Hamster in Turmoil
Location: Puerto Rico
Contact:

Re: How to make User Interaction have precedence over SpriteManager event?

#4 Post by SypherZent »

I am bumping this, as it has been 12 days and I still need help.
12 days may not sound like a lot, but I am about to release this game in 1-2 weeks.

Also, time is relative to Consciousness and Perception.
For me, 12 days is an eternity (I work 180-192 hours in 12 days).

Any help is appreciated.
Creator of Multiverse Heroes & Space Hamster in Turmoil

Want me to code your game?
Check my services thread!

User avatar
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: How to make User Interaction have precedence over SpriteManager event?

#5 Post by PyTom »

It's not clear that there's an answer to your question. 6.99.14.1 should improve certain things. Beyond that, you may need to change your game to do less work.
Supporting creators since 2004
(When was the last time you backed up your game?)
"Do good work." - Virgil Ivan "Gus" Grissom
Software > Drama • https://www.patreon.com/renpytom

User avatar
SypherZent
Veteran
Posts: 362
Joined: Fri Sep 02, 2016 3:14 am
Completed: Multiverse Heroes, Space Hamster in Turmoil
Location: Puerto Rico
Contact:

Re: How to make User Interaction have precedence over SpriteManager event?

#6 Post by SypherZent »

Excellent! I saw the update on 6.99.14.1 and I have high hopes for it. :D

It's not the worst issue. Overall, I cannot place a Pause button during combat.
However, combat doesn't generally last longer than 30 seconds.
It's doing perfect, otherwise, and I don't think players will even notice, as there's nothing to click.

Reprogramming the flow is an option, but it would make it closer to turn-based, in terms of processing.
Currently, I really love the setup of real-time, where every unit has a shared timer and all attack at once (hence so many events queued).

So, I guess it is a balance thing.
I will close this for now, and work with what I have. ^^

Also, for next games, I will be way below this amount of logic between event_timer loops, now that I know its extent.
It's a pretty vast limit...

Also, I felt a difference after optimizing a few of my custom Python functions, so I will delve into that further, once game is completed.
I believe that will solve the trick, as I've been pretty lazy about the whole processing and being nice about how I construct ifchecks.
Sort of taking it for granted...Lol.

Thanks a ton for the reply and the update, PyTom!

6.99.14, overall, has displayed significant improvements for my developments, so I am excited for *.1 :D.
Will check it out in the morning with a fresh mind. ^^

User avatar
SypherZent
Veteran
Posts: 362
Joined: Fri Sep 02, 2016 3:14 am
Completed: Multiverse Heroes, Space Hamster in Turmoil
Location: Puerto Rico
Contact:

Re: (SOLVED!) Very particular ATL transform and SpriteManager conflict

#7 Post by SypherZent »

Bumping this to post my solution.

I have a comprehensive understanding of this problem, now, and I'd like to share.

This is the problematic code, below.
Please note, this is a class in Python, that has an "update" function called in the SpriteManager update loop.

Also note, this issue with transforms is exclusive to using them in this particular manner, in SpriteManager.
I had not run into this before, and I have used transforms on other occasions.
So, this is not a common problem (well, just look at it LOL).

Code: Select all

# In my combat.rpy
    class BulletSprite(renpy.Displayable):
        def __init__(self, xpos, ypos, offset, shooter, target, type, large=None, force_dest=None):
            self.shooter = shooter
            self.allied = shooter.allied
            self.sprite = get_sprite_by_class(large)
            self.show = manager.create(self.sprite)
            #...

        def get_sprite_by_class(self, large):
            #...
            if self.shooter.hero == "Blacksmith":
                ssprite = (blacksmith_hammer if not large else blacksmith_lg_hammer)
                if not self.allied:
                    return At(im.Flip(ssprite,True,False),rotating_rev) # <--- PROBLEM
                return At(ssprite,rotating) # <--- PROBLEM


# In my transforms.rpy
transform rotating:
    linear 1.0 rotate 360 #<--- PROBLEM
    repeat

transform rotating_rev:
    zoom 0.5
    linear 1.0 rotate -360 #<--- PROBLEM
    repeat

The solution lies in -> Not Using ATL transforms with linear interpolation <-

The linear call in the transform manifests the following problems:
1) Ren'Py locks up, and User cannot click to interact, for many seconds (it continues stacking / snowballing through more calls, but game still flows).
2) Framerate accelerates to seemingly 100 fps (hard to tell without gauging it, this is just a guesstimate).
3) After the transform ends (sprite is gone) speed goes back down to normal 30/60 fps (whatever user had, probably 30).


Here is the exact solution, including the image that is being read by the crops, to emulate rotation.

Code: Select all

# In my combat.rpy
    class BulletSprite(renpy.Displayable):
        def __init__(self, xpos, ypos, offset, shooter, target, type, large=None, force_dest=None):
            self.shooter = shooter
            self.allied = shooter.allied
            self.sprite = get_sprite_by_class(large)
            self.show = manager.create(self.sprite)
            #...

        def get_sprite_by_class(self, large):
            #...
            if self.shooter.hero == "Blacksmith":
                self.curr_frame = -1
                self.frames_list = (DYNAMIC_FX["Hammer Large"] if large else DYNAMIC_FX["Hammer"]) #<--- SOLUTION
                return DynamicDisplayable(self.animate_frames)

        def animate_frames(self, st, at):
            if self.curr_frame == len(self.frames_list)-1:
                self.curr_frame = -1
                this_frame = self.frames_list[self.curr_frame]
            else:
                self.curr_frame = self.curr_frame + 1
                this_frame = self.frames_list[self.curr_frame]

            if not self.allied:
                this_frame = im.Flip(this_frame,True,False)
            return this_frame, store.current_speed


# In my dictionaries.rpy
init python:
    DYNAMIC_FX = {
        "Hammer": [
            im.Crop("fx/hammer.png",(4,4,32,29)),
            im.Crop("fx/hammer.png",(39,2,33,29)),
            im.Crop("fx/hammer.png",(73,2,30,33)),
            im.Crop("fx/hammer.png",(108,1,30,34)),
            im.Crop("fx/hammer.png",(142,3,31,32)),
            im.Crop("fx/hammer.png",(175,4,34,30)),
            im.Crop("fx/hammer.png",(210,4,33,30)),
            im.Crop("fx/hammer.png",(246,2,29,34)),
            im.Crop("fx/hammer.png",(283,3,29,33))
        ],
        "Hammer Large": [
            im.Crop("fx/hammer_lg.png",(8,8,64,58)),
            im.Crop("fx/hammer_lg.png",(78,4,66,58)),
            im.Crop("fx/hammer_lg.png",(146,4,60,66)),
            im.Crop("fx/hammer_lg.png",(216,2,60,68)),
            im.Crop("fx/hammer_lg.png",(284,6,62,64)),
            im.Crop("fx/hammer_lg.png",(350,8,68,60)),
            im.Crop("fx/hammer_lg.png",(420,8,66,60)),
            im.Crop("fx/hammer_lg.png",(492,4,58,68)),
            im.Crop("fx/hammer_lg.png",(566,6,58,66))
        ]
    }
Image
Image


Please note, once I fixed this, User Interaction is instantaneous, and I have not optimized the code.

What I thought was Ren'Py's processing "ceiling", was only the entrance to the building.
I have yet to scrape the limits of Ren'Py.
I feel like this opens a whole new world of exploration.
Must...make...more...complex...A.I....

Anyway, I do not think many will run into this issue, unless using Python and SpriteManager and Transforms with timed interpolations.
But I do leave this here, in case someone runs into a similar issue.


SZ
Creator of Multiverse Heroes & Space Hamster in Turmoil

Want me to code your game?
Check my services thread!

Post Reply

Who is online

Users browsing this forum: Google [Bot], Semrush [Bot]