0

画面上の特定の領域に触れることでプレーヤーを制御する、Android用のkivyを使用してゲームを作成しています。タップするとキャラクターが動く、目に見えないボタン (char_controls) を作成します。指を離した瞬間にキャラクターを止めてほしいです。

文字クラスの move_up 関数で Clock.schedule_interval を呼び出す関数を各ボタンにバインドしました (現在は上ボタンでのみ動作しています)。ボタンが離されると、元の関数のスケジュールを解除する別の関数が呼び出されます (Clock.unschedule を使用)。しかし、そうはならず、キャラクターは動き続けます。

ボタンの on_press および on_release 動作を別のクラスで定義された関数にバインドするために使用するときに、kivy の bind() 関数を誤用していますか? self を使用して move_up を参照すると、AttributeError: 'Button' object has no attribute 'move_up' が発生することに気付きました — 文字クラスで参照している場合でも、代わりに move_up 関数を character.move_up として参照する必要があります。 . 問題が bind() 関数に関係していない場合、プログラムで move_up 関数のスケジュールを解除するにはどうすればよいですか?

以下は私のコードです:

from kivy.uix.widget import Widget
from kivy.graphics import Canvas, Rectangle, Color
from kivy.uix.anchorlayout import AnchorLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.button import Button
from kivy.clock import Clock
from kivy.properties import *
from kivy.core.window import Window
from main import *
from render import Layer


class char_controls(FloatLayout):
    '''controls where the character moves. There are 4 regions where the player can tap:
       the top third to go up, the bottom third to go down, the center left to go left
       and the center right to go right. They are buttons.'''

    def __init__(self, **kwargs):
        super(char_controls, self).__init__(**kwargs)
        self.opacity = 0
        self.size = (Window.width, Window.height)

        anchor_bc = AnchorLayout(anchor_x = 'center', anchor_y = 'bottom')
        down_btn = Button(text='', size_hint = (1, 0.3333))
        down_btn.bind(on_press=character.move_down, on_release=character.stop)
        down_btn.bind(on_press=Layer.move_down, on_release=Layer.stop)
        anchor_bc.add_widget(down_btn)
        self.add_widget(anchor_bc)

        anchor_cl = AnchorLayout(anchor_x = 'left', anchor_y = 'center')
        left_btn = Button(text='', size_hint = (0.5, 0.3333))
        left_btn.bind(on_press=character.move_left, on_release=character.stop)
        left_btn.bind(on_press=Layer.move_left, on_release=Layer.stop)
        anchor_cl.add_widget(left_btn)
        self.add_widget(anchor_cl)

        anchor_cr = AnchorLayout(anchor_x = 'right', anchor_y = 'center')
        right_btn = Button(text='', size_hint = (0.5, 0.3333))
        right_btn.bind(on_press=character.move_right, on_release=character.stop)
        right_btn.bind(on_press=Layer.move_right, on_release=Layer.stop)
        anchor_cr.add_widget(right_btn)
        self.add_widget(anchor_cr)

        #button of interest
        anchor_tc = AnchorLayout(anchor_x = 'center', anchor_y = 'top')
        up_btn = Button(text='', size_hint = (1, 0.3333))
        up_btn.bind(on_press=character.schedule_up, on_release=character.stop)
        up_btn.bind(on_press=Layer.move_up, on_release=Layer.stop)
        anchor_tc.add_widget(up_btn)
        self.add_widget(anchor_tc)



class character(Widget):
    '''The character class.'''
    x_pos = 0
    y_pos = 0
    pos = (x_pos, y_pos)

    def __init__(self, **kwargs):
        super(character, self).__init__(**kwargs)
        with self.canvas:
            Color(1., 0, 0)
            character.sprite = Rectangle(pos=self.pos, size=(32, 32))


    #is there a cleaner way to call the movement functions than this? (Eg lambda)
    def schedule_up(self):
        Clock.schedule_interval(character.move_up, 1/30.)

    def move_up(self):
        character.y_pos += 1
        character.pos = (character.x_pos, character.y_pos)
        character.sprite.pos = character.pos
        print('run')

    def move_down(self):
        print('down')

    def move_right(self):
        print('right')

    def move_left(self):
        print('left')

    def stop(self):
        Clock.unschedule(character.move_up) #this is not actually unscheduling the move_up function.
        print('stop') #prints, so the function is working

前もって感謝します!

4

1 に答える 1

0

コンソールを見る:

from kivy.base import runTouchApp
from kivy.uix.boxlayout import BoxLayout
class Test(BoxLayout):
    def __init__(self, **kw):
        super(Test,self).__init__(**kw)
        from kivy.clock import Clock
        func1=Test.foo
        print func1
        Clock.schedule_interval(func1,1)
        func2=Test.foo
        print func2
        print func1 is func2 # <--------------------Here(False) ^^
        Clock.unschedule(func2)
    def foo(self):
        print 'bar'
runTouchApp(Test())

クラス内でスケジュールされている2つの異なるものcharacter.<function>を使用しており(アクセスできる場合は奇妙に思えます) 、同じ方法でのみ呼び出す別の関数のselfスケジュールを解除します。self.<function>

1 つ目はバインドされていないメソッドTest.fooで、2 つ目は同じ関数ではない別のバインドされていないクラスにバインドされているため、不適切な関数、つまりスケジュールされていない関数のスケジュールを解除しています。どこでも同じ言葉遣いを使用するか、適切に使用してください。

また、必要なのはクラス通信です。これは、このタグの下のいくつかの質問で説明されています。たとえば、ここではメインの App クラスを使用して接続を処理します。

私はこれらのことをkv内で行っているので、あなたが誤用しているかどうかはよくわかりませんがbind()、一度に異なるキーボードを使用できるはずです.bind(on_press=...,on_release=...)

于 2016-05-14T06:21:37.600 に答える