Search code examples
python-3.xkivyimage-rotation

Kivy rotation during movement


I'm struggling with how to properly implement simultaneous movement and rotation using Kivy (in python, not kv lang). My goal is to rotate an object so it's facing its destination then move it towards the destination using Animation. Using the code below I typically get movement in relation to the angle rotated instead of in relation to my general playing area. For example the animation without rotation might move an image to point [1,1] whereas with rotation of 180* the animation is moving the image to [-1,-1]. The image is properly rotated in this scenario, meaning it's facing the right way but going the wrong way.

My understanding is that the push/pop matrix functions should provide the appropriate context for the animation rather than the rotated element context. Because the PopMatrix function is happening in Canvas.after it seems like this has no effect - my animation is completed before the original Matrix is restored.

I'm lacking some key piece of information here that's causing a lot of headache. Can someone explain why the code below causes an image to move to (-1,-1) rather than the (1,1) indicated, and how to properly implement this?

I threw this code together as an example, my game code is far more complex. That's why I'm hoping for an explanation rather than a direct solution for my code. Thanks.

    with self.image.canvas.before:
        PushMatrix()
        self.rot = Rotate()
        self.rot.axis = (0, 0, 1)
        self.rot.origin=self.center
        self.rot.angle=180
    with self.image.canvas.after:
        PopMatrix()

    self.anim = Animation(pos = (1,1), duration=1)
    self.anim.start(self)
    self.image.pos = self.pos
    self.image.size = self.size

Solution

  • In case others are interested in how to make this work consistently - I've found that setting origin and angle on each frame, along with binding the image widget to any pos change on it's parent will ensure the widget moves with its parent and in the proper direction. I implemented that like this:

    Instantiate the image like this:

    with self.image.canvas.before:
        PushMatrix()
        self.rot = Rotate()
        self.rot.axis = (0, 0, 1)
        self.rot.origin=self.center
        self.rot.angle = 0
    with self.image.canvas.after:
        PopMatrix()
    

    Bind it like this:

    self.bind(pos = self.binding)
    
    def binding(self, *args):
        self.image.center = self.center
        self.image.size = self.size
    

    On each frame call a function that does similar to the below.

    self.rot.origin = self.center
    self.rot.angle = getangle()#you can use a set angle or generate a new angle every frame