Page 1 of 1

[SOLVED] Using a Screen Inside of a Function gives 'Not Defined' error

Posted: Mon Feb 17, 2020 11:02 pm
by Catsi
My goal is to have an option that, when enabled by the player, will cause a bar to appear in the upper-left hand corner when a music track starts, which will have a little icon of a music note and the name of the song. This is for folks who want to know the names of the songs, folks who cannot hear the audio and want cues to know when the audio atmosphere has changed, etc.

To do this, I've created a screen based off of ren'py's notify screen. I didn't use the notify screen itself because I still want to use the notify screen for other functionalities.

The code for the music track change screen is in the screens.rpy file and reads as follows:

Code: Select all

init -2:
    define gui.track_change_frame_borders = Borders(125, 31, 25, 31)
    define gui.track_change_text_size = 35
    define gui.track_change_ypos = 0
    define gui.frame_tile = False

    screen track_change(message):
        zorder 100
        style_prefix "track_change"

        frame at track_change_appear:
            text "[message!tq]"

        timer 5.25 action Hide('track_change')


    transform track_change_appear:
        on show:
            ypos -1 alpha 0.0
            parallel:
                easein 1.5 ypos 0.0
            parallel:
                linear 1.2 alpha 1.0
        on hide:
            parallel:
                easein 1.2 ypos -5
            parallel:
                linear 1.2 alpha 0.0


    style track_change_frame is empty
    style track_change_text is gui_text

    style track_change_frame:
        ypos gui.track_change_ypos

        background Frame("gui/track_change.png", gui.track_change_frame_borders, tile=gui.frame_tile)
        padding gui.track_change_frame_borders.padding

    style track_change_text:
        properties gui.text_properties("track_change")
I know this screen works fine because if I use 'show screen' directly in the script, it appears. That's not how I want to use it, however, as that would be tedious.

In a separate defineables.rpy file I have defines kept which includes the class of music files, and my function for playing songs:

Code: Select all

init python:
    class MusicTrack:
        def __init__(self, songtitle, filename):
            self.songtitle = songtitle
            self.filename = filename

    sloantheme = "audio/music/Tempered.mp3"

    music_tracks = []
    music_tracks.append(MusicTrack("Tempered", sloantheme))

    def play_music(song):
        renpy.music.play(song)
        if persistent.music_notifs == True:
            for x in music_tracks:
                if x.filename == renpy.music.get_playing('music'):
                    track_change("Currently playing: " + x.songtitle)
To play music in the script itself I just use the following:

Code: Select all

    $persistent.music_notifs = True

    $play_music(sloantheme)

And here is the traceback I get:

Code: Select all

I'm sorry, but an uncaught exception occurred.

While running game code:
  File "game/warscript.rpy", line 41, in script
    $play_music(sloantheme)
  File "game/warscript.rpy", line 41, in <module>
    $play_music(sloantheme)
  File "game/defineables.rpy", line 83, in play_music
    track_change("Currently playing: " + x.filename)
NameError: global name 'track_change' is not defined

-- Full Traceback ------------------------------------------------------------

Full traceback:
  File "game/warscript.rpy", line 41, in script
    $play_music(sloantheme)
  File "C:\Users\Amanda\Desktop\renpy-7.2.0-sdk\renpy\ast.py", line 914, in execute
    renpy.python.py_exec_bytecode(self.code.bytecode, self.hide, store=self.store)
  File "C:\Users\Amanda\Desktop\renpy-7.2.0-sdk\renpy\python.py", line 2028, in py_exec_bytecode
    exec bytecode in globals, locals
  File "game/warscript.rpy", line 41, in <module>
    $play_music(sloantheme)
  File "game/defineables.rpy", line 83, in play_music
    track_change("Currently playing: " + x.filename)
NameError: global name 'track_change' is not defined
So I'm assuming the error has something to do with global/local definitions? Like play_music() can't reach track_change to use it? But I don't know how to fix that.

Also, if it helps, I also tried the following:
If I try renpy.track_change() instead of just track_change(), I get

Code: Select all

File "game/defineables.rpy", line 83, in play_music
    renpy.track_change("Currently playing: " + x.songtitle)
AttributeError: 'module' object has no attribute 'track_change'
And if instead of that, I try renpy.notify(), then it appears just fine..

I just can't seem to get my track_change screen to work... :( If anyone could offer some advice, it'd be greatly appreciated.

Re: Using a Screen Inside of a Function gives 'Not Defined' error

Posted: Tue Feb 18, 2020 8:51 am
by gas
The error is that you have to show the screen, not just calling it like any function.

Re: Using a Screen Inside of a Function gives 'Not Defined' error

Posted: Tue Feb 18, 2020 12:31 pm
by Catsi
gas wrote:
Tue Feb 18, 2020 8:51 am
The error is that you have to show the screen, not just calling it like any function.
Thank you for responding?
What's the way to show a screen under a python init? Because this:

Code: Select all

init python:

    def play_music(song):
        renpy.music.play(song)
        if persistent.music_notifs == True:
            for x in music_tracks:
                if x.filename == renpy.music.get_playing('music'):
                    show screen track_change("Currently playing: " + x.songtitle)
Gives me

Code: Select all

I'm sorry, but errors were detected in your script. Please correct the
errors listed below, and try again.


File "game/defineables.rpy", line 83: invalid syntax
                    show screen track_change("Currently playing: " + x.songtitle)
                               ^
:(

Or do you mean I will have to manually use 'show screen' directly in my script every time I want the track_change screen to appear?

Re: Using a Screen Inside of a Function gives 'Not Defined' error

Posted: Tue Feb 18, 2020 1:27 pm
by rames44
Since you’re inside a Python function, you need to use the Python function to show your screen

https://www.renpy.org/doc/html/screen_p ... how_screen

Re: Using a Screen Inside of a Function gives 'Not Defined' error

Posted: Tue Feb 18, 2020 1:47 pm
by Catsi
rames44 wrote:
Tue Feb 18, 2020 1:27 pm
Since you’re inside a Python function, you need to use the Python function to show your screen

https://www.renpy.org/doc/html/screen_p ... how_screen
OHHHHH!! Oh my god, thank you so much!! Changing it to this:

Code: Select all

init python:

    def play_music(song):
        renpy.music.play(song)
        if persistent.music_notifs == True:
            for x in music_tracks:
                if x.filename == renpy.music.get_playing('music'):
                    renpy.show_screen("track_change", "Currently playing: " + x.songtitle)
                    
Worked perfectly!! Thank you again!

Re: [SOLVED] Using a Screen Inside of a Function gives 'Not Defined' error

Posted: Wed Feb 19, 2020 1:12 pm
by rames44
You’re very welcome!