I am not fully understanding how to use canvas correctly for images with animations.
See the attached snippet, where I load an animated icon into an Image and do both: (1) add_widget the Image (2) create a Rectangle canvas instruction with a texture = Image's texture
The Image animates The Rectangle texture does not
I have read through all of the Kivy manual and read through Image and Canvas and I get the idea that Image is a nice high level class with all of this image animation handling and Canvas is more of a raw low-level drawing canvas.
So here is my question - what is the Kivy-correct architecture for handling animations on a Canvas? I looked at Animation but that seems for more matrix-like animations such as translation, scaling, rotation.
Here is what I am doing now: I have game with large map window and then a bunch of game UX in helper windows The game UX helper windows I do all the kivy layouts and such and use generally Images and so my icons are animating nicely
However in the game map, I am using canvas:
Drawing all of my game objects using this paradigm:
r=Rectangle(texture=some_Image.texture)
map.canvas.add(r)
When the world needs to be re-drawn:
1) map.canvas.clear()
2) draw all of the stuff in their new positions and states (to be faster, I should just track the dirty objects and locations and just draw those, but to be honest I am getting fantastic fps even with this nuclear-level clear on each draw)
This is of course a lot faster and lighter weight than creating and destroying hundreds of widget-classes - what map canvas is for - right?
But the problem is that my icons with animations in a zip file are not animating
Q: Am I thinking of canvas wrong? Should I instead be adding an Image for each of my game objects instead? (And take advantage of all the animated image support?)
from kivy.uix.relativelayout import RelativeLayout
from kivy.uix.image import Image
from kivy.app import App
from kivy.graphics import Rectangle
class MainApp(App):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.root = RelativeLayout()
# use any zip file of an animated image
self.animated_icon = Image(source='factory_icon.zip')
# If I add an Image, the icon animates
self.root.add_widget(self.animated_icon)
# If I add the Image's texture on to a Rectangle instruction, no animation
r = Rectangle(texture=self.animated_icon.texture, size=(100, 100), pos=(100, 100))
self.root.canvas.add(r)
def build(self):
return self.root
if __name__ == '__main__':
MainApp().run()
canvas: # add your instruction for main canvas here with self. canvas. before: # you can use this to add instructions rendered before with self.
Texture is a class that handles OpenGL textures. Depending on the hardware, some OpenGL capabilities might not be available (BGRA support, NPOT support, etc.) You cannot instantiate this class yourself. You must use the function Texture.create() to create a new texture: texture = Texture.
Image.texture
property changes in time. It schedules internally methods to update it as the animation goes. This change doesn't propagate to your rectangle because you created it with texture value captured at a very certain point in time, between updates. Consider this example (I use a .gif file for the animation, but the principle should be the same):
from kivy.uix.relativelayout import RelativeLayout
from kivy.uix.image import Image
from kivy.app import App
from kivy.graphics import Rectangle
class MainApp(App):
def __init__(self, **kwargs):
super(MainApp, self).__init__(**kwargs)
self.root = RelativeLayout()
animated_icon = Image(source='test.gif')
animated_icon.bind(texture=self.update_texture)
self.r = Rectangle(texture=animated_icon.texture, size=(500, 255), pos=(100, 100))
self.root.canvas.add(self.r)
def update_texture(self, instance, value):
self.r.texture = value
def build(self):
return self.root
if __name__ == '__main__':
MainApp().run()
Here I bind my own update_texture
method to image's texture
property so every time it changes I can update the rectangle accordingly.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With