如何在Kivy中持续改变图片位置实现动态天空移动效果
问题解决方案
报错根因
你出现TypeError: 'ObservableReferenceList' object is not callable的核心原因是:Kivy控件的pos是属性变量,不是可调用的方法,你使用cloud.pos(x, y)的写法相当于把pos属性当成函数调用,自然会报错,正确的写法是直接对pos属性赋值:cloud.pos = (新x坐标, 新y坐标)。
另外你原代码里Clock的导入路径错误,正确的导入路径是from kivy.clock import Clock,原写法也可能引发运行异常。
完整实现代码
我们拆分「云朵生成」和「位置更新」两个逻辑,同时自动清理移出屏幕的云朵避免内存占用持续升高,最终可运行代码如下:
from kivy.app import App from kivy.clock import Clock from kivy.uix.widget import Widget from kivy.uix.image import Image from kivy.core.window import Window import random class MainWidget(Widget): state_game_ongoing = True def __init__(self, **kwargs): super().__init__(**kwargs) # 改为实例属性,避免类属性全局共享的异常问题 self.clouds = [] # 每0.1秒生成一朵新云朵 Clock.schedule_interval(self.init_clouds, 1 / 10) # 每1/60秒刷新一次位置,保证动画流畅 Clock.schedule_interval(self.update_clouds, 1 / 60) def init_clouds(self, dt): # 新云朵从屏幕右侧外生成,移动效果更自然 x = random.randint(self.width, self.width + 200) y = random.randint(0, self.height - 100) cloud = Image(source="images/cloudbig.png", pos=(x, y)) self.add_widget(cloud) self.clouds.append(cloud) def update_clouds(self, dt): # 倒序遍历避免删除元素时索引错乱 for i in range(len(self.clouds)-1, -1, -1): cloud = self.clouds[i] # 调整数值可以修改云朵移动速度,数值越大移动越快 new_x = cloud.pos[0] - 2 cloud.pos = (new_x, cloud.pos[1]) # 云朵完全移出屏幕左侧时销毁 if new_x + cloud.width < 0: self.remove_widget(cloud) self.clouds.pop(i) class BalloonGameApp(App): def build(self): Window.clearcolor = (.2, .6, .8, 1) xd = MainWidget() return xd BalloonGameApp().run()
可自定义调整的参数
- 修改
Clock.schedule_interval(self.init_clouds, 1 / 10)里的第二个参数,可以调整云朵生成的频率 - 修改
new_x = cloud.pos[0] - 2里的减数,可以调整云朵左移的速度 - 修改
init_clouds方法里x、y的随机范围,可以调整云朵生成的位置区域
内容的提问来源于stack exchange,提问作者Pyr0
相关产品推荐
相关产品推荐

