(Solved) Correct way to close SpriteManager?

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) Correct way to close SpriteManager?

#1 Post by SypherZent »

----- SOLVED -----

This whole issue was due to one line. All my fault. xD
Basically, I was using renpy.hide_screen instead of renpy.hide to close the SpriteManager which is shown using:

Code: Select all

renpy.show("testname", layer="events", what=manager)
When using hide_screen on the testname tag, it silently fails (which is probably a good thing since people may add redundant hiding to ensure screens are not shown, when not tracking every screen).

In the end, I always assumed this worked, and my code is relatively large by now (5000+ lines), so it was a difficult thing to spot, lol.

Thanks again, PyTom, for taking the time and having the patience with me!


----- ORIGINAL POST -----

Hello,

What is the proper way to close a Creator Defined Displayable running multiple sprites with SpriteManager?

I have used renpy.end_interaction, but it takes me back to the Start Game screen and I can't find where it is in the control, since it is not reading any of my code after result = ui.interact().

I have other screens setting a variable to False when buttons are pressed, and that variable, when False, is what calls renpy.end_interaction within the event function of the SpriteManager.

I am loading the SpriteManager using:

Code: Select all

    python:
        manager = SpriteManager(update=t_update, event=t_event)
        renpy.show("testname", layer="events", what=manager)
        # Run the Interaction System
        result = ui.interact()

    if result:
        jump map_scrn
Am I overlooking something, perhaps?
In my event:

Code: Select all

    def t_event(ev, x, y, st):
        if store.safeguard:
            store.safeguard = False
            renpy.end_interaction(True)
            return
Hope this is a simple one.
Thanks for taking the time. ^^
Last edited by SypherZent on Mon Feb 20, 2017 8:57 pm, edited 4 times in total.
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: Proper way to close UDD / SpriteManager

#2 Post by PyTom »

At the end of the event method, return True (or some other non-None value) to get out of the interaction.
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: Proper way to close UDD / SpriteManager

#3 Post by SypherZent »

Hmm. The event continues to run, registering all clicks in other screens.

Code: Select all

    def t_event(ev, x, y, st):
        if store.safeguard:
            store.safeguard = False
            renpy.end_interaction(True)
            return True
Changing return to return True does not work for me.

Everything past this block continues to run even after everything has visibly closed properly.
This block actually does run, and turn safeguard off because it's the only thing that can turn it off.

My next screen and everything loads.
My problem is this t_event keeps running and processing clicks after that end_interaction(True) and that return True run.
Also, it never goes back to the lines after result = ui.interact() in script.
It just takes me to Start Game screen.

I don't really want to leave this event running 24/7 with safeguard enabled to keep it from processing, because I will know it's there...in the background...processing nothing over and over and over, and that will really hurt my OCD. xD

Is there a proper way to close this?

Is there a difference that the return True is at the last line?
If so, then why would the other lines run past this return to make that a difference?
If not, then this did not work for me. Reason unknown, everything else works fine.

I can even enable safeguard perpetually as I mentioned, but this is bad practice IMHO as there will be more events.
It would be convenient if using "scene" in script cleared UDD / SpriteManager as it does other screens.
Maybe I grew too reliant on it. :/ I have been stuck on this for a few days, though. Help appreciated.

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: Way to close SpriteManager? end_interaction not working

#4 Post by SypherZent »

Is there a way for ui.interact to stop referring to the SpriteManager interaction, and instead be targeting Screens in the new language that have been called after the SpriteManager has been displayed?

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: Way to close SpriteManager? end_interaction not working

#5 Post by PyTom »

What do you mean by closing it? What you want to do is to hide it once it's finished.

Actually, nowadays, you probably just want to include it in a screen.

Code: Select all

screen managerscreen():
    add manager

call screen manager
if _result:
    ...
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: Way to close SpriteManager? end_interaction not working

#6 Post by SypherZent »

Hmm. I see.

Basically what I mean by "close" it is that I want the t_event to stop running once this displayable has been hidden.
It's just not stopping.

I've had to enable a safeguard variable that only unlocks when the sprites appear.
After destroying the sprites and clearing all my lists and hiding the screens, this t_event still processes every click in other screens.

With the safeguard variable I just make it return, but I know it's still processing the clicks as it crashes without the safeguard due to lists now being empty (as those sprites have been destroyed and the lists have been cleared).

I think perhaps I am just destroying sprites and not properly stopping this event from running.
With my current method, I can load the event, leave and come back, and it works but it needs safeguard and t_event stays running forever after it is called the first time (I presume t_update keeps running, as well, but it just returns if the main list is empty).

Any explicit way of making the events of the SpriteManager stop running?

Code: Select all

manager = SpriteManager(update=t_update, event=t_event)
I haven't tried calling the manager from a screen yet.
Will that make a difference for this particular issue?

Thanks for the help!

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: Way to close SpriteManager? Event/update stay running.

#7 Post by PyTom »

t_event can't run when the manager is hidden, so I'd check to make sure you're actually hiding it properly.
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: Way to close SpriteManager? Event/update stay running.

#8 Post by SypherZent »

Ack, for me it's not functioning that way.

Whenever I use any of the following:
-ui.returns(True)
-return True
-renpy.end_interaction

It closes my entire game, sending me to Start Menu. None of these work properly for me.
I may need to go through the source for ui.interact itself, just to understand it, as it seems to be confused about the context.
After renpy.end_interaction, if I just MOVE my mouse, it closes everything and sends me to Start Game.

Even after properly loading the next screens.

Not only that but the t_event still runs...even after sending me to Start Menu.
For now my safeguard is functional, RAM stays below 300MB and it doesn't seem to infinitely stack more t_events as I leave/re-enter zones.
Of course I am assuming RAM would go up if multiple t_events were running and kept stacking.
Please correct me if I am wrong.

It would be very helpful if I just had an example that shows how to properly close a UDD / Spritemanager, call new screens, close screens and re-open the UDD / Spritemanager, close the UDD / Spritemanager, and re-open screens, all while appropriate ending t_event and t_update which never stop running.

I have found absolutely no information on this. Not in cookbooks, not in source code for other games.
Not even in the threads here which I scour fairly often using all forms of search engine functionality at my disposal, whether in-site or in google using site:

Essentially whenever I show my tile engine, t_event and t_update begin running.
They just -never- stop after that. I have to use a variable to prevent them from processing information.
There is a video available in my KIGAEA Tactics WiP, of how everything is functioning smoothly with the safeguard.
RAM is still at less than 300MB and it doesn't seem to keep stacking new instances of t_event and t_update.

However, I would love to solve this 'issue' properly. I don't like 'not knowing' how to turn things off properly, like the t_event and the t_update.
I even tried redefining the manager variable so it no longer carries data for the SpriteManager instance.

Is there anything that you can think of that could cause this erratic functionality?

Note: When I return True, the control does not go to my if result: check.
I cannot even pinpoint where the control in the script goes after running end_interaction.
It does not process anything I program after result = ui.interact()

Do I need to use call_in_new_context anywhere?
The example would be most helpful, anyone who could provide one.

Even if it is RhythmD game by xela, with a button to close it and go to a script, and then reopen and then close, showing how the script functions properly all the while properly closing and opening the UDD / Spritemanager so that t_event and t_update stop running when script runs.
Would ideally like to know how to close it from a different Screen's button, as well as from its own t_event.


I have not yet attempted to call this from a screen. Will that make a difference in terms of shutting manager off?
Thanks for taking the time, and sorry for being a pain. :S
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: Way to close SpriteManager? Event/update stay running.

#9 Post by PyTom »

There's a good example of a CDD in the Ren'Py tutorial.

Really, you're at the level where if you want help, you should be posting code - ideally, a small standalone game that exhibits the problems in question. Not only will that let us give you advice on how to fix it, often trying to extract the code that causes the problem is enough to help you figure out what the problem is.
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: Way to close SpriteManager? Event/update stay running.

#10 Post by SypherZent »

Code: Select all

label do_zone:
    python:
        # Sprite Lists
        manager = SpriteManager(update=tiles_update, event=tiles_event)

        # Retain Data and Prevent Rollback for this Interaction
        renpy.block_rollback()
        renpy.retain_after_load()

        # Set Grid Running Status
        ev_grid_running = True
        safeguard = False

        # Show the Screens
        renpy.show_screen("town_bg")
        renpy.show_screen("town_ui", _layer="town_UI")
        renpy.show("testname", layer="events", what=manager)
        #renpy.show_screen("debug", _layer="town_UI")

        # Run the Interaction System
        result = ui.interact()

    if result: #<-- Never runs
        "Done!" #<-- Never runs
        jump map_scrn #<-- Never runs
This is what initiates the UDD.

Code: Select all


    def tiles_event(ev, x, y, st):
        if store.safeguard:
            end_event()
            #renpy.end_interaction(True) <-- not working, takes back to Start Game.
            return
        if ev.type == MOUSEBUTTONDOWN: # Trigger: Pressed click
            if ev.button == 1: # Left Click
                if store.ev_grid_running:
                    renpy.restart_interaction()
                    return
                else:
                    #renpy.end_interaction(True) <-- not working either, takes back to Start Game.
                    return
        elif ev.type == MOUSEBUTTONUP: # Trigger: Let go of click
            if ev.button == 1: # Left Click
                if store.ev_grid_running:
                    renpy.restart_interaction()


    def tiles_update(st):
        if not store.ev_grid_running:
            if safeguard:
                end_event()
                #renpy.end_interaction(True)  <-- not working, takes back to Start Game.
                return
        for tile in tiles[:]:
            tile.update()
        for char in allies[:]:
            char.update()
        for wall in walls[:]:
            wall.update()
        for building in buildings[:]:
            building.update()
        for dec in decor[:]:
            dec.update()
        for npc in npcs[:]:
            npc.update()
        return 0.02

    def end_event():
        if allies:
            for ally in allies[:]:
                ally.show.destroy()
                allies.remove(ally)
            for wall in walls[:]:
                wall.show.destroy()
                walls.remove(wall)
            for tile in tiles[:]:
                tile.show.destroy()
                tiles.remove(tile)
            for building in buildings[:]:
                building.show.destroy()
                buildings.remove(building)
            for dec in decor[:]:
                dec.show.destroy()
                decor.remove(dec)
            for npc in npcs[:]:
                npc.show.destroy()
                npcs.remove(npc)
        store.safeguard = True

The events of the SpriteManager.

I use a separate screen (town_ui on townUI layer) to jump to this label where ev_grid_running is set to False:

Code: Select all


# LABEL : Transition screen for switching to Zone.
label go_town_zone:
    if on_exit == "map":
        $ disp.screen = "map"
        $ ev_grid_running = False
        $ renpy.hide_screen("town_ui", layer="town_UI")
        $ renpy.hide_screen("testname", layer="town_UI")
        $ on_exit = False
        $ safeguard = True
        scene bg black with fade
        jump map_scrn
    else:
        if disp.screen == "map":
            $ disp.screen = "town"
            $ safeguard = False
            $ event_msgs = []
        else:
            $ renpy.hide_screen("town_ui", layer="town_UI")
            $ renpy.hide_screen("testname", layer="town_UI")
            $ safeguard = True
        $ on_exit = False
        scene bg black with fade
        jump do_zone



##############################################################################
# Town Zones
#
# These are the screens used for town zones, background and overlay.
#
screen town_bg:
    add current_zone_bg

screen town_ui:
    if event_msgs:
        style_group "townStyle"
        add "talk_bubble.png" align (0.90,0.18)
        vbox:
            text "[ev_msg]"

    elif on_exit:
        $ tstr = "World Map" if on_exit == "map" else on_exit
        frame:
            style_group "townUIbot"

            vbox:
                text "To: [tstr]"
                textbutton _("Next Zone") action [
                                            SetVariable("current_zone",on_exit),
                                            Hide("town_bg"),
                                            Hide("debug"),
                                            Jump("go_town_zone")
                                          ]


When ev_grid_running is False, the tiles_event should end_event() and then run end_interaction(True).
However, when renpy.end_interaction(True) runs, it takes me to Start Game menu.

Code: Select all

    if result: #<-- Never runs
        "Done!" #<-- Never runs
        jump map_scrn #<-- Never runs
This never runs.

Right now, my method works. Namely:
1) keeping end_interactions commented, as displayed above
2) keeping these events doing just "return" when safeguard == True.

I need to know how to "close" UDD / SpriteManager.
Outside of perfect programmer terminology. The spirit of this statement is the message I need to convey.
I need to know how to close a SpriteManager.

Not simply Destroy Sprites, and Hide it.
end_interaction isn't doing that. It's closing everything and sending me to Start Game menu.

Is there something else, something simple, something elegant, perhaps Pythonic, where I can just do manager.end()?
I need to optimize my code, and this would be extremely convenient rather than all of the safeguards.

I went through the source to see how Ren'Py knows what screens / displayables are on what layer and how it identifies them, but honestly it was not very explicit to me at all.
I mean, I could not figure out how Ren'Py distinguishes a ui.interact (interaction).

To me, Ren'Py thinks that the interaction is the Game itself, as if it does not know that SpriteManager is the current interaction.
As if it loses track of the interaction's identifier somehow, possibly from my interaction with buttons on other screens? Or from calling scene?
This is the problem that I have identified.

I hope these code snippets make evident what I am trying to achieve and perhaps help clarify what I may be doing that Ren'Py does not like very much.
Please let me know if I need to provide any further information or if anything remains unclear.

Essentially, I need a concrete method (example) to close and repoen SpriteManager that allows me to use other screens as well.
This method seems to leave events / update running, as the sprites are just being destroyed and the displayable hidden.

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: Way to close SpriteManager? Event/update stay running.

#11 Post by PyTom »

I don't think you're ever hiding the sprite manager, are you?

You want to do:

Code: Select all

renpy.hide("testname", onlayer="events")
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: Way to close SpriteManager? Event/update stay running.

#12 Post by SypherZent »

Hmm. I need to try that. I was actually using renpy.hide_screen.
I guess since the sprites are destroyed, perhaps that wasn't running at all.

I will update my scripts tomorrow after work, test, see if that was the issue.
It'd really be a huge weight off my shoulders, if the solution is that simple!

Thanks for getting back to me so quickly on this everyday, PyTom.
I've got a slightly different way of reasoning that makes understanding simple things extremely difficult at times, so I appreciate the patience. :)

Post Reply

Who is online

Users browsing this forum: No registered users