Seite 1 von 1

PyGame Joystick

Verfasst: Sonntag 9. März 2008, 04:11
von Sephiroth
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

Verfasst: Sonntag 9. März 2008, 09:10
von 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.

Verfasst: Sonntag 9. März 2008, 09:58
von Imperator

Verfasst: Sonntag 9. März 2008, 18:16
von Sephiroth
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!

Verfasst: Sonntag 9. März 2008, 18:38
von BlackJack
Wenn Du das jeweilige *_DOWN-Ereignis bekommst läufst Du solange bis das *_UP dazu kommt.

Verfasst: Sonntag 9. März 2008, 19:15
von Imperator
das kannst du per Syntax machen

Verfasst: Sonntag 9. März 2008, 20:20
von Sephiroth
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

Verfasst: Sonntag 9. März 2008, 21:17
von BlackJack
Es gibt nur einmal ein *_DOWN, bis zum *_UP musst *Du* selbst dafür sorgen, dass die Figur bewegt wird.

Verfasst: Sonntag 9. März 2008, 23:55
von Sephiroth
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

Verfasst: Montag 10. März 2008, 00:29
von Hyperion
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.

Verfasst: Montag 10. März 2008, 02:05
von Sephiroth
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

Verfasst: Montag 10. März 2008, 09:36
von Hyperion
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!

Verfasst: Montag 10. März 2008, 10:56
von mkesper
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.

Verfasst: Montag 10. März 2008, 17:42
von Sephiroth
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

Verfasst: Montag 10. März 2008, 18:42
von 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.

Verfasst: Montag 10. März 2008, 18:42
von Leonidas
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.

Verfasst: Montag 10. März 2008, 20:15
von Sephiroth
@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