You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kivy点击Play跳转游戏后窗口静止但后台已运行如何解决?

错误根源

  1. 实例不匹配:调用Builder.load_file("myMenu.kv")已经生成了一个包含MenuWindow、Game实例的WindowManager对象,存在代码中的kv变量中。但原build方法中要么返回了单独新建的Game实例,要么返回了新建的空WindowManager实例,和KV加载的已有实例完全独立,导致后台运行的游戏逻辑和前端显示的界面不匹配,画面静止。
  2. 初始化时机错误:原代码在build阶段就启动了Game的update调度和发球逻辑,此时Game实例还未被挂载到显示树,画面不会同步更新。
  3. 实例获取方式错误:WindowManager()每次调用都会生成全新的空实例,因此查询current_screen永远返回None,实际运行的WindowManager实例可以通过App.get_running_app().root或者Screen子类的self.manager获取。

修正代码

Python代码

import kivy
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.lang.builder import Builder
from kivy.uix.screenmanager import Screen, ScreenManager
from kivy.properties import NumericProperty, ReferenceListProperty, ObjectProperty
from kivy.vector import Vector
from kivy.clock import Clock

class WindowManager(ScreenManager):
    pass

class MenuWindow(Screen):
    pass 

class PongBall(Widget):
    velocity_y= NumericProperty(0)
    velocity_x= NumericProperty(0)
    velocity=ReferenceListProperty(velocity_x,velocity_y)
    def move(self):
        self.pos = Vector(self.velocity) + self.pos

class PongPad(Widget):
    score=NumericProperty(0)
    def Check_bounce(self,ball):
        if self.collide_widget(ball):
            vx,vy= ball.velocity
            bounced= Vector(-1* vx, vy )
            speedup= abs(((ball.velocity_x *0.1) -(ball.center_y - self.center_y)) *0.002) 
            vel = bounced *  (speedup +1.1)
            if (ball.center_y - self.center_y) > 0:
                ball.velocity=vel.x,vel.y
                ball.velocity_y= 2
            else:
                ball.velocity= vel.x,vel.y
                ball.velocity_y= -2

class Game(Screen):
    ball = ObjectProperty(None)
    player_1 = ObjectProperty(None)
    player_2 = ObjectProperty(None)
    _update_event = None # 存储调度事件避免重复调度

    def serve_ball(self,vel=(1,0.5)):
        print("234Served")
        self.ball.velocity= vel
        self.ball.center = self.center

    def Check_Top_Bottom(self):
        if self.ball.y <0:
            self.ball.velocity_y= abs(self.ball.velocity_y)
        if self.ball.y+50> self.height:
            self.ball.velocity_y = -abs(self.ball.velocity_y)

    def Check_if_score(self):
        if self.ball.x >self.width:
            self.player_1.score +=1
            self.serve_ball()
        if self.ball.x+50 <0:
            self.player_2.score += 1
            self.serve_ball()

    def update(self,dt):
        self.ball.move()
        self.Check_Top_Bottom()
        self.Check_if_score()
        self.player_1.Check_bounce(self.ball)
        self.player_2.Check_bounce(self.ball)
        print(self.manager.current_screen) # 正确获取当前屏幕

    def on_enter(self, *args):
        # 进入游戏界面时才初始化游戏
        self.serve_ball()
        if not self._update_event:
            self._update_event = Clock.schedule_interval(self.update, 1.0/60.0)
    
    def on_leave(self, *args):
        # 离开游戏界面时停止调度,不需要可删除
        if self._update_event:
            Clock.unschedule(self._update_event)
            self._update_event = None

    def on_touch_move(self,touch):
        if touch.x > self.width/2:
            self.player_2.center_y = touch.y
        else:
            self.player_1.center_y= touch.y

kv= Builder.load_file("myMenu.kv")

class myMenuApp(App):
    def build(self):
        # 直接返回KV加载生成的WindowManager实例
        return kv

if __name__ == "__main__":
    myMenuApp().run()

KV代码无需修改,可保持原有内容。

修正后效果

  • 应用启动后直接显示主菜单界面,查询当前屏幕可正常返回对应实例
  • 点击Play按钮跳转至游戏界面后,球才开始运动,画面和逻辑完全同步
  • 切回主菜单时可自动停止游戏更新(可根据需求删除on_leave逻辑保留后台运行)

内容的提问来源于stack exchange,提问作者Kol4o100

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 06:06:03