Player für PyGame Spiel

Hier werden alle anderen GUI-Toolkits sowie Spezial-Toolkits wie Spiele-Engines behandelt.
MGS_Freak
User
Beiträge: 35
Registriert: Donnerstag 13. Januar 2011, 13:50
Wohnort: Schweiz

Ciao a tutti

Für ein Pygame-Spiel möchte ich 2 Player erstellen, welche fixe Bewegunstasten zugewiesen bekommen. Kann ich das so:

Code: Alles auswählen

import pygame

players = ["player1"{
    "up": pygame.K_UP,
    "down": pygame.K_DOWN},
           "player2"{
               "up": pygame.K_w,
               "down": pygame.K_s}]
machen? Irgendwie schein mir das nicht so toll zu sein, doch vielleicht liegt das ja an mir...

Danke vielmals & Grüsse
MGS_Freak
Zuletzt geändert von Anonymous am Donnerstag 15. März 2012, 11:33, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Code-Tags gesetzt.
BlackJack

@MGS_Freak: Syntaktisch nicht korrekter Python-Quelltext ist wirklich nicht so toll. Insbesondere in Programmen ist der ärgerlich. :twisted:

Code: Alles auswählen

In [31]: import pygame

In [32]: %cpaste
Pasting code; enter '--' alone on the line to stop.
:players = ["player1"{
:    "up": pygame.K_UP,
:    "down": pygame.K_DOWN},
:           "player2"{
:               "up": pygame.K_w,
:               "down": pygame.K_s}]
:--
------------------------------------------------------------
   File "<string>", line 1
     players = ["player1"{
                         ^
SyntaxError: invalid syntax
Grundsätzlich kann man Konfigurationsdaten natürlich in einer verschalteten Wörterbuchstruktur speichern.
MGS_Freak
User
Beiträge: 35
Registriert: Donnerstag 13. Januar 2011, 13:50
Wohnort: Schweiz

@MGS_Freak: Syntaktisch nicht korrekter Python-Quelltext ist wirklich nicht so toll. Insbesondere in Programmen ist der ärgerlich.
Defintiv, ich Dödel :( Grosses Sorry!
Grundsätzlich kann man Konfigurationsdaten natürlich in einer verschalteten Wörterbuchstruktur speichern.
Dem grundsätzlich entnehme ich, dass es bessere Varianten gibt - ist das so ;)?
BlackJack

@MGS_Freak: Das kommt ganz darauf an was man mit den Daten anstellt. Kann man IMHO ohne mehr Kontext nichts zu sagen.
MGS_Freak
User
Beiträge: 35
Registriert: Donnerstag 13. Januar 2011, 13:50
Wohnort: Schweiz

Hm ok, versuche mal zu erörtern: Es soll ein 2-Spieler Game werden bei dem man sich gegenseitig mit -was auch immer z.B. Kampfjets - bekriegen soll, im Retro-Look. Dazu braucht es vorerst nur die Richtungstasen, später folgt noch ein Schiessbutton. Hab mir gedacht es könnte schlau sein eine Klasse (sagen wir mal "Player") zu erstellen, die sollte die Steuerung pro Spieler kennen. Bloss hab ich grad die totale Blockade in meinem Hirn und bring (wie das Beispiel am Anfang verdeutlicht) heute einfach nix auf die Reihe :(
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Wie du schon richtig erkannt hast, sind Klassen hier an sich eine gute Wahl. Es stellt sich dann natürlich die Frage, warum du keine Klassen verwendest ;-) Außerdem würde ich dein Problem eher anders herum angehen:

Code: Alles auswählen

import collections

class Player(object):
    def __init__(self, name):
        self.name = name
    
    def up(self):
        ...

    def down(self):
        ....

class Controller(object):
    def __init__(self):
        self.key_mapping = collections.defaultdict(list)

    def register(self, key, action):
        self.key_mapping[key].append(action)

    def on_key(key):
        for action in self.key_mapping[key]:
            action()

controller = Controller()
p = Player("spam")
q = Player("eggs")

controller.register(pygame.K_UP, p.up)
controller.register(pygame.K_w, q.up)
...
Das Leben ist wie ein Tennisball.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Na also eine simple Klasse könnte ja schlicht so aussehen:

Code: Alles auswählen

class Player(object):
    def __init__(self, name, up, down):
        self.name = name
        self.up = up
        self.down = down

    def __str__(self):
        return "Player({})".format(self.name)
Evtl. mag es sinnvoll sein, die Steuerung an sich in einem separaten Datentypen darzustellen. Damit ließen sich Profile leichter unabhängig von einem Spielerobjekt anpassen:

Code: Alles auswählen

class Control(object):
    def __init__(self, up, down):
        self.up = up
        self.down = down

class Player(object):
    def __init__(self, name, control):
        self.name = name
        self.control = control
Evtl. ist das aber auch übertrieben... :-D

Edit: Ok, EyDu hat da einen besseren Ansatz gefunden :-)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
MGS_Freak
User
Beiträge: 35
Registriert: Donnerstag 13. Januar 2011, 13:50
Wohnort: Schweiz

Dankeschön an alle. Um die Frage warum ich keine Klassen verwende zu beantworten: dachte es wäre übertrieben für die 3 Tasten die ich zuweise.
Wow, das mit 2 Klassen könnte das sein was sich in meinem Hirn nicht einnisten wollte ;). Versuche das mal umzusetzen und poste das Ergebnis damit ihr weiter so wunderbar konstruktive Kritik üben könnt - dieses Lob darf man sicher loswerden, gelle :)
MGS_Freak
User
Beiträge: 35
Registriert: Donnerstag 13. Januar 2011, 13:50
Wohnort: Schweiz

Oha, den Post von EyDu hatte ich übersehen :( zwecks collections werde ich die Doku bemühen. Habe mich an Hyperions Post gehalten, das Ganze sieht nun so aus:
http://www.python-forum.de/pastebin.php?mode=view&s=271

zu Testzwecken hab ich das mal importiert, 2 "Standard Layouts" erstellt und meinen player_1 damit ausgestattet, was so ausschaut:
http://www.python-forum.de/pastebin.php?mode=view&s=272

Ah ja, der Player hat nun einen Score spendiert bekommen, denke um den zu erhöhen werde ich dem Player noch eine update-Methode spendieren.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Wie ich selber schon schrieb ist die Idee von EyDu die bessere. Insofern solltest Du diese adaptieren.

- Ich kapiere nicht, wieso Du die Klassen in ein separates Modul auslagerst?

- Zudem ist das ``import pygame`` im ``player``-Modul überflüssig.

- Wieso bindest Du die Konfigurationen an Namen?

Code: Alles auswählen

player_1 = player.Player("Begi", player.Control(pygame.K_UP, pygame.K_DOWN, pygame.K_LEFT))
hätte es doch auch getan.

- Generell sollte man Namen nicht nummerieren; ok, bei zwei Spielern muss man nicht unbedingt zu einer Liste / Dictionary greifen, aber je nach späterer Logik kann sich das dennoch anbieten. Im Grunde genommen stellt das Binden an zwei separate Namen imho eher die Ausnahme dar.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
MGS_Freak
User
Beiträge: 35
Registriert: Donnerstag 13. Januar 2011, 13:50
Wohnort: Schweiz

öhm ja, collections in der Doku anschauen und so das Verständnis dafür kriegen was EyDu da genau macht -> wird noch gemacht.

rein um zu Testen obs klappt wenn ich die Player Klasse in ein Script importiere

sicher das ohne import pygame die Tasten wirklich richtig zugewiesen werden? war mir da nicht so sicher, darum der pygame import

hätte es, wieder nur zu Testzwecken

hm, wenn ich dich richtig verstehe würde ich demnach eine liste erstellen, nennen wir sie: players -> players = []. so, für jeden Spieler - gehen wir von 4 aus - erstellen wir eine Steuerung und speichern die dann in dieser Liste - wolltest Du darauf hinaus? oder hab ich Dich falsch verstanden?

Edit: für 2 Spieler würde es dann so aussehen, stimmt das?

Code: Alles auswählen

players = [Player("Begi", Control(pygame.K_UP, pygame.K_DOWN, pygame.K_LEFT)),
           Player("Schmidi", Control(pygame.K_w, pygame.K_s, pygame.K_a))]
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

MGS_Freak hat geschrieben:öhm ja, collections in der Doku anschauen und so das Verständnis dafür kriegen was EyDu da genau macht -> wird noch gemacht.
Du kannst das auch ohne ``defaultdict`` implementieren. Dann kannst Du pro Taste nur genau eine Aktion ausführen. Aber das ist im Moment bei Dir ja eh so und evtl. ja auch vollkommen ausreichend. Du kannst den Vorschlag also leicht auf ein normales Dictionary umschreiben.
MGS_Freak hat geschrieben: rein um zu Testen obs klappt wenn ich die Player Klasse in ein Script importiere
Hu? Wieso sollte das nicht klappen? Bzw. so richtig verstehe ich den "Test"zweck hier nicht...
MGS_Freak hat geschrieben: sicher das ohne import pygame die Tasten wirklich richtig zugewiesen werden? war mir da nicht so sicher, darum der pygame import
Erstens kann man sich das denken (taucht da irgend wo auch nur der Name ``pygame`` bzw. ein Name aus dem ``pygame``-Modul auf?) und zweitens kann man es leicht testen :-D

Außerdem kannst Du Dir mal ``pylint``, ``PyChecker`` oder auch ``PyFlakes`` angucken. Damit kann man u.a. unbenutzte Module ausfindig machen.

@Rest: Ja, so könnte man es umsetzen. Das hängt natürlich auch vom Spiel an sich ab. Wenn man da öfter mal über eine ID / den Namen auf ein Spielerobjekt zugreifen muss, dann bietet sich auch ein Dictionary an. Spielt dann zusätzlich noch die Reihenfolge, so kann man sich eine solche darüber hinaus als Liste merken. Das kann man pauschal nicht beantworten.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
MGS_Freak
User
Beiträge: 35
Registriert: Donnerstag 13. Januar 2011, 13:50
Wohnort: Schweiz

Du kannst das auch ohne ``defaultdict`` implementieren. Dann kannst Du pro Taste nur genau eine Aktion ausführen. Aber das ist im Moment bei Dir ja eh so und evtl. ja auch vollkommen ausreichend. Du kannst den Vorschlag also leicht auf ein normales Dictionary umschreiben.
aha, danke, versuche es umzusetzen.
Hu? Wieso sollte das nicht klappen? Bzw. so richtig verstehe ich den "Test"zweck hier nicht...
Erklärungsversuch: das Game an sich ist in einem anderen Script, darum der Test mit dem import
Erstens kann man sich das denken (taucht da irgend wo auch nur der Name ``pygame`` bzw. ein Name aus dem ``pygame``-Modul auf?) und zweitens kann man es leicht testen
tatsächlich tauchen Namen aus dem Pygame Modul auf, oder was sind für dich die Tasten pygame.K_UP/pygame.K_DOWN usw.?

für den Rest auch danke :)
BlackJack

@MGS_Freak: Wo bitte genau tauchen hier http://www.python-forum.de/pastebin.php?mode=view&s=271 irgendwelche Namen aus dem `pygame`-Modul auf!?
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

MGS_Freak hat geschrieben: tatsächlich tauchen Namen aus dem Pygame Modul auf, oder was sind für dich die Tasten pygame.K_UP/pygame.K_DOWN usw.?
Wo bitte tauchen hier diese Namen auf?

Hm... irgend wie erscheinen mir Dinge wie eine Spielerklasse ziemlich Spiel spezifisch. Muss man das wirklich in ein separates Modul auslagern? Wo liegt da Deiner Meinung nach der Vorteil?
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
MGS_Freak
User
Beiträge: 35
Registriert: Donnerstag 13. Januar 2011, 13:50
Wohnort: Schweiz

omg Sorry! Ihr beide habt natürlich vollkommen Recht!
Dort natürlich nicht, nur dann wenn es in einem Script steht - wie das im Moment nur auf meiner HD der Fall ist. Werde jetzt erstmal eine Pause einlegen (Hirnblockade lässt grüssen) und am Abend alles überarbeiten und hoffentlich kann ich Euch dann eine gute Version bieten. Danke nochmal und bis später

Edit: noch eine Stellungsnahme dazu:
Hm... irgend wie erscheinen mir Dinge wie eine Spielerklasse ziemlich Spiel spezifisch. Muss man das wirklich in ein separates Modul auslagern? Wo liegt da Deiner Meinung nach der Vorteil?
Eigentlich nur darum damit man es in mehreren Spielen erneut gebrauchen kann
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

MGS_Freak hat geschrieben: Eigentlich nur darum damit man es in mehreren Spielen erneut gebrauchen kann
Also grundsätzlich ist es ja sinnvoll, möglichst generisch zu programmieren, um Code wieder benutzen zu können. Aber bei Deinem Modell fällt alleine schon auf, dass es sehr speziell ist. Es gibt sicherlich eine Menge Spiele, die keine Steuerung benötigen, dafür aber andere Attribute als "Punkte" ;-) Da müsstest Du eh wieder eine neue Klasse erstellen.

Ich würde mich am Anfang nicht zu sehr damit verzetteln, zig Module aufzubauen. Sofern Du bei Deinem zweiten Spiel merkst, dass Du Code kopierst, kannst Du den immer noch in ein separates Modul auslagern ;-)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
MGS_Freak
User
Beiträge: 35
Registriert: Donnerstag 13. Januar 2011, 13:50
Wohnort: Schweiz

Hast Du natürlich auch Recht :). Merci, werd ich mir so zu Herzen nehmen und vorerst nicht auslagern.
MGS_Freak
User
Beiträge: 35
Registriert: Donnerstag 13. Januar 2011, 13:50
Wohnort: Schweiz

So da bin ich wieder. Neu schaut es so aus:
http://www.python-forum.de/pastebin.php?mode=view&s=273
generiert diesen Output:

Code: Alles auswählen

{273: <bound method Player.up of <__main__.Player object at 0x0277E630>>, 119: <bound method Player.up of <__main__.Player object at 0x0277E5B0>>}
. Stimmt es soweit?
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Bis auf die ungewohnten Leerzeilen im Code und den eher ungewöhnlichen Namen ``test`` für die ``main``-Funktion, sieht es doch ganz brauchbar aus. Außerdem würde ich nie ein ``print`` in dieser Form in eine Methode schreiben. Du kannst das doch auch "von außen" ausgeben lassen;:

Code: Alles auswählen

print controller.key_mapping
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Antworten