Pygame, problem mit Python 2.6

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Berserker55
User
Beiträge: 6
Registriert: Sonntag 18. Oktober 2009, 20:18

Mein Programm supi in Python 3.1 aber in 2.6 was ich immernoch benötige um eine exe zu bauen gibt es ein Problem.
Entweder ich lös das Problem oder ich finde eine Möglichkeit eine Python 3.1 Exe zu bauen, naja,- hier der Fehler:
TypeError: unbound method fire() must be called with TripleSmallBlue instance as
first argument (got Player4 instance instead)
Der Fehler tritt auf wenn gefeuert wird, also wenn self.weapon.fire(self) in player4.update ausgelöst wird.

was mir auffällt is das die methode fire in python 3.1 eine function at xxxxxx ist, anstelle von unbound.

nun der Relevante Code:

Code: Alles auswählen


class Player4(Sprite): # Bomber
    def __init__(self, screen, playerimagefilename, initialposition, initialdirection, up, right, down, left, playerspeed, color, number, playermode):
        Sprite.__init__(self)
        self.screen = screen
        self.base_image = pygame.image.load(playerimagefilename).convert_alpha()
        self.image = self.base_image
        self.playermode = playermode
        self.image_w, self.image_h = self.image.get_size()
        self.score = 0
        self.scored = False
        self.bounderror = False
        self.up = up
        self.right = right
        self.down = down
        self.left = left
        self.speed = float(playerspeed)
        self.max_speed = 3
        self.acceleration = 0.1
        self.pos = vec2d.vec2d(initialposition)
        self.direction = vec2d.vec2d(initialdirection).normalized()
        self.rotationspeed = 1
        self.rotation = 0
        self.min_speed = -1
        self.color = color
        self.rect = self.image.get_rect().move(self.pos.x - self.image_w / 2, self.pos.y - self.image_h / 2)

        self.fire = 50
        self.number = number
        self.set_weapon(TripleSmallBlue)
    def set_weapon(self, weapon):
        self.weapon = weapon#(self)
    def pupdate(self):
        if self.scored == False:
            
            .... (viele Sachen, gekürzt) ....
            if self.fire <= 0:
                
                self.weapon.fire(self)
                self.fire += 50
                
            self.fire -=1

Code: Alles auswählen

class Laser(Sprite):
    def __init__(self, initialposition, initialdirection, number, rotation = 0, speed = 10):
        Sprite.__init__(self)
        self.image = pygame.image.load(os.path.join("data/Sprites", "Projectile.png")).convert_alpha()
        self.pos = vec2d.vec2d(initialposition)
        self.direction = vec2d.vec2d(initialdirection).normalized()
        self.direction.rotate(rotation)
        self.image_w, self.image_h = self.image.get_size()
        self.rect = self.image.get_rect().move(self.pos.x - self.image_w / 2, self.pos.y - self.image_h / 2)
        self.life = 200
        self.speed = speed
        self.damage = 1
        self.pnumber = number
    def update(self):
        if 1 > self.life:
            self.kill()
        displacement = vec2d.vec2d(    
            self.direction.x * self.speed, 
            self.direction.y * self.speed)
        self.pos += displacement
        self.rect = self.image.get_rect().move(self.pos.x - self.image_w / 2, self.pos.y - self.image_h / 2)
        self.life -= 1

Code: Alles auswählen

class TripleSmallBlue:
    def fire(player):
        Game.projectiles.add(Laser(player.pos, player.direction, player.number))
        Game.projectiles.add(Laser(player.pos, player.direction, player.number, rotation = 3))
        Game.projectiles.add(Laser(player.pos, player.direction, player.number, rotation = -3))
Zuletzt geändert von Berserker55 am Sonntag 18. Oktober 2009, 21:50, insgesamt 2-mal geändert.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Interessant wäre einmal die genaue Code-Stelle gewesen, an der der Fehler auftritt! Leider ist Dein Fehler-Paste da ein wenig zu kurz...
Berserker55
User
Beiträge: 6
Registriert: Sonntag 18. Oktober 2009, 20:18

Hyperion hat geschrieben:Interessant wäre einmal die genaue Code-Stelle gewesen, an der der Fehler auftritt! Leider ist Dein Fehler-Paste da ein wenig zu kurz...
....>python "Evade Game.pyw"
using psyco
__main__.TripleSmallBlue
Traceback (most recent call last):
File "Evade Game.pyw", line 2271, in <module>
MainMenu()
File "Evade Game.pyw", line 2161, in MainMenu
G.selection()
File "Evade Game.pyw", line 1516, in selection
self.main(data, playerdata)
File "Evade Game.pyw", line 1717, in main
self.players.pupdate()
File "Evade Game.pyw", line 1044, in pupdate
self.weapon.fire(self)
TypeError: unbound method fire() must be called with TripleSmallBlue instance as
first argument (got Player4 instance instead)
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Code: Alles auswählen

self.weapon.fire(self) 
Was ist denn self hier? Was weapon? Ich vermute mal, dass self vom Typ Player4 ist... wenn weapon vom Typ TripleSmallBlue ist. Dessen fire()-Methode erwartet aber keinen expliziten Parameter...

Mich wundert nur, dass das unter Python 3.1 laufen soll.
Berserker55
User
Beiträge: 6
Registriert: Sonntag 18. Oktober 2009, 20:18

Hyperion hat geschrieben:

Code: Alles auswählen

self.weapon.fire(self) 
Was ist denn self hier? Was weapon? Ich vermute mal, dass self vom Typ Player4 ist... wenn weapon vom Typ TripleSmallBlue ist. Dessen fire()-Methode erwartet aber keinen expliziten Parameter...

Mich wundert nur, dass das unter Python 3.1 laufen soll.

self.weapon.fire(self)
Erstes self ist player4,
in player4 ist die variable weapon die classe TripleSmallBlue (siehe set_weapon ** siehe ende) und löst darüber Fire aus.
Das self in den Klammern ist reduntant. Kam dazu beim testen, aber mit oder ohne macht überhaubt keinen Unterschied.

*edit* is doch nich reduntant, ohne geths nicht.
aber im Grunde löse ich übers erste self das fire aus, und übers zweite self übergebe ich die spielerinfo ans geschoss (um später die Score zuzuweisen, Geschwindigkeit, richtung etc.)


*edit2*
wenn ich mit explizit TripleSmallBlue.fire(self) schieße passiert exakt dasselbe, in py31 supi und py26 versagt

** Code:

Code: Alles auswählen

        self.set_weapon(TripleSmallBlue) 
    def set_weapon(self, weapon): 
        self.weapon = weapon#(self)
BlackJack

@Hyperion: Vielleicht prüft Python 3 nicht mehr, ob das erste Objekt vom richtigen Typ ist. Hängt vielleicht damit zusammen, dass "Methoden" auf den Klassen jetzt (AFAIK wieder) ganz normale Funktionen sind und nicht mehr vom Typ "unbound method".

@Berserker55: An Deinem Entwurf ist IMHO etwas schief. Du erstellst gar keine Exemplare von `TripleSmallBlue`, sondern rufst die Funktionen auf dem Klassenobjekt auf. Also missbrauchst Du die Klasse als Namensraum für Funktionen, und statt wenigstens statische Methoden daraus zu machen, verwendest Du weiter die Namenskonvention mit `self`, was semantisch falsch und *extrem* irreführend ist.
Berserker55
User
Beiträge: 6
Registriert: Sonntag 18. Oktober 2009, 20:18

BlackJack hat geschrieben:@Hyperion: Vielleicht prüft Python 3 nicht mehr, ob das erste Objekt vom richtigen Typ ist. Hängt vielleicht damit zusammen, dass "Methoden" auf den Klassen jetzt (AFAIK wieder) ganz normale Funktionen sind und nicht mehr vom Typ "unbound method".

@Berserker55: An Deinem Entwurf ist IMHO etwas schief. Du erstellst gar keine Exemplare von `TripleSmallBlue`, sondern rufst die Funktionen auf dem Klassenobjekt auf. Also missbrauchst Du die Klasse als Namensraum für Funktionen, und statt wenigstens statische Methoden daraus zu machen, verwendest Du weiter die Namenskonvention mit `self`, was semantisch falsch und *extrem* irreführend ist.
Ja ich benutze die Waffenklassen wie TripleSmallBlue als zwischenblock um dann "Laser" Klassen zu erstellen

ich glaub ich werd mal versuchen das aus den klassen rauszunehmen und die als lose Funktionen zu nutzen.

Fands aber als Klassen übersichtlicher und in python 3.1 gehts ja.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Ich bin im Erklären von "self" sicher nicht besonders fit, aber generell gibt es kein 1. und kein 2. self. self ist eben im Kontext des Code-Blockes immer eindeutig und eine Art Zeiger auf die aktuelle Klasse.

Code: Alles auswählen

In [10]: class Foo(object):
   ....:     def __init__(self):
   ....:         print self, type(self)
   ....:
   ....:

In [11]: f = Foo()
<__main__.Foo object at 0x7fa0838aff90> <class '__main__.Foo'>
Wenn Du mit self.weapon auf ein TripleSmallBlue-Objekt aus der Player4-Klasse zugreifst, dann ist self eben die Referenz auf die Player4-Klasse, in der Du Dich befindest. Die fire()-Methode ist aber ja Bestandteil der TripleSmallBlue Klasse - wenn Du der also etwas anderes als self vorwirfst, muss der Python-Interpreter ja eben denken, dass fire() zu einem anderen Objekt gehört.

Hm... das klingt irgend wie verworren, aber besser bekomme ich das jetzt nicht hin ;-)

Zeig doch mal bitte den Code-Schnipsel um den Aufruf herum! Der ist oben nicht zu sehen, wenn ich das richtig gesehen habe.
BlackJack

@Berserker55: Ob etwas geht, und ob man es machen sollte, sind zwei verschiedene Dinge. Etwas in einer Methode `self` zu nennen, was *nicht* ein Exemplar der Klasse repräsentiert, in der die Methode steckt, ist eine *sehr* schlechte Idee, weil das alles andere als übersichtlich ist. Damit rechnet einfach niemand, folglich sorgt das für Verwirrung, wenn man den Quelltext verstehen will.
Berserker55
User
Beiträge: 6
Registriert: Sonntag 18. Oktober 2009, 20:18

an der stelle brauch ich wirklich 2 mal self.
wie gesagt ich kann explizit die Klasse rufen aber das ist normalerweise änderbar (Waffenwechsel) self.weapon verweist einfach nur an die eigene Waffe, die Spielerdaten muss ich ich dann immernoch mit fire(self) übergeben, sonst krieg ich die halt nich.

und das self innerhalb TripleSmallBlue kann wohl alles sein, aber ich seh das mehr als teil des Spielers, also hab ichs self genannt. könnte auch player nehmen, oder wasauchimmer, da habt ihr recht

*edit* self in player geändert wo ging, im Eröffnungstext
Ändert aber nix am Problem

OKI, wenn ich TripleSmallBlue auseinandernehme und nich als Klasse nehme, sonder als lose Funktion dann funktioniert es, is aber unhübsch da ich sonst alles in Klassen hab, gibts da keine Möglichkeit für in Python 26?

Code: Alles auswählen

def fire_TripleSmallBlue(player):
    Game.projectiles.add(Laser(player.pos, player.direction, player.number))
    Game.projectiles.add(Laser(player.pos, player.direction, player.number, rotation = 3))
    Game.projectiles.add(Laser(player.pos, player.direction, player.number, rotation = -3))
BlackJack

@Berserker55: Alles in Klassen stecken ist nur "hübsch", wenn es Sinn macht. Klassen und OOP sind kein Selbstzweck. Lösungen ausser Funktionen gibt es, und zwei wurden im Grunde auch genannt: Exemplare der Klasse erstellen und die verwenden. Statische Methoden. Was eigentlich dann wieder Funktionen sind.

Also ich würde die Klasse halt einfach wie eine Klasse verwenden und Exemplare davon erstellen.

Edit: Das `Game` in der Feuer-Funktion gross geschrieben ist, lässt auch einen unschönen Entwurf erahnen.
Berserker55
User
Beiträge: 6
Registriert: Sonntag 18. Oktober 2009, 20:18

Ja Klasse jetzt isses Feuern in Python 31 kapott :roll:
Also weitersuchen...

Die Waffe wird aus irgendwelchen Gründen in Python 31 nich gesetzt also bei

Code: Alles auswählen

        self.set_weapon(fire_TripleSmallBlue)

    def set_weapon(self, weapon):

        self.weapon = weapon
kommt am ende self.weapon == None raus :(

*edit* Gelöst

Perfect fänd ich einfach bloß Py2exe für Python3.1....

Mir fällt grad auf ich bin im falschen subforum, ich dachte ich hätt sonstige ausgewählt gehabt...
naja das Problem war ja eh ein Allgemeines, nichts in Bezug auf Pygame

Danke für die Hilfe beim finden des Problems.
Aber ein bischen weniger auf die "Schreibweise" rumhacken wär nett gewesen.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Berserker55 hat geschrieben:Aber ein bischen weniger auf die "Schreibweise" rumhacken wär nett gewesen.
Dann solltest du PEP 8 lesen und verinnerlichen. Sonst wird man dich bei jeder deiner Frage darauf hinweisen ;-)
Das Leben ist wie ein Tennisball.
Antworten