Editing and Ending a Rhythm Game Loop...

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
VAPMichaelaLaws
Regular
Posts: 185
Joined: Mon Dec 10, 2012 2:11 am
Completed: Check Signature!
Projects: Check Signature!
Organization: Seraphim Entertainment
Tumblr: thebunnyofevil
Contact:

Editing and Ending a Rhythm Game Loop...

#1 Post by VAPMichaelaLaws » Thu Jun 21, 2018 1:44 pm

Heyo!

I'm trying my darnedest to make a Dance QTE happen in my short VN and my first attempt to make something happen using only screens and timers did not work (ending with a laggy playback and an obnoxious amount of timing issues).

So I took to the interwebs and found this:
viewtopic.php?p=348727#p348727

I wanted to utilize it (giving proper credit of course) but when testing this code, I found that it's an eternal loop. Since the song the mini game is used for is only 63 seconds, this is an issue.

This is my edit to the code, but it's still unfortunately looping forever. My GOAL for it is two conditions:
1. If the player consistently hits the dance button successfully on it's marker during the duration of that 63 seconds, the game ends and the story continues (Label "dance_success")
2. If the player misses THREE times (whether it be misclicking or letting the target run past the marker), the game ends and the story goes to a bad end (Label "dance_failure")

Regardless, the loop needs to break and I have NO clue how to even do that.

Code: Select all

init python:
    config.screen_width=1280
    config.screen_height=800
    import time
    import pygame
    MOUSEBUTTONDOWN=pygame.MOUSEBUTTONDOWN
    
    class RhythmD(object):
        def __init__(self, sprite, speed, delay, ypos=0):
            self.sprite = sprite
            self.speed = speed
            self.delay = delay
            self.show = manager.create(sprite)
            self.show.x = -200
            self.show.y = ypos
            self.moving = False # No point in checking if it isn't.
            
        def update(self):
            if store.t + self.delay < time.time():
                self.moving = True
                self.x = self.x + self.speed
            else:
                pass
            
        @property
        def x(self):
            return self.show.x
        @x.setter
        def x(self, value):
            self.show.x = value
            
        @property
        def y(self):
            return self.show.y
        @y.setter
        def y(self, value):
            self.show.y = value
            
    def sprites_update(st):
        for sprite in sprites[:]:
            sprite.update()
            if sprite.x > config.screen_width:
                sprite.show.destroy()
                sprites.remove(sprite)
        return 0.05
        
    def sprites_event(ev, x, y, st):
        if ev.type == MOUSEBUTTONDOWN:
            if ev.button == 1:
                hit = False
                for sprite in sprites[:]:
                    if sprite.moving:
                        if int(sprite.x) in store.targets:
                            store.hits += 1
                            hit = True
                            sprite.show.destroy()
                            sprites.remove(sprite)
                            break
                if not hit:
                    store.misses += 1
                renpy.restart_interaction()
                
screen show_vars:
    text "Misses: [misses], Hits: [hits]" xalign 0.5
    add "practicebutton.png":
        pos (1000, 100)
        
    timer 63.0 action Jump("omgyayyoudidit") #63 seconds is the length of the song. GAME MUST END AT END OF SONG.
                
label rhythm_qte:
    play music "WALTZ.ogg"
    
    python:
        hits = 0
        misses = 0
        t = time.time()
        manager = SpriteManager(update=sprites_update, event=sprites_event)
        sprite = Image("practicebutton1.png")
        targets = set(1000+i for i in xrange(-200, 200))
        sprites = []
        td = 0
        for i in xrange(100):
            td += renpy.random.choice([0.5, 1, 2]) #TIMED SPACING
            sprites.append(RhythmD(Image("practicebutton.png"), 31, td, 100)) #image, time of distance, time of spawn, ypos
            
        renpy.show_screen("show_vars")
        renpy.show("_", what=manager, zorder=1)
        
    while True:
        $ result = ui.interact()
Image
Voice Actress | Singer | Writer | Producer | Director
http://www.michaelaamandalaws.com/
--------
Completed Projects: My Teacher (NaNoReno2013), Pizz'Amore, My Lady, Our School Love (Otome Audio CD), Our Honeymoon (Otome Audio CD), Seduce Me, Maid With Perfection (NaNoReno2015), Blind Love (ILUjam 2015), Love And Romance: A Study Of Intimacy, Seduce Me 2: The Demon War, Remember, Remember
Projects Still In Production: All For You

kivik
Miko-Class Veteran
Posts: 782
Joined: Fri Jun 24, 2016 5:58 pm
Contact:

Re: Editing and Ending a Rhythm Game Loop...

#2 Post by kivik » Thu Jun 21, 2018 2:00 pm

I'm glance reading as I'm in a rush, but I assume the while True part at the end is the infinite loop. You want to use a variable to determine whether the loop should continue, then change the variable from True to False when it's finished.

What I don't know at a quick glance is whether you have the code to check if the entire sequence has been completed, though given your description and this line, I assume you don't:

Code: Select all

    timer 63.0 action Jump("omgyayyoudidit") #63 seconds is the length of the song. GAME MUST END AT END OF SONG.
But I assume that line doesn't actually jump you to the label (which seems weird), or maybe something else is afoot. So perhaps change it to SetVariable() which alters your while loop variable:

Code: Select all

default qte_loop = True

...

    timer 63.0 action SetVariable("qte_loop", False) #63 seconds is the length of the song. GAME MUST END AT END OF SONG.

...

while qte_loop:
    ui.interact()

# should get to here after 63 seconds
jump dance_success
I don't see code that checks for failure of 3 times though, do you need help to add them as well? I assume you insert them in the if not hit: block to check for 3 misses and do a renpy.jump("dance_failure").

User avatar
VAPMichaelaLaws
Regular
Posts: 185
Joined: Mon Dec 10, 2012 2:11 am
Completed: Check Signature!
Projects: Check Signature!
Organization: Seraphim Entertainment
Tumblr: thebunnyofevil
Contact:

Re: Editing and Ending a Rhythm Game Loop...

#3 Post by VAPMichaelaLaws » Thu Jun 21, 2018 4:26 pm

Hello! Thank you for the assist!

I added a block at the end of the if not hit code and it works!

Code: Select all

    def sprites_event(ev, x, y, st):
        if ev.type == MOUSEBUTTONDOWN:
            if ev.button == 1:
                hit = False
                for sprite in sprites[:]:
                    if sprite.moving:
                        if int(sprite.x) in store.targets:
                            store.hits += 1
                            hit = True
                            sprite.show.destroy()
                            sprites.remove(sprite)
                            break
                if not hit:
                    store.misses += 1
                    if misses == 3:
                        renpy.hide_screen("show_vars")
                        renpy.hide("_")
                        renpy.jump("dance_failure")
                renpy.restart_interaction(
Now I only need to define that missing the mark also counts as a miss...

---

Otherwise, I added

Code: Select all

default qte_loop = True
to the code and changed my jump to the SetVariable, but it still loops past the timer.

Code: Select all

screen show_vars:
    text "Misses: [misses], Hits: [hits]" xalign 0.5
    add "practicebutton.png":
        pos (1000, 100)
        
    timer 63.0 action SetVariable("qte_loop", False) #63 seconds is the length of the song. GAME MUST END AT END OF SONG.
                
label rhythm_qte:
    play music "WALTZ.ogg"
    
    default qte_loop = True
    
    python:
        hits = 0
        misses = 0
        t = time.time()
        manager = SpriteManager(update=sprites_update, event=sprites_event)
        sprite = Image("practicebutton1.png")
        targets = set(1000+i for i in xrange(-200, 200))
        sprites = []
        td = 0
        for i in xrange(100):
            td += renpy.random.choice([0.5, 1, 2]) #TIMED SPACING
            sprites.append(RhythmD(Image("practicebutton.png"), 31, td, 100)) #image, time of distance, time of spawn, ypos
            
        renpy.show_screen("show_vars")
        renpy.show("_", what=manager, zorder=1)
        
    while qte_loop:
        $ result = ui.interact()

# should get to here after 63 seconds
    jump dance_success
Image
Voice Actress | Singer | Writer | Producer | Director
http://www.michaelaamandalaws.com/
--------
Completed Projects: My Teacher (NaNoReno2013), Pizz'Amore, My Lady, Our School Love (Otome Audio CD), Our Honeymoon (Otome Audio CD), Seduce Me, Maid With Perfection (NaNoReno2015), Blind Love (ILUjam 2015), Love And Romance: A Study Of Intimacy, Seduce Me 2: The Demon War, Remember, Remember
Projects Still In Production: All For You

kivik
Miko-Class Veteran
Posts: 782
Joined: Fri Jun 24, 2016 5:58 pm
Contact:

Re: Editing and Ending a Rhythm Game Loop...

#4 Post by kivik » Fri Jun 22, 2018 2:19 am

Sounds like the timer's not firing at all for whatever reason - which was what i was concerned about originally. I can have a look this evening when I'm back home, but meanwhile can you move the timer line to the start of the screen to see if it makes a difference?

User avatar
VAPMichaelaLaws
Regular
Posts: 185
Joined: Mon Dec 10, 2012 2:11 am
Completed: Check Signature!
Projects: Check Signature!
Organization: Seraphim Entertainment
Tumblr: thebunnyofevil
Contact:

Re: Editing and Ending a Rhythm Game Loop...

#5 Post by VAPMichaelaLaws » Fri Jun 22, 2018 12:07 pm

I moved it to the top and there was no change )=

Code: Select all

screen show_vars:
    timer 63.0 action SetVariable("qte_loop", False) #63 seconds is the length of the song. GAME MUST END AT END OF SONG.
    
    text "Misses: [misses], Hits: [hits]" xalign 0.5
    add "practicebutton.png":
        pos (1000, 100)
Image
Voice Actress | Singer | Writer | Producer | Director
http://www.michaelaamandalaws.com/
--------
Completed Projects: My Teacher (NaNoReno2013), Pizz'Amore, My Lady, Our School Love (Otome Audio CD), Our Honeymoon (Otome Audio CD), Seduce Me, Maid With Perfection (NaNoReno2015), Blind Love (ILUjam 2015), Love And Romance: A Study Of Intimacy, Seduce Me 2: The Demon War, Remember, Remember
Projects Still In Production: All For You

kivik
Miko-Class Veteran
Posts: 782
Joined: Fri Jun 24, 2016 5:58 pm
Contact:

Re: Editing and Ending a Rhythm Game Loop...

#6 Post by kivik » Sun Jun 24, 2018 12:49 pm

Bummer, seems like something is making the timer not fire on your screen, which is weird. Can you change the timer to 1 seconds and see if it does anything?

I'm not familiar with the ui.interact() to know if it causes problems along side screen timers - if so that's bad.

If a shorter timer of 1 seconds works, you could maybe do something different and use it to check every second if 63 seconds have passed. Your code includes t = time.time() so you just need to compare time.time() with t to see if it's been 63 seconds. Something like this (untested):

Code: Select all

screen show_vars:
    timer 1:
        repeat True:
        action If(time.time()-t >= 63, true=SetVariable("qte_loop", False))
If that doesn't work, maybe change the 63 seconds to shorter time intervals to test if it eventually triggers.

If that doesn't work, I think the current code doesn't have any other way of taking timed events as the ui.interact() will essentially block any renpy code physically...

Maybe see if you can find the creator and see how they end the game?

User avatar
gas
Veteran
Posts: 439
Joined: Mon Jan 26, 2009 7:21 pm
Contact:

Re: Editing and Ending a Rhythm Game Loop...

#7 Post by gas » Thu Jun 28, 2018 11:59 am

That code RESHOWN the screen at each interaction, resetting the timer at 63 each time.
Leave your original code untouched.
Show ANOTHER screen with timer alone just after the label statement.
Tested and it work fine.

Code: Select all

label  rythm_qte:
    show screen timeup()
    # whatever follow

screen timeup():
    timer 63.0 action Jump("completed")
Don't forget on your landing labels to hide screens and del spritemanagers and fuctions
10 ? "RENPY"
20 GOTO 10

RUN

User avatar
Alex
Eileen-Class Veteran
Posts: 1921
Joined: Fri Dec 11, 2009 5:25 pm
Contact:

Re: Editing and Ending a Rhythm Game Loop...

#8 Post by Alex » Thu Jun 28, 2018 2:17 pm

VAPMichaelaLaws wrote:
Fri Jun 22, 2018 12:07 pm
I moved it to the top and there was no change )=

Code: Select all

screen show_vars:
    timer 63.0 action SetVariable("qte_loop", False) #63 seconds is the length of the song. GAME MUST END AT END OF SONG.
    
    text "Misses: [misses], Hits: [hits]" xalign 0.5
    add "practicebutton.png":
        pos (1000, 100)
My two cents...

Code: Select all

    while qte_loop:
        $ result = ui.interact()
this part waits for something to be returned from your rythm game, and if so step to another iteration in loop while condition still true. This can be usefull if your game return anything on players interaction (for now it's not). So here you actually doesn't need the while loop, leave just

Code: Select all

$ result = ui.interact()
$ renpy.hide("_")
"End game ([result])"
and make your timer return some value to cause interaction, like

Code: Select all

timer 3.0 action Return("smth")

Post Reply

Who is online

Users browsing this forum: Powderchoweder