为了账号安全,请及时绑定邮箱和手机立即绑定

Kivy:对象运动/更新问题(Kivy Pong 教程改编)

Kivy:对象运动/更新问题(Kivy Pong 教程改编)

呼啦一阵风 2022-01-05 10:22:27
我改编了 kivy pong 教程 ( https://kivy.org/doc/stable/tutorials/pong.html ) 的一部分来创建一个应该每秒更新 60 次的球类,在屏幕上移动球。同样,当球击中两侧时,应向相反方向反射。然而,球只是坐在屏幕的角落一动不动。我犯的语法/逻辑错误是什么?这是我的代码:from kivy.lang import Builderfrom kivy.app import Appfrom kivy.uix.boxlayout import BoxLayoutfrom kivy.uix.image import Imagefrom kivy import Configfrom kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition,\SlideTransitionfrom kivy.uix.widget import Widgetfrom kivy.animation import Animationfrom kivy.properties import NumericProperty, ReferenceListProperty,\ObjectPropertyfrom kivy.clock import Clockfrom kivy.vector import Vectorfrom random import randintBuilder.load_string('''<Ball>:    Image:        source: '58-Breakout-Tiles.png'        size: 15, 15        pos: self.pos<SettingsScreen>:    close: close    AnchorLayout:        anchor_x: 'left'        anchor_y: 'top'        Image:            id: close            size_hint: .03, .03            source: 'grey_crossGrey.png'    GridLayout:        cols: 2        Label:            font_name: 'vgafix.fon'            text: 'Music: '        Switch:            active: True        Label:            font_name: 'vgafix.fon'            text: 'Sounds: '        Switch:            active: True<MenuScreen>:    cog: cog    AnchorLayout:        anchor_x: 'right'        anchor_y: 'top'        Image:            id: cog            size_hint: .03, .03            source: 'settings-cog.png'    BoxLayout:        orientation: 'vertical'        Image:            source: 'brickbreaker log.png'        Label:            font_name: 'vgafix.fon'            text: 'Tap to start'<GameScreen>:    ball: ball    cog: cog    AnchorLayout:        anchor_x: 'right'        anchor_y: 'top'        Image:            id: cog            size_hint: .03, .03            source: 'settings-cog.png'    Ball:        id: ball        center: self.parent.center''')
查看完整描述

2 回答

?
九州编程

TA贡献1785条经验 获得超4个赞

该问题有两种解决方案。

方法一——kv文件

  • 消除 Image:

  • 添加size_hint: None, None以覆盖 (1, 1) 或 (100, 100) 的默认大小

  • 添加 canvas:

片段

Builder.load_string('''

<Ball>:

    size_hint: None, None

    size: 15, 15

    canvas:

        Rectangle:

            source: '58-Breakout-Tiles.png'

            pos: self.pos

            size: self.size

Kivy Canvas »来源

source

此属性表示要从中加载纹理的文件名。如果要使用图像作为源,请执行以下操作:


with self.canvas:

    Rectangle(source='mylogo.png', pos=self.pos, size=self.size)

这是 Kivy 语言中的等价物:


<MyWidget>:

    canvas:

        Rectangle:

            source: 'mylogo.png'

            pos: self.pos

            size: self.size

方法 2 - kv & py 文件

  • 将球定义从 kv 文件移动到 Python 脚本中

  • 创建球图像的纹理

  • 向画布声明一个包含球纹理的矩形

  • 只要有一个或更改self.rect,就将矩形绑定到一个方法。update_ball()possize

片段 - py

from kivy.core.image import Image

from kivy.graphics import Rectangle

...

class Ball(Widget):

    velocityX, velocityY = NumericProperty(0), NumericProperty(0)

    velocity = ReferenceListProperty(velocityX, velocityY)


    def __init__(self, **kwargs):

        super(Ball, self).__init__(**kwargs)

        texture = Image('58-Breakout-Tiles.png').texture

        self.size_hint = None, None

        self.size = (15, 15)

        with self.canvas:

            self.rect = Rectangle(texture=texture, pos=self.pos, size=self.size)

        self.bind(pos=self.update_ball, size=self.update_ball)


    def update_ball(self, *args):

        self.rect.pos = self.pos

        self.rect.size = self.size


    def move(self):

        self.pos = Vector(*self.velocity) + self.pos

片段 - kv

Builder.load_string('''

<SettingsScreen>:

Kivy 帆布 »纹理

texture

表示用于绘制此指令的纹理的属性。你可以像这样设置一个新的纹理:


from kivy.core.image import Image


texture = Image('logo.png').texture

with self.canvas:

    Rectangle(texture=texture, pos=self.pos, size=self.size)

通常,您将使用源属性而不是纹理。


查看完整回答
反对 回复 2022-01-05
?
慕姐4208626

TA贡献1852条经验 获得超7个赞

您的代码大部分都在工作。一个相当简单的解决方法是将您更改Ball为扩展Image(而不是Widget),然后添加size_hint: None, None.


因此,Ball类声明变为:


class Ball(Image):

类本身可以保持不变


对于规则Ball在你的kv文件被简化为:


<Ball>:

    source: '58-Breakout-Tiles.png'

在您的GameScreen规则中,该Ball部分变为:


Ball:

    id: ball

    size_hint: None, None

    center: self.parent.center

只需添加size_hint.


我认为这足以让它发挥作用。


或者,您可以将size_hint加到您的Ball作为:


Ball:

    id: ball

    size_hint: None, None

    center: self.parent.center

并改变pos: self.pos对pos: root.pos你的<Ball>:规则为:


<Ball>:

    Image:

        source: '58-Breakout-Tiles.png'

        size: 15, 15

        pos: root.pos

原始代码的主要问题是Image向 aWidget添加一个只是向Ball Widget. Widget不是 a 的ALayout不处理绘制其子项。原Pong游戏的把球图像中得到解决这个Canvas的Ball Widget。这Image门课基本上是为你做的。


查看完整回答
反对 回复 2022-01-05
  • 2 回答
  • 0 关注
  • 229 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信