Smoother movement transition for custom displayable / UDD

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
sapiboonggames
Veteran
Posts: 298
Joined: Thu Jan 05, 2012 8:53 am
Completed: I Love You, Brother [BxB]
Contact:

Smoother movement transition for custom displayable / UDD

#1 Post by sapiboonggames » Tue Jun 23, 2020 1:26 pm

Hello everyone! :mrgreen:
I want to implement a real-time movement where player moves towards mouse position. I managed to accomplish it via screens, but it got a bit laggy (sometimes player image doesn't respond to mouse click :()
Anyway, I stumbled upon UDD and it seems like a better way for dealing with anything real-time and should be less laggy.

Here's what I've got so far:

Code: Select all

class PlayerWalking(renpy.Displayable):

        def __init__(self):
            
            renpy.Displayable.__init__(self)
            
            self.height = 20
            self.width = 20
            
            self.sprite = Solid("#ffffff", xsize=self.width, ysize=self.height)
            
            self.x = 960
            self.y = 540
            
            self.targetx = 0
            self.targety = 0
                
        def render(self, width, height, st, at):
            t = Transform(child=self.sprite, xpos=self.x, ypos=self.y)

            render = renpy.Render(1920, 1080)
            
            child_render = renpy.render(self.sprite, width, height, st, at)
            
            x, y = self.x, self.y
            x -= self.height / 2
            y -= self.width / 2
            
            render.blit(child_render, (t.xpos, t.ypos))
            
            return render

        def event(self, ev, x, y, st):
            if renpy.map_event(ev, 'mousedown_1'):
            
                self.targetx=renpy.get_mouse_pos()[0]
                self.targety=renpy.get_mouse_pos()[1]
            
            distancex = self.x - self.targetx
            distancey = self.y - self.targety
            dist = (distancex**2)+(distancey**2)
            dist = math.sqrt(dist)
            
            if dist != 0:
                speed = dist/5
                
                newx = (self.x - (distancex/dist) * speed)
                newy = (self.y - (distancey/dist) * speed)
                
                self.x = newx
                self.y = newy
                
                renpy.redraw(self, 0)
            
        def visit(self):
            return [ self.sprite ]
Sprite does move to mouse position, but the movement transition isn't smooth (it's kinda choppy & has unstable speed).
I'm definitely doing something wrong here & I'm guessing the correct way to do it is by modifying st / at in render() (?) but I have no idea how since sample codes for UDD are very rare :cry:

Can anyone please point me to the right direction?
It's my first time using UDD and hoping to learn, so please bear with me!
Visit my website: http://www.sapiboong.com

rames44
Veteran
Posts: 231
Joined: Sun May 29, 2016 4:38 pm
Contact:

Re: Smoother movement transition for custom displayable / UDD

#2 Post by rames44 » Wed Jun 24, 2020 12:25 pm

Well, first I’m not sure why you’re creating the Transform, since all you use from it is it’s position, which you pass into it. Probably not a big deal, bun unnecessary processing.

Second, and more important, your “event” and “render” methods are going to get called at irregular intervals, but you’re not using the time info passed in to determine how much you should really move. Two calls might be separated by 0.1 seconds or 0.01 seconds, but you’re moving things by the same amount each time. Essentially, you need to figure out how long you want it to take for the sprite to get to its final position, and then use the st and/or at variables to figure out how far along the path it’s gotten and draw it there. This will make the motion constant, regardless of the frame rate variations.

Finally, you are asking for a redraw in your event method, but you’re not calling renpy.timeout(). This means you have no idea how long it will be until Ren’py decides to call your event() method again, which means you have no idea when the position will next be updated. You probably want a pretty short timeout so that you update regularly. 1/20th of a second, maybe.

User avatar
sapiboonggames
Veteran
Posts: 298
Joined: Thu Jan 05, 2012 8:53 am
Completed: I Love You, Brother [BxB]
Contact:

Re: Smoother movement transition for custom displayable / UDD

#3 Post by sapiboonggames » Wed Jun 24, 2020 12:45 pm

rames44 wrote:
Wed Jun 24, 2020 12:25 pm
Well, first I’m not sure why you’re creating the Transform, since all you use from it is it’s position, which you pass into it. Probably not a big deal, bun unnecessary processing.

Second, and more important, your “event” and “render” methods are going to get called at irregular intervals, but you’re not using the time info passed in to determine how much you should really move. Two calls might be separated by 0.1 seconds or 0.01 seconds, but you’re moving things by the same amount each time. Essentially, you need to figure out how long you want it to take for the sprite to get to its final position, and then use the st and/or at variables to figure out how far along the path it’s gotten and draw it there. This will make the motion constant, regardless of the frame rate variations.

Finally, you are asking for a redraw in your event method, but you’re not calling renpy.timeout(). This means you have no idea how long it will be until Ren’py decides to call your event() method again, which means you have no idea when the position will next be updated. You probably want a pretty short timeout so that you update regularly. 1/20th of a second, maybe.
I ended up doing the redraw and speed calculation in render() method and it somehow works (still not entirely sure why it works, but it works :lol: ).
What is the function of renpy.timeout()?
(Also, where do you guys find out about these functions? I dig through the Renpy docs and can't really find these nifty functions...)
Visit my website: http://www.sapiboong.com

rames44
Veteran
Posts: 231
Joined: Sun May 29, 2016 4:38 pm
Contact:

Re: Smoother movement transition for custom displayable / UDD

#4 Post by rames44 » Wed Jul 01, 2020 10:06 am

The renpy.timeout() function is documented at on the page describing UDD's: https://www.renpy.org/doc/html/udd.html (Down at the bottom.)

Doing the "where is it now" calculations inside redraw "feels correct" to me - basically, since redrawing can happen at any time, asynchronously from receiving events, the redraw function _should_ be able to figure out where things are at any point in time and draw them there correctly.

Post Reply

Who is online

Users browsing this forum: No registered users