PyGame Joystick

Hier werden alle anderen GUI-Toolkits sowie Spezial-Toolkits wie Spiele-Engines behandelt.
Antworten
Sephiroth
User
Beiträge: 28
Registriert: Freitag 3. November 2006, 00:12

Hallo,
ich habe auf dem Rechner ein kleines Script geschrieben, dass jetzt auch auf meinem gp2x laufen soll.
Allerdings bekomme ich die Buttonansprache nicht richtig hin.

Ich habe ein zusätzliches Modul gp2x.py erstellt mit dem Inhalt:

Code: Alles auswählen

# GP2X joystick button mappings
BUTTON_UP            = 0
BUTTON_DOWN          = 4
BUTTON_LEFT          = 2
BUTTON_RIGHT         = 6
BUTTON_UPLEFT        = 1
BUTTON_UPRIGHT       = 7
BUTTON_DOWNLEFT      = 3
BUTTON_DOWNRIGHT     = 5
BUTTON_CLICK         = 18
BUTTON_A             = 12
BUTTON_B             = 13
BUTTON_X             = 14
BUTTON_Y             = 15
BUTTON_L             = 10
BUTTON_R             = 11
BUTTON_START         = 8 
BUTTON_SELECT        = 9
BUTTON_VOLUP         = 16
BUTTON_VOLDOWN       = 17
(Aus dem gp2x wiki kopiert..;) )

Bisher hab ich in meinem Programm Tastaturabfragen so engegengenommen:
zb:

Code: Alles auswählen

        pygame.event.pump()
        if pygame.key.get_pressed()[pygame.K_LEFT]:
            self.spieler1.move(-1,0)
Und das ganze in einer while-Schleife.

Wie kann ich diesen Aufruf umschrieben, dass er eben die Joystick oder Buttoneingabe vom Handheld annimmt?


Im wiki steht zwar folgendes:

Code: Alles auswählen

    event = pygame.event.poll()
    if event.type == pygame.JOYBUTTONDOWN:
        if event.button == gp2x.BUTTON_X:
            print "X pressed"
http://wiki.gp2x.org/wiki/SDL_Joystick_mapping#Python

Allerdings kann ich damit nicht den Button gedrückt halten, sondern muss immerwieder neu draufdrücken das zb self.spieler1.move(-1,0) ausgeführt wird.
Bei dem von mir als erstes geposteten war dies nicht so.

Also zusammenfassend:
Gibt es eine Anweisung, mit der ich den Input vom Joystick genauso regeln kann wie mit pygame.key.get_pressed()[pygame.K_LEFT] auf dem PC?

Gruss
BlackJack

Du solltest auf ereignisbasierte Verarbeitung umstellen wie's im Wiki steht und auch allen Tutorials für pygame/SDL allgmein, die ich bis jetzt gelesen habe.
Imperator
User
Beiträge: 275
Registriert: Montag 20. August 2007, 14:43
Kontaktdaten:

Sephiroth
User
Beiträge: 28
Registriert: Freitag 3. November 2006, 00:12

Mit pygame.event.get() und auch mit pygame.event.poll() (Wie im wiki) habe ich es schon versucht:

Code: Alles auswählen

        eingabe = pygame.event.poll()
        if eingabe.type == pygame.KEYDOWN:
            if eingabe.key == pygame.K_RIGHT:
                self.spieler1.move(1,0)
und

Code: Alles auswählen

        for eingabe in pygame.event.get():
            if eingabe.type == pygame.KEYDOWN:
                if eingabe.key == pygame.K_RIGHT:
                    self.spieler1.move(1,0)
Beides klappt wunderbar, bis auf:
Ich möchte, wenn ich zum Beispiel Taste K_RIGHT gedrückt halte, das er die ganze Zeit nach rechts geht. Und das ich nicht immer neu drücken muss um einen "Schritt" zu machen. Mit pygame.key.get_pressed()[pygame.K_RIGHT]
hat das ja funktioniert. Aber ist anscheinend nicht auf den Joystick übertragbar.

Kann mir jemand kurz erläutern, was konkret an meinen beiden Code-Schnipseln falsch ist, bzw was ich verändern muss, dass "der Held" bei gedrückthalten der Taste "ununterbrochen" die Aktion durchführt.
(Egal ob für die Tastatur oder einen Joystick. Wenn ich das eine hab wird die Erschließung vom andern nicht so schwer sein..:D )


Gruss

und schonmal danke im vorraus für eure Hilfe!
BlackJack

Wenn Du das jeweilige *_DOWN-Ereignis bekommst läufst Du solange bis das *_UP dazu kommt.
Imperator
User
Beiträge: 275
Registriert: Montag 20. August 2007, 14:43
Kontaktdaten:

das kannst du per Syntax machen
Sephiroth
User
Beiträge: 28
Registriert: Freitag 3. November 2006, 00:12

Wenn Du das jeweilige *_DOWN-Ereignis bekommst läufst Du solange bis das *_UP dazu kommt.
Dachte ich auch, aber er macht immer nur einen Schritt, obwohl ich garkein *_UP drin habe.(Also sollte das *_DOWN ja durchgehend ausgeführt werden oder?)
das kannst du per Syntax machen
Syntax ist doch sowas wie "wie-ein-Befehl-strukturiert-sein-muss" oder?
Verstehe die Aussage nicht ganz..

Ich habe hier mal den kompletten Code hochgeladen, vielleichts hilfts ja bei der Problemerkennung..
http://paste.pocoo.org/show/32638/
die "def handleEventPC" ist die, die atm funktioniert, aber eben nur mit der Tastatur.
In der "def handleEventPC2" hab ich schon einiges durchprobiert. Funktioniert aber nichts so wirklich..^^
Die "def handleEventgp2x" könnter einfach ignorieren..

Gruss
BlackJack

Es gibt nur einmal ein *_DOWN, bis zum *_UP musst *Du* selbst dafür sorgen, dass die Figur bewegt wird.
Sephiroth
User
Beiträge: 28
Registriert: Freitag 3. November 2006, 00:12

Es gibt nur einmal ein *_DOWN, bis zum *_UP musst *Du* selbst dafür sorgen, dass die Figur bewegt wird.
Ok, ich glaube ich weiß jetzt was falsch bei mir war.
Aber kann ich denn sowas umsetzten?

Code: Alles auswählen

IF button_rechts gedrückt:
   while not button_rechts gelöst:
     laufen
So funktionierts mal nicht(bei mir)..

Gruss
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Merk Dir doch in der Klasse der Figur einfach die Bewegungsrichtung. In Deinem Event-Management änderst Du dann einfach die Bewegungsrichtung. Solange sich nichts ändert, rennt die Figur einfach stumpf weiter in eine Richtung!

Code: Alles auswählen

class Player():
    def __init__(self):
       self.xmove, self.ymove = (0, 0)

...
player = Player()
...
// Eventmanagement
if eingabe.type == KEYDOWN and event.key == pygame.K_UP:
    self.xmove, self.ymove = (0, -1)
elif ...
// usw.
Sephiroth
User
Beiträge: 28
Registriert: Freitag 3. November 2006, 00:12

Merk Dir doch in der Klasse der Figur einfach die Bewegungsrichtung. In Deinem Event-Management änderst Du dann einfach die Bewegungsrichtung. Solange sich nichts ändert, rennt die Figur einfach stumpf weiter in eine Richtung!
Danke!! Es funktioniert:) :



Eventmanagement sieht jetzt bei mir so aus:

Code: Alles auswählen

        eingabe = pygame.event.poll() 
        if eingabe.type == pygame.QUIT or (eingabe.type == pygame.KEYDOWN and eingabe.key == pygame.K_ESCAPE):
            self.running = False
        #---Spieler2---
        #S2 hoch
        if eingabe.type == pygame.KEYDOWN and eingabe.key == pygame.K_UP:
                self.spieler2.xmove = 0
                self.spieler2.ymove = -1  
Allerdings ist die Steuerung jetzt viel hakeliger..:(
Kann das vielleicht daran liegen, dass zwei Tasten gleichzeitig nichtmehr berücksichtigt werden(wie rechts und hoch zb)?

Gruss
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Nein, daran kann es eigentlich nicht liegen!

Ohne Deinen Code zu sehen, kann man da schlecht Aussagen machen. Wenn Du bisher nur immer genau einen Schritt gemacht hast, dann ist ja klar, dass man viel mehr Zeit hatte zu reagieren als Spieler, die Richtung zu wechseln!
Benutzeravatar
mkesper
User
Beiträge: 919
Registriert: Montag 20. November 2006, 15:48
Wohnort: formerly known as mkallas
Kontaktdaten:

Du darfst beim entsprechenden Event nur die Richtung beeinflussen, die auch gewünscht ist. Wenn du den Joytick nach rechts unten drückst, müßte er zwei Events erzeugen: rechts und unten gedrückt. Gehst du jetzt nur noch nach rechts, erhältst du einen "unten losgelassen" Event. Dieser darf aber nur die eine Richtung beeinflussen, nicht die andere.
Sephiroth
User
Beiträge: 28
Registriert: Freitag 3. November 2006, 00:12

Ohne Deinen Code zu sehen, kann man da schlecht Aussagen machen.
Hab hier mal den kompletten Code hochgeladen.(Das Main Menu ist noch im Aufbau;) )
http://paste.pocoo.org/show/32808/
(Zur Erläuterung: Das Programm ist ein Spiel(solls jedenfalls mal werden) in dem 2Spieler(die jeweils ein Quadrat steuern) einem dritten, das zufällig auf der Oberfläche gesetzt wird hinterherjagen. Wenn es berührt wurde, bekommt der Spieler einen Punkt und ein neues ziel wird gesetzt.)


Also ich habe mal etwas getestet, und ich glaube, dass wenn ein Spieler gerade eine Eingabe macht(wie nach rechts laufen), werden die Eingaben vom Anderen ignoriert.
Und:
Vorher hatte meine Eventmanagement Funktion etwas so ausgesehen:

Code: Alles auswählen

        pygame.event.pump()
        if pygame.key.get_pressed()[pygame.K_d]:
            self.spieler2.move(1,0)
        if pygame.key.get_pressed()[pygame.K_LEFT]:
            self.spieler1.move(-1,0)
.....usw
Damit hat auch sowas wie rechtshoch etc. funktioniert, und beide konnten gleichzeitig was eingeben.
Hat jemand ne Idee wie ich das realisieren könnte?

Gruss
BlackJack

@mkallas: Die Frage hat mkallas doch schon beantwortet und das sollte doch klar sein, wenn Du mal kurz drüber nachdenkst. Es gibt kein "rechts-oben", sondern nur "rechts" und "oben" und wenn beide jeweils die x- und die y-Richtung beeinflussen, kann nur eines davon "gewinnen". Und das beim Loslassen *irgendeiner* Taste alle Bewegungsrichtungen auf 0 gesetzt werden, ist auch ein wenig bescheuert und erklärt vielleicht warum Du die Steuerung als hakelig empfindest. :roll:

Wenn Du "oben" drückst, wird x=0 und y=-1 gesetzt, wenn dann noch "rechts" dazu kommt, wird x=1 und y=0 gesetzt, wobei Du den Effekt von "oben" zunichte gemacht hast. Wenn Du jetzt "oben" loslässt bleibt der Spieler stehen (x=0, y=0) obwohl ja immer noch "rechts" gedrückt ist.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Sephiroth hat geschrieben:Also ich habe mal etwas getestet, und ich glaube, dass wenn ein Spieler gerade eine Eingabe macht(wie nach rechts laufen), werden die Eingaben vom Anderen ignoriert.
Tastaturen können manchmal nicht mehr als drei gleichzeitig gedrückte Tasten verarbeiten. Das merkt man bei einigen Spielen, wenn man zu zweit auf einem Keyboard spielt.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Sephiroth
User
Beiträge: 28
Registriert: Freitag 3. November 2006, 00:12

@mkallas: Die Frage hat mkallas doch schon beantwortet und das sollte doch klar sein, wenn Du mal kurz drüber nachdenkst. Es gibt kein "rechts-oben", sondern nur "rechts" und "oben" und wenn beide jeweils die x- und die y-Richtung beeinflussen, kann nur eines davon "gewinnen". Und das beim Loslassen *irgendeiner* Taste alle Bewegungsrichtungen auf 0 gesetzt werden, ist auch ein wenig bescheuert und erklärt vielleicht warum Du die Steuerung als hakelig empfindest. Rolling Eyes

Wenn Du "oben" drückst, wird x=0 und y=-1 gesetzt, wenn dann noch "rechts" dazu kommt, wird x=1 und y=0 gesetzt, wobei Du den Effekt von "oben" zunichte gemacht hast. Wenn Du jetzt "oben" loslässt bleibt der Spieler stehen (x=0, y=0) obwohl ja immer noch "rechts" gedrückt ist.
Jetzt wo ihr es sagt ist es schon irgendwie einleuchtend. Habe es jetzt mal geändert:

Code: Alles auswählen

        #---Spieler2---
        #S2 hoch
        if eingabe.type == pygame.KEYDOWN and eingabe.key == pygame.K_UP:
                self.spieler2.ymove = -1  
        #S2 runter        
        elif eingabe.type == pygame.KEYDOWN and eingabe.key == pygame.K_DOWN:
                self.spieler2.ymove = 1
        #S2 rechts
        elif eingabe.type == pygame.KEYDOWN and eingabe.key == pygame.K_RIGHT:
                self.spieler2.xmove = 1   
        #S2 links
        elif eingabe.type == pygame.KEYDOWN and eingabe.key == pygame.K_LEFT:
                self.spieler2.xmove = -1             
        #S2 Taste loslassen
        #hoch runter
        elif eingabe.type == pygame.KEYUP and (eingabe.key == pygame.K_UP or pygame.K_DOWN):
                self.spieler2.ymove = 0               
        #rechts links
        elif eingabe.type == pygame.KEYUP and (eingabe.key == pygame.K_RIGHT or pygame.K_LEFT):
                self.spieler2.xmove = 0 
{Bewegungen auf der y-Achse funktionieren super.
Allerdings die auf der x-Achse nicht.
Drücke ich nach links oder rechts, bewegt sich das quadrat die ganze zeit in die Richtung, bis ich die entgegengesetzte Richtungstaste drücke.
Obwohl ich es doch bei beiden gleich gemacht habe.
In der Spieler-klasse wird auch die x und die y Achse gleich behandelt.
Find einfach keinen Unterschied, der erklären könnte wieso es auf der y-achse funktioniert und auf der x-Achse nicht.
}

[EDIT]: Ok, falsche Info. Ich musste einfach beim letzten elif block(Der ob rechts oder links losgelassen wurde) in einen normalen if block umwandeln.
[EDIT2]: Grade noch aufgefallen, dass wenn ein Spieler ne Richtungstaste loslässt, beim anderen egal welche Bewegung auch gestoppt wird.

Muss mir trotzdem nochmal alles durch den Kopf gehen lassen, denn hab immernoch das selbe Problem. Wenn zum rechten tastendruck noch einer nach oben hinzukommt etc.
Tastaturen können manchmal nicht mehr als drei gleichzeitig gedrückte Tasten verarbeiten. Das merkt man bei einigen Spielen, wenn man zu zweit auf einem Keyboard spielt.
Ist das dann ein Hard oder Softwareproblem der Tastatur?

Ps: Ich weiß, dass wahrscheinlich die meisten meiner Frage sehr trivial sind. Hab allerdings erst vor ner Woche mit Python/Pygame angefangen und bin von daher noch nicht so geübt im "Problem erkennen und lösen".
Also danke für euer Verständnis:)

Gruss
Antworten