首页 > 解决方案 > Kivy on_touch_move 和 DragBehaviour 不移动 Image Widget

问题描述

我试图让我的播放器图像在由 on_touch_move 事件触发时移动。我曾尝试使用 DragBehaviour,但没有成功。同样,更新 Player Image 的 x 坐标也没有效果。

代码

from kivy.lang import Builder
from kivy.app import App
from kivy.uix.image import Image
from kivy import Config
from kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition
from kivy.uix.widget import Widget
from kivy.properties import NumericProperty, ReferenceListProperty,\
StringProperty
from kivy.clock import Clock
from kivy.vector import Vector
from random import randint

Builder.load_string('''
<Ball>:
    size_hint: None, None
    source: '58-Breakout-Tiles.png'
    pos: self.pos
    size: 15, 15

<Player>:
    size_hint: None, None
    source: '49-Breakout-Tiles.png'
    pos: self.pos
    size: 60, 30



<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
    player: player
    cog: cog
    AnchorLayout:
        anchor_x: 'right'
        anchor_y: 'top'
        Image:
            id: cog
            size_hint: .03, .03
            source: 'settings-cog.png'

    Ball:
        id: ball
        size_hint: None, None
        center: self.parent.center
    Player:
        id: player
        size_hint: None, None
''')

Config.set('graphics', 'multisamples', '0')


class Ball(Image):
    velocityX, velocityY = NumericProperty(0), NumericProperty(0)
    velocity = ReferenceListProperty(velocityX, velocityY)

    def move(self):
        self.pos = Vector(*self.velocity) + self.pos


class Player(Image):
    def __init__(self, **kwargs):
        super(Player, self).__init__(**kwargs)

    def on_touch_move(self, touch):
        if self.collide_point(*touch.pos):
            if (self.x >= 0) and (self.x <= self.width - 15):
                self.x += (abs(self.x - touch.x))

class Brick(Image):
    pass



class SettingsScreen(Screen):

    def __init__(self, **kwargs):
        super(SettingsScreen, self).__init__(**kwargs)
        self.previous = StringProperty('')

    def on_touch_down(self, touch):
        if self.close.collide_point(*touch.pos):
            self.manager.current = self.previous


class MenuScreen(Screen):

    def on_touch_down(self, touch):
        if self.cog.collide_point(*touch.pos):
            self.manager.get_screen('settings').previous = self.manager.current
            self.manager.current = 'settings'
        else:
            self.manager.transition = FadeTransition()
            self.manager.current = 'game'


class GameScreen(Screen):

    def __init__(self, **kwargs):
        super(GameScreen, self).__init__(**kwargs)
        self.initWidgets()

    def on_pre_enter(self, *args):
        self.interval = Clock.schedule_interval(self.update, 1.0 / 60.0)

    def on_touch_down(self, touch):
        if self.cog.collide_point(*touch.pos):
            self.manager.get_screen('settings').previous = self.manager.current
            self.manager.current = 'settings'

    def initWidgets(self):
        self.ball.center = self.center
        self.ball.velocity = Vector(0, 4).rotate(randint(0, 360))
        self.player.pos_hint = {'top': 0.1, 'right': 0.6}

    def update(self, dt):
        self.ball.move()
        if (self.ball.y < 0) or (self.ball.y > self.height - 15):
            self.ball.velocityY *= -1
        # bounce off left and right
        if (self.ball.x < 0) or (self.ball.x > self.width - 15):
            self.ball.velocityX *= -1

    def on_pre_leave(self, *args):
        self.interval.cancel()


sm = ScreenManager(transition=FadeTransition())
sm.add_widget(MenuScreen(name='menu'))
sm.add_widget(GameScreen(name='game'))
sm.add_widget(SettingsScreen(name='settings'))


class BrickBreakerInsanityApp(App):
    def build(self):
        return sm


if __name__ == '__main__':
    BrickBreakerInsanityApp().run

代码资产(必填):

https://drive.google.com/open?id=1GAnv5DfjNUuAXTybmsan90Dm0OuSVOfb

https://i.stack.imgur.com/rR799.png

https://i.stack.imgur.com/ngYvL.png

https://i.stack.imgur.com/AuxI3.png

https://i.stack.imgur.com/ypd7C.png

https://i.stack.imgur.com/rNvLz.png

标签: pythonpython-3.xkivykivy-language

解决方案


根本原因

播放器小部件没有移动,因为self.player.pos_hint = {'top': 0.1, 'right': 0.6}

解决方案

.kv 文件

  • self.player.pos_hint = {'top': 0.1, 'right': 0.6}从方法中移除initWidgets()

片段 - kv

Ball:
    id: ball
    center: root.center

Player:
    id: player
    y: root.height * 0.1 - self.height
    x: root.width * 0.6 - self.width

py文件

  • 将方法添加on_touch_move()class Player()or中class GameScreen()

片段 - Py:方法 1

class Player(Image):

    def on_touch_move(self, touch):
        if (touch.x >= 0) and (touch.x <= self.parent.width - self.width):
            self.x = touch.x
            return True
        return super(Player, self).on_touch_move(touch)
    ...
class GameScreen(Screen):
    ...
    def initWidgets(self):
        self.ball.velocity = Vector(0, 4).rotate(randint(0, 360))

片段 - Py:方法 2

class Player(Image):
    pass
    ...
class GameScreen(Screen):
    ...
    def initWidgets(self):
        self.ball.velocity = Vector(0, 4).rotate(randint(0, 360))
    ...
    def on_touch_move(self, touch):
        if (touch.x >= 0) and (touch.x <= self.width - self.player.width):
            self.player.x = touch.x
            return True
        return super(GameScreen, self).on_touch_move(touch)

推荐阅读