Kivy on_touch_move和DragBehaviour不能移动图像小部件

时间:2019-04-11 20:50:57

标签: python python-3.x kivy kivy-language

当我被on_touch_move事件触发时,我试图使我的播放器图像移动。我曾尝试使用DragBehaviour,但没有用。同样,更新播放器图像的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

1 个答案:

答案 0 :(得分:0)

根本原因

由于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()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)