为什么我的游戏 window 不能在 Kivy 中运行?
Why does my game window not work in Kivy?
我正在尝试在我的应用程序中构建一个主菜单,然后将您链接到游戏,我的游戏正在运行问题是当您按下播放时它会将您带到不会移动但我使用过的游戏打印语句进行检查,实际上,从您启动应用程序的那一刻起,游戏就在后台 运行。
这是 Py 代码:
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.uix.floatlayout import FloatLayout
from kivy.uix import label
from kivy.uix.gridlayout import GridLayout
from kivy.uix.button import Button
from kivy.clock import Clock
from kivy.config import Config
from kivy.uix.boxlayout import BoxLayout
class WindowManager(ScreenManager):
def StartUp(self):
self.current = "Menu"
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)
offset=(((ball.center_y - self.center_y)/2) - (ball.velocity_x /2)) *0.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)
def serve_ball(self,vel=(1,0.5)):
print("234Served")
self.ball.velocity= vel
self.ball.center = self.center
def Check_Top_Bottom(self):
#Check bottom collion
if self.ball.y <0:
self.ball.velocity_y= abs(self.ball.velocity_y)
#Check top colision
if self.ball.y+50> self.height:
self.ball.velocity_y = -abs(self.ball.velocity_y)
def Check_if_score(self):#Score
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(WindowManager().children)
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):
game=Game()
print(WindowManager().current_screen)
game.serve_ball()
Clock.schedule_interval(game.update, 1.0/60.0)
return game
if __name__ == "__main__":
myMenuApp().run()
这里是 KV 代码:
WindowManager:
MenuWindow:
Game:
<MenuWindow>:
name: "Menu"
FloatLayout:
Button:
size_hint: 0.2,0.05
pos_hint: {"x":0.39,"y":0.75}
text:"Play"
on_release:
app.root.current= "Game"
root.manager.transition.direction= "left"
Button:
size_hint: 0.2,0.05
pos_hint: {"x":0.39,"y":0.7}
text:"Settings"
Button:
size_hint: 0.2,0.05
pos_hint: {"x":0.39,"y":0.65}
text:"High Score"
Button:
size_hint: 0.2,0.05
pos_hint: {"x":0.39,"y":0.6}
text:"Quit"
<PongBall>
size_hint: None, None
size: 50,50
canvas:
Ellipse:
pos:self.pos
size:self.size
<PongPad>
size_hint: None, None
size:25,150
canvas:
Rectangle:
pos:self.pos
size:self.size
<Game>:
name:"Game"
ball: Pong_ball
player_1: Player1
player_2: Player2
canvas:
Rectangle:
pos:self.center_x -5,0
size: 15,root.height
PongPad:
id: Player2
pos:root.width-25,root.center_y-75
PongPad:
id: Player1
pos:0,root.center_y-75
PongBall:
id: Pong_ball
center: self.parent.center
我尝试过不使用 Builder,但问题几乎相同,我也尝试在 return 函数中调用屏幕管理器,但这只会给我一个空白屏幕。
另一件事是我在主菜单上尝试检查当前屏幕,它输出“NONE”
谢谢
几个问题:
- 当您执行
print(WindowManager().current_screen)
时,您正在创建一个新的 WindowManager
并打印它的 current_screen
。这与您的 GUI 中的任何 WindowManager
无关。
- 您正在加载
kv
文件,该文件构建了一个带有 WindowManager
的 GUI,它 returns。但是你忽略了 returned WindowManager
和 build()
方法 return 是一个 Game
实例,它成为你的 GUI 的根(没有 WindowManager
).
你可以使用Screen
的on_enter()
方法在Game
变为当前Screen
时启动Game
,像这样:
class Game(Screen):
ball = ObjectProperty(None)
player_1 = ObjectProperty(None)
player_2 = ObjectProperty(None)
def on_enter(self, *args):
# start the game
self.serve_ball()
Clock.schedule_interval(self.update, 1.0 / 60.0)
并且在 App
的 build()
方法中,只有 return 由 Builder
:
构建的 GUI
class myMenuApp(App):
def build(self):
return kv
我正在尝试在我的应用程序中构建一个主菜单,然后将您链接到游戏,我的游戏正在运行问题是当您按下播放时它会将您带到不会移动但我使用过的游戏打印语句进行检查,实际上,从您启动应用程序的那一刻起,游戏就在后台 运行。
这是 Py 代码:
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.uix.floatlayout import FloatLayout
from kivy.uix import label
from kivy.uix.gridlayout import GridLayout
from kivy.uix.button import Button
from kivy.clock import Clock
from kivy.config import Config
from kivy.uix.boxlayout import BoxLayout
class WindowManager(ScreenManager):
def StartUp(self):
self.current = "Menu"
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)
offset=(((ball.center_y - self.center_y)/2) - (ball.velocity_x /2)) *0.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)
def serve_ball(self,vel=(1,0.5)):
print("234Served")
self.ball.velocity= vel
self.ball.center = self.center
def Check_Top_Bottom(self):
#Check bottom collion
if self.ball.y <0:
self.ball.velocity_y= abs(self.ball.velocity_y)
#Check top colision
if self.ball.y+50> self.height:
self.ball.velocity_y = -abs(self.ball.velocity_y)
def Check_if_score(self):#Score
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(WindowManager().children)
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):
game=Game()
print(WindowManager().current_screen)
game.serve_ball()
Clock.schedule_interval(game.update, 1.0/60.0)
return game
if __name__ == "__main__":
myMenuApp().run()
这里是 KV 代码:
WindowManager:
MenuWindow:
Game:
<MenuWindow>:
name: "Menu"
FloatLayout:
Button:
size_hint: 0.2,0.05
pos_hint: {"x":0.39,"y":0.75}
text:"Play"
on_release:
app.root.current= "Game"
root.manager.transition.direction= "left"
Button:
size_hint: 0.2,0.05
pos_hint: {"x":0.39,"y":0.7}
text:"Settings"
Button:
size_hint: 0.2,0.05
pos_hint: {"x":0.39,"y":0.65}
text:"High Score"
Button:
size_hint: 0.2,0.05
pos_hint: {"x":0.39,"y":0.6}
text:"Quit"
<PongBall>
size_hint: None, None
size: 50,50
canvas:
Ellipse:
pos:self.pos
size:self.size
<PongPad>
size_hint: None, None
size:25,150
canvas:
Rectangle:
pos:self.pos
size:self.size
<Game>:
name:"Game"
ball: Pong_ball
player_1: Player1
player_2: Player2
canvas:
Rectangle:
pos:self.center_x -5,0
size: 15,root.height
PongPad:
id: Player2
pos:root.width-25,root.center_y-75
PongPad:
id: Player1
pos:0,root.center_y-75
PongBall:
id: Pong_ball
center: self.parent.center
我尝试过不使用 Builder,但问题几乎相同,我也尝试在 return 函数中调用屏幕管理器,但这只会给我一个空白屏幕。
另一件事是我在主菜单上尝试检查当前屏幕,它输出“NONE”
谢谢
几个问题:
- 当您执行
print(WindowManager().current_screen)
时,您正在创建一个新的WindowManager
并打印它的current_screen
。这与您的 GUI 中的任何WindowManager
无关。 - 您正在加载
kv
文件,该文件构建了一个带有WindowManager
的 GUI,它 returns。但是你忽略了 returnedWindowManager
和build()
方法 return 是一个Game
实例,它成为你的 GUI 的根(没有WindowManager
).
你可以使用Screen
的on_enter()
方法在Game
变为当前Screen
时启动Game
,像这样:
class Game(Screen):
ball = ObjectProperty(None)
player_1 = ObjectProperty(None)
player_2 = ObjectProperty(None)
def on_enter(self, *args):
# start the game
self.serve_ball()
Clock.schedule_interval(self.update, 1.0 / 60.0)
并且在 App
的 build()
方法中,只有 return 由 Builder
:
class myMenuApp(App):
def build(self):
return kv