KIVY - Python继续按下按钮

时间:2016-07-25 22:17:38

标签: android python ios kivy

我目前正在尝试为IOS / Android制作平台游戏,但我遇到了问题。我创建了两个按钮和一个角色。我希望角色继续移动,直到按钮被释放。我的意思是:当按下按钮时,我可以移动角色一次,但是我希望它一直移动直到按钮被释放。

我尝试了多种解决方案,例如我使用了pythons time module:

class Level1(Screen):
    posx = NumericProperty(0)
    posy = NumericProperty(0)
    moving = True
    i = 0
    def __init__(self, **kwargs):
        super(Level1, self).__init__(**kwargs)

    def rightmove(self):
        self.posx = self.posx+1
        time.sleep(10)

    def goright(self):
        while self.moving == True:
            self.rightmove()
            i += 1
            if i == 10:
                break


    def stopright(self):
        self.moving == False

但它不起作用。 它认为它以某种方式被置于无限循环中,因为当我按下按钮时,应用程序停止工作(“app停止工作......”错误)。

我几乎不知道如何解决这个问题。我在过去的几个小时里一直在努力,但还没有找到解决方案。 这是我的.py文件:

from kivy.app import App
from kivy.lang import Builder
from kivy.uix.screenmanager import ScreenManager, Screen, FadeTransition,         SlideTransition
from kivy.config import Config
from kivy.core.window import Window
from kivy.uix.label import Label
from kivy.uix.image import Image
from kivy.uix.widget import Widget
from kivy.properties import ObjectProperty, NumericProperty
from kivy.clock import Clock
from kivy.uix.floatlayout import FloatLayout
import time
Config.set('graphics','resizable',0) #don't make the app re-sizeable
#Graphics fix
 #this fixes drawing issues on some phones
Window.clearcolor = (0,0,0,1.) 

language = "english"
curr1msg = 1

class HomeScreen(Screen):
    pass  

class OptionsScreen(Screen):
    pass

class GameScreen(Screen):
    pass

class LevelScreen(Screen):
    pass

class Level1intro(Screen):
    global language
    global curr1msg
    if language == "english" and curr1msg == 1:
        pName = "Pedro"
        msg1 = """Hello my friend!
My name is Pedro and I have a problem. Will you help me?
My spanish studens have a spanish test tomorrow, but I lost the exams!
You are the only one who can help me!"""
        cont = "Press anywhere to continue..."
    elif language == "swedish" and curr1msg == 1:
        pName = "Pedro"
        msg1 = """Hejsan!
Jag är Pedro och jag har ett problem. Kan du hjälpa mig?
Mina spanska-elever har ett spanskaprov imorgon men jag har tappat bort     proven!
Du är den enda som kan hjälpa mig!"""
        cont = "Tryck på skärmen för att fortsätta..."

class Level1(Screen):
        posx = NumericProperty(0)
        posy = NumericProperty(0)
        moving = True
        i = 0
        def __init__(self, **kwargs):
            super(Level1, self).__init__(**kwargs)

        def rightmove(self):
            self.posx = self.posx+1
            time.sleep(10)

        def goright(self):
            while self.moving == True:
                self.rightmove()
                i += 1
                if i == 10:
                    break


        def stopright(self):
            self.moving == False


class ScreenManagement(ScreenManager):
    pass


presentation = Builder.load_file("main.kv")

class MainApp(App):
    def build(self):
        return presentation

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

这是我的.kv文件:

#: import FadeTransition kivy.uix.screenmanager.FadeTransition
#: import SlideTransition kivy.uix.screenmanager.SlideTransition
ScreenManagement:
    transition: FadeTransition()
    HomeScreen:
    OptionsScreen:
    LevelScreen:
    Level1intro:
    Level1:

<HomeScreen>:
    name: 'home'

    FloatLayout:
        canvas:
            Rectangle:
                source:"images/home_background.jpg"
                size: self.size
        Image:
            source:"images/logo.png"
            allow_stretch: False
            keep_ratio: False
            opacity: 1.0
            size_hint: 0.7, 0.8
            pos_hint: {'center_x': 0.5, 'center_y': 0.9}
        Button:
            size_hint: 0.32,0.32
            pos_hint: {"x":0.34, "y":0.4}
            on_press:
                app.root.transition = SlideTransition(direction="left")
                app.root.current = "level"
            background_normal: "images/play_button.png"
            allow_stretch: False
        Button:
            size_hint: 0.25,0.25
            pos_hint: {"x":0.38, "y":0.15}
            on_press:
                app.root.transition = SlideTransition(direction="left")
                app.root.current = 'options'
            background_normal: "images/settings_button.png"

<OptionsScreen>:
    name: 'options'

<LevelScreen>
    name: "level"

    FloatLayout:
        canvas:
            Rectangle:
                source:"images/home_background.jpg"
                size: self.size
        Label:
            text: "[b]Choose Level[/b]"
            markup: 1
            font_size: 40
            color: 1,0.5,0,1
            pos: 0,250
        Button:
            size_hint: 0.1,0.1
            pos_hint: {"x": 0.1, "y": 0.8}
            on_press:
                app.root.current = "level1intro"
            Image:
                source:"images/level1.png"
                allow_stretch: True
                y: self.parent.y + self.parent.height - 70
                x: self.parent.x
                height: 80
                width: 80

        Button:
            background_normal: "images/menu_button.png"
            pos_hint: {"x": 0.4, "y": 0}
            size_hint: 0.3,0.3
            pos_hint: {"x": 0.35}
            on_press:
                app.root.transition = SlideTransition(direction="right")
                app.root.current = "home"

<Level1intro>
    name: "level1intro"

    canvas:
        Rectangle:
            source: "images/background.png"
            size: self.size
    Image:
        source: "images/dialog.png"
        pos_hint: {"y": -0.35}
        size_hint: 0.7,1.0
    Label:
        font_size: 20
        color: 1,1,1,1
        pos_hint: {"x": -0.385, "y": -0.285}
        text: root.pName
    Label:
        font_size: 15
        color: 1,1,1,1
        pos_hint: {"x": -0.15, "y": -0.4}
        text: root.msg1
    Label:
        font_size: 15
        color: 0.7,0.8,1,1
        pos_hint: {"x": 0.025, "y": -0.449}
        text: root.cont
        on_touch_down: 
            app.root.transition = FadeTransition()
            app.root.current = "level1"

<Level1>
    name: "level1"
    canvas:
        Rectangle:
            source: "images/background.png"
            size: self.size

    Button:
        text: ">"
        size_hint: 0.1,0.1
        pos_hint: {"x":0.9, "y":0.0}
        on_press:
            root.goright()
        on_release:
            root.stopright()
    Button:
        text: "<"
        size_hint: 0.1,0.1
        pos_hint: {"x": 0.0, "y": 0.0}
        on_press:
            root.posx = root.posx-1

    Image:
        id: char
        source: "images/idle1.png"
        size: self.size
        pos: root.posx,root.posy

感谢您的时间和帮助。 GryTrean

//我将“i”更改为“self.i”并且无法解决问题。

3 个答案:

答案 0 :(得分:3)

我为你创建了一个简单的例子,介绍如何通过按下按钮来移动角色(在这种情况下,精灵战士等级1 ):

#!/usr/bin/env python3.5
# -*- coding: utf-8 -*-
from kivy.app import App
from kivy.lang import Builder
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.clock import mainthread, Clock

gui = '''
Root:
    orientation: 'vertical'

    arena: arena
    control_button: control_button

    Arena:
        id: arena

    Button
        id: control_button
        size_hint_y: None
        height: dp(50)
        text: 'move'


<Arena@FloatLayout>:
    player: player

    Button:
        id: player
        pos: 150, 300
        text: 'elf warrior\\nlevel 1'
        size_hint: None, None
        size: 100, 100
'''


class Root(BoxLayout):

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

        @mainthread
        def job():
            self.control_button.bind(on_press=self._on_press)
            self.control_button.bind(on_release=self._on_release)

        job()

    def _on_press(self, button):
        self.arena.start_movement()

    def _on_release(self, button):
        self.arena.stop_movement()


class Arena(FloatLayout):

    def start_movement(self):
        Clock.schedule_interval(self._move_right, 0.01)

    def stop_movement(self):
        Clock.unschedule(self._move_right)

    def _move_right(self, dt):
        self.player.x += 1


class Test(App):

    def build(self):
        return Builder.load_string(gui)


Test().run()

答案 1 :(得分:2)

根据Kivy API,一旦按下按钮,就可以创建一个事件。例如,

my_event = Clock.schedule_interval(rightmove, 0.5)

此事件将每0.5秒调用rightmove()。创建事件后,您可以通过-VariableName-()进行调用,因此在这种情况下,我们将放置my_event()

现在,如果我们释放按钮,则需要此按钮来停止循环,因此您可以绑定按钮的on_release属性,以在事件上执行cancel()函数。像这样:

my_event.cancel()

Button(on_release=my_event.cancel)

注意:您将需要my_event作为全局变量,以便开始和结束功能可以访问它。

答案 2 :(得分:0)

Here是kivy中的按钮API。适用于您的问题的两个绑定是on_presson_release绑定。您可以使用Button.bind()方法。可以使用将函数绑定到按钮绑定的示例here