2016-05-14 13 views
0

Ich mache ein Spiel mit Kivy für Android, die den Spieler durch Berühren bestimmter Bereiche auf dem Bildschirm gesteuert hat. Ich erstelle unsichtbare Buttons (char_controls), die nach dem Antippen den Charakter bewegen. In dem Moment, in dem der Finger losgelassen wird, möchte ich, dass der Charakter aufhört.Clock.unschedule funktioniert nicht, wenn mit bind() in kivy referenziert

Ich habe eine Funktion an jede Schaltfläche gebunden, die Clock.schedule_interval auf eine move_up -Funktion in der Zeichenklasse aufruft (nur mit der Up-Taste im Moment arbeiten). Wenn die Taste losgelassen wird, ruft sie eine andere Funktion auf, die die ursprüngliche Funktion (mit Clock.unschedule) entplanen sollte. Es tut dies jedoch nicht und der Charakter bewegt sich weiter.

Verwende ich die bind() - Funktion von kivy, wenn ich sie verwende, um die on_press- und on_release-Verhalten der Schaltfläche an Funktionen zu binden, die in einer anderen Klasse definiert sind? Ich habe bemerkt, dass ich einen AttributeError bekomme: 'Button' -Objekt hat kein Attribut 'move_up', wenn ich self zur Referenz move_up verwende - ich muss stattdessen auf die move_up-Funktion als character.move_up verweisen, auch wenn ich sie in der Zeichenklasse referenziere . Wenn das Problem nicht mit der bind() - Funktion zu tun hat, wie kann ich das Programm die move_up-Funktion entplanen lassen?

Unten ist mein Code:

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 

Vielen Dank im Voraus!

Antwort

0

Uhr die Konsole:

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

Sie verwenden zwei verschiedene Dinge character.<function>, die innerhalb der Klasse geplant ist (scheint mir seltsam, wenn Sie self zugänglich sein) und Sie Unschedule die self.<function> eine andere Funktion, die Sie nur den gleichen Weg anrufen.

Die erste ist ungebundene Methode Test.foo, ist die zweite zu einer Klasse andere ungebundene gebunden, die nicht die gleiche Funktion ist, deshalb unscheduling Sie eine falsche Funktion heißt die eine, die nicht eingeplant haben. Verwenden Sie den gleichen Wortlaut überall oder verwenden Sie ihn ordnungsgemäß.

Auch was Sie wollen, ist die Klassenkommunikation, die in einigen Fragen unter diesem Tag z. here - Verwenden der Haupt-App-Klasse für die Verbindung.

Ich bin nicht wirklich sicher, ob Sie bind() missbräuchlich, weil ich diese Sache innerhalb kv tun, aber Sie sollten einmal unterschiedliche Tastaturen verwenden, um auf das heißt bind(on_press=...,on_release=...)

+0

Oh dear ... Ich habe einen Tippfehler in meinem Frage. In der Zeile clock.unschedule (character.move_up) habe ich versehentlich clock.unschedule (self.move_up) eingegeben, das wäre natürlich ein entscheidender Fehler im Programm. Die Frage, die ich stelle, ist also, warum die Uhr die Funktion nicht einplant, selbst wenn sie als character.move_up referenziert wird? Ich habe auch keinen Zugriff auf sich selbst aus irgendeinem seltsamen Grund ... – Bam8000

+0

@ Bam8000 nichts wirklich geändert, Sie immer noch verschiedene Funktionen, sehen Sie das Beispiel wieder, ich habe es bearbeitet ^^ – KeyWeeUsr

+0

Danke für das Aufzeigen des Problems! Ich sehe das Problem jetzt. Aber warum sind sie nicht die gleiche Funktion? Ich verweise sie auf die gleiche Weise. Sollte ich einen anderen Ansatz verfolgen? – Bam8000