Instanzvariable unbekannt..??

Hier werden alle anderen GUI-Toolkits sowie Spezial-Toolkits wie Spiele-Engines behandelt.
Antworten
Benutzeravatar
Don Polettone
User
Beiträge: 115
Registriert: Dienstag 23. November 2010, 20:26
Wohnort: Schweiz

Hallo und so,

ich habe im Moment echt Mühe und sehe wirklich keinen Fehler... es geht um Folgendes:

Hab mir eine Creep-Klasse gebastelt. Die hat eine update-Methode (Creeps bewegen und animieren etc), hier ein kleiner Teil davon (also die update-Methode selbst und die Methode, welche Probleme bereitet):

Code: Alles auswählen

    def get_blitpos(self):
        """Ermittelt die effektive Blitposition des Creeps"""

        x_diff = self.width - self.u
        y_diff = self.height - self.u

        self.blit_y = self.y - (self.u / 2 + y_diff)
        self.blit_x = self.x - (self.u / 2 + x_diff)
        self.blitpos = (self.blit_x, self.blit_y)

    def update(self, wave):
        self.walk()
        delta, wave = self.zielupdate(wave)                                                                            
        if delta != None:
            self.dir = richtungscheck((self.x, self.y), (self.zielpunkte[self.zielindex]))
            if delta > 0:
                self.walk(delta)                                                                                
        self.bildupdate()
        self.get_blitpos()

        return wave
Im Hauptscript wird eine Wave aus Creeps erzeugt, welche dann alle ihre update-Methode durchgehen. Das sieht etwa so aus:

Code: Alles auswählen

        wave = get_wave()
        
        for creep in wave:
            creep.einreihen(karte)
        
        while len(wave) > 0:
            
            for event in pygame.event.get():
                if event.type == QUIT:
                    pygame.quit()
                    sys.exit()
                    
            BILDSCHIRM.fill(farben.schwarz)
            BILDSCHIRM.blit(hintergrund, (0, 0))
            
            for creep in wave:
                wave = creep.update(wave)
                BILDSCHIRM.blit(creep.imagesets[str(creep.dir)][creep.cycleindex], (creep.blit_x, creep.blit_y))
            slow_motion()
Das alles hatte prächtig funktioniert - bis ich die get_blitpos() - Methode hinzugefügt habe... jetzt kommt folgende Fehlermeldung:

Traceback (most recent call last):
File "C:\Python25\Game Development\Power Defense\td_experience_nih.py", line 86, in <module>
invasion()
File "C:\Python25\Game Development\Power Defense\td_experience_nih.py", line 80, in invasion
BILDSCHIRM.blit(creep.imagesets[str(creep.dir)][creep.cycleindex], (creep.blit_x, creep.blit_y))
AttributeError: Creep instance has no attribute 'blit_x'

es kommt noch besser: Die get_blitpos()-Methode gibt's gar nicht! Macht Ihr gugg:

Code: Alles auswählen

        wave = get_wave()
        
        for creep in wave:
            creep.einreihen(karte)
            creep.get_blitpos()
...und dann heisst es:

Traceback (most recent call last):
File "C:\Python25\Game Development\Power Defense\td_experience_nih.py", line 87, in <module>
invasion()
File "C:\Python25\Game Development\Power Defense\td_experience_nih.py", line 67, in invasion
creep.get_blitpos()
AttributeError: Creep instance has no attribute 'get_blitpos'

Das gibt's doch nicht?! Sieht jemand wat wat ich nich seh..?

es grüsst:


Henry
Ich code, also bin ich.
BlackJack

@Henry Jones Jr.: Offensichtlich ist so ein Creep nicht das was Du denkst. Gib doch mal ``type(creep)``, ``creep.__class__.__module__``, und ``dir(creep)`` aus, ob da jeweils das heraus kommt, was Du erwartest.

Ansonsten ist das zu wenig Quelltext.
Benutzeravatar
Don Polettone
User
Beiträge: 115
Registriert: Dienstag 23. November 2010, 20:26
Wohnort: Schweiz

Hi BlackJack,

hab da gestern noch ein bisschen getestet. es ist wirklich merkwürdig... meine Creeps sind definitiv Instanzen von Creep() und sie kennen alle die ihnen zugewiesenen Instanzvariablen und Methoden - bis auf eben die Methode get_blitpos() und die darin verwiesenen Instanzvariablen blit_x, blit_y und blitpos, ansonsten ist alles da.

Wie gesagt war das ganze auch voll funktionsfähig und da geht schon recht wat auf dem Screen und das läuft sogar flüssig, auch wenn ich eine Wave aus 500 Creeps über den Schirm jage.. voll cool eigentlich. Ich werde heute Abend zuhause noch die ganze Creep-Klasse posten und das Hauptscript wenn's Dir recht ist, dann wäre ich froh wenn Du nochmals kurz reingugg könntest - ich verstehe es echt nicht und sehe echt keinen Sinn darin - voll schräg diese Sache.

ja bis denn dann, vielen Dank jedenfalls.


Henry
Ich code, also bin ich.
Benutzeravatar
Don Polettone
User
Beiträge: 115
Registriert: Dienstag 23. November 2010, 20:26
Wohnort: Schweiz

Hallo mal wieder,

ich bin dann mal so frei; hier mein Hauptskript:

Code: Alles auswählen

# -*- coding: cp1252 -*-

import sys, pygame
pygame.init()
from pygame.locals import *
import os
import random

from td_creeps_nih import Creep
from kartengenerator import get_karte
from wavegenerator import get_wave
import farben
import grafiken
from kartenzeichner import karte_zeichnen
from layers import get_layers

def slow_motion(mil_sek = 30):
    pygame.display.flip()
    pygame.time.delay(mil_sek)

AUFLOESUNG = (640, 480)
BILDSCHIRM = pygame.display.set_mode((AUFLOESUNG), FULLSCREEN)
hintergrund = pygame.Surface(AUFLOESUNG)

# pygame.mouse.set_visible(0) # Cursor ausblenden

def invasion():
    while True:
        hintergrund = pygame.Surface(AUFLOESUNG)
        karte = get_karte(AUFLOESUNG, "zufall", "zufall")
        hintergrund, karte = karte_zeichnen(hintergrund, karte)

        wave = get_wave()
        
        for creep in wave:
            creep.einreihen(karte)
        
        while len(wave) > 0:
            
            for event in pygame.event.get():
                if event.type == QUIT:
                    pygame.quit()
                    sys.exit()
                    
            BILDSCHIRM.fill(farben.schwarz)
            BILDSCHIRM.blit(hintergrund, (0, 0))
            
            for creep in wave:
                wave = creep.update(wave)
                
            for creep in wave:
                BILDSCHIRM.blit(creep.imagesets[str(creep.dir)][creep.cycleindex], (creep.blit_x, creep.blit_y))
                
            slow_motion()
            
        else:
            print "Alle Creeps tot! Start neu..."
            continue
        
invasion()
...und hier die Creep-Klasse:

Code: Alles auswählen

# -*- coding: cp1252 -*-

import grafiken
import zufall
from karte_x import richtungscheck
import random

creeps = {}

creeps["blob"] = {"x_cycles" : 6, "y_cycles" : 6, "cycletrigger" : 8, "distance" : None, "speed" : 8, "hp" : 100}
creeps["bat"] = {"x_cycles" : 2, "y_cycles" : 2, "cycletrigger" : 12, "distance" : None, "speed" : 8, "hp" : 100}

def get_imagesets(typ, cycle_x, cycle_y):
    """"gibt das Imageset des Creeps name zurück"""

    pfad = "Creeps"

    abc = ("a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m")
    x_cycles = abc[:cycle_x]
    y_cycles = abc[:cycle_y]
    
    directions = ("2", "8", "6", "4")
    imageset = {}

    for direction in directions:
        bilder = []
        
        if direction in ("2", "8"):
            cycles = y_cycles
        elif direction == "6":
            cycles = x_cycles
            
        if direction in ("2", "8", "6"):
            for n in cycles:
                bildname = typ + "_" + direction + n + ".png"
                bild = grafiken.bild_laden(pfad, bildname, True)
                bilder.append(bild)
            imageset[direction] = bilder
            
        elif direction == "4":
            for n in imageset["6"]:
                bild = grafiken.bild_spiegeln(n, True, False)
                bilder.append(bild)
            imageset[direction] = bilder

    return imageset

class Creep():
    """Erzeugt ein Creep"""

    def __init__(self, typ):

        self.typ = typ
        self.steps = 0
        self.cyclecounter = 0
        self.cycleindex = None
        self.zielindex = 0
        if not creeps[typ]["distance"]:
            self.distance = 56
        else:
            self.distance = creeps[typ]["distance"]
        self.cycletrigger = creeps[typ]["cycletrigger"]
        self.hp = creeps[typ]["hp"]
        self.speed = creeps[typ]["speed"]
        self.imagesets = get_imagesets(typ, creeps[typ]["x_cycles"], creeps[typ]["y_cycles"])
        self.height, self.width = self.imagesets["2"][0].get_height(), self.imagesets["2"][0].get_width()

    def get_zielpunkte(self, karte):
        """Erstellt die Liste mit den Zielpunkten für das Creep -> self.zielpunkte"""

        ### weil die Tiles der Karte grösser sind als die Creeps, muss deren Position korrigiert werden -> y_korrektur ###

        u = self.u = karte["u"]
        self.zielpunkte = []

        for pos in karte["wegpos"]:
            zielpunkt = (pos[0] + u / 2, pos[1] + u / 2)
            self.zielpunkte.append(zielpunkt)

        ### Zielpunkt berechnen und zu zielpunkte hinzufügen ###

        letzter_wegpunkt = self.zielpunkte[-1]
        zielrichtung = karte["zielrichtung"]
        
        if zielrichtung == 8:
            zielpos = (letzter_wegpunkt[0], 0 - self.height)
        elif zielrichtung == 2:
            zielpos = (letzter_wegpunkt[0], 480 + self.height)
        elif zielrichtung == 6:
            zielpos = (640 + u, letzter_wegpunkt[1])
        else:
            zielpos = (0 - u, letzter_wegpunkt[1])
            
        self.zielpunkte.append(zielpos)

    def einreihen(self, karte):
        """Stellt die Creeps in einer Reihe in Ausgangsposition auf"""

        u = karte["u"]

        self.dir = karte["startrichtung"]
        
        self.get_zielpunkte(karte)

        distance = self.distance * self.nr
        wegpunkt_1 = self.zielpunkte[self.zielindex]

        if self.dir in (8, 2):
            self.x = wegpunkt_1[0]
            if self.dir == 2:
                start_y = 0
                self.y = start_y - distance
            elif self.dir == 8:
                start_y = 480
                self.y = start_y + distance
        else:
            self.y = wegpunkt_1[1]
            if self.dir == 6:
                start_x = 0
                self.x = start_x - distance
            elif self.dir == 4:
                start_x = 640
                self.x = start_x + distance

    def zielupdate(self, wave):
        """Üperprüft, ob der nächste wegpunkt erreicht wurde und ändert self.zielindex und self.dir"""
            
        zielpos = self.zielpunkte[self.zielindex]
        delta = None # wenn das Creep seinen aktuellen Zielpunkt noch nicht erreicht hat, bleibt delta auch None
        
        if self.dir == 8:
            if self.y <= zielpos[1]: # wenn Zielpunkt erreicht oder überschritten...
                if self.zielindex == len(self.zielpunkte) - 1:
                    wave.remove(self)
                    del self
                else:
                    delta = zielpos[1] - self.y
                    self.y = zielpos[1]
                    self.zielindex += 1
        elif self.dir == 2:
            if self.y >= zielpos[1]:
                if self.zielindex == len(self.zielpunkte) - 1:
                    wave.remove(self)
                    del self
                else:
                    delta = self.y - zielpos[1]
                    self.y = zielpos[1]
                    self.zielindex += 1
        elif self.dir == 6:
            if self.x >= zielpos[0]:
                if self.zielindex == len(self.zielpunkte) - 1:
                    wave.remove(self)
                    del self
                else:
                    delta = self.x - zielpos[0]
                    self.x = zielpos[0]
                    self.zielindex += 1
        else:
            if self.x <= zielpos[0]:
                if self.zielindex == len(self.zielpunkte) - 1:
                    wave.remove(self)
                    del self
                else:
                    delta = zielpos[0] - self.x
                    self.x = zielpos[0]
                    self.zielindex += 1

        return (delta, wave) # wenn delta hier noch None ist, fand keine Richtungsänderung statt

    def walk(self, speed = None):
        """Bewegt das Creep anhand self.speed und self.dir"""
        
        if speed == None:
            self.steps += self.speed
            speed = self.speed
        else:
            pass
        
        if self.dir == 8:
            self.y -= speed
        elif self.dir == 2:
            self.y += speed
        elif self.dir == 6:
            self.x += speed
        else:
            self.x -= speed

    def bildupdate(self):
        """Errechnet, ob das Bild geändert werden soll und ändert dann self.cycleindex"""                        # LAUFANIMATION #

        imageset = self.imagesets[str(self.dir)]                                                        # anhand self.dir wird das aktuelle Imageset bestimmt

        if self.cycleindex == None:                                                                                 # eigentlich hätte ich dies ganz am Anfang dieser Methode wollen, aber...
            self.cycleindex = zufall.index_x(self.imagesets[str(self.dir)])                                          # ...ohne, dass zuerst das aktuelle imageset inittet wird funzt das nicht...

        self.cyclecounter += self.speed                                                                 # anhand der zurüggelegten Strecke seit dem letzten Bildwechsel wird...
        if self.cyclecounter >= self.cycletrigger:
            self.cyclecounter = 0                                                                            # ...allenfalls wieder das Bild gewechselt (oder besser der Index des Imagesets :-) )
            if self.cycleindex < (len(imageset) - 1):
                self.cycleindex += 1
            else:
                self.cycleindex = 0

    def get_blitpos(self):
        """Ermittelt die effektive Blitposition des Creeps"""

        x_diff = self.width - self.u
        y_diff = self.height - self.u

        self.blit_y = self.y - (self.u / 2 + y_diff)
        self.blit_x = self.x - (self.u / 2 + x_diff)
        self.blitpos = (self.blit_x, self.blit_y)

    def update(self, wave):
        self.walk()
        delta, wave = self.zielupdate(wave)                                                                            
        if delta != None:
            self.dir = richtungscheck((self.x, self.y), (self.zielpunkte[self.zielindex]))
            if delta > 0:
                self.walk(delta)                                                                                
        self.bildupdate()
        self.get_blitpos()

        return wave
mein Problem ist wie gesagt, dass meine Creep-Instanzen die Methode get_blitpos(self) nicht kennen wollen... ansonsten ist aber alles da und funzt prächtig. Wenn ich zum Beispiel mal print dir(creep) aufrufe (für jedes Creep in der Wave), sieht das so aus:

['__doc__', '__init__', '__module__', 'bildupdate', 'cyclecounter', 'cycleindex', 'cycletrigger', 'dir', 'distance', 'einreihen', 'get_zielpunkte', 'height', 'hp', 'imagesets', 'nr', 'speed', 'steps', 'typ', 'update', 'walk', 'width', 'x', 'y', 'zielindex', 'zielpunkte', 'zielupdate']
['__doc__', '__init__', '__module__', 'bildupdate', 'cyclecounter', 'cycleindex', 'cycletrigger', 'dir', 'distance', 'einreihen', 'get_zielpunkte', 'height', 'hp', 'imagesets', 'nr', 'speed', 'steps', 'typ', 'update', 'walk', 'width', 'x', 'y', 'zielindex', 'zielpunkte', 'zielupdate']

etc etc (sind ja viele Creeps am Start). Aber da steht nix von get_blitpos, obwohl dies ganz klar eine Methode der Creep-Klasse ist... wenn ich nun die Creeps an ihrer blitpos auf den Screen blitten will (nachdem deren update-Methode ausgeführt wurde, welche wiederum die get_blitpos-Methode aufruft), steht da:

Traceback (most recent call last):
File "C:\Python25\Game Development\Power Defense\td_experience_nih.py", line 61, in <module>
invasion()
File "C:\Python25\Game Development\Power Defense\td_experience_nih.py", line 53, in invasion
BILDSCHIRM.blit(creep.imagesets[str(creep.dir)][creep.cycleindex], (creep.blit_x, creep.blit_y))
AttributeError: Creep instance has no attribute 'blit_x'

Jemand eine Idee..? Das gibt's doch nicht?? Super lustig ist auch, dass, wenn ich die get_blitpos-Methode innerhalb des Creep Moduls abrufe, diese tadellos funktioniert. Aber wenn die Creeps im Hauptskript deren update-Methode duchgehen, scheint es so, als ob diese die Methode get_blitpos gar nicht aufrufen würde!

Sorry ich versteh die Welt nicht mehr. Bis jetzt hat doch alles funktioniert..?! Wenn ich blitpos weglasse, ist da voll Rock'nRoll:

Bild

und da mache ich nix Anderes, als die Viecher einfach anstelle von blit_x und blit_y anhand von x und y zu blitten - auch diese Werte werden innerhalb der update-Methode verändert und das geht! Ist doch eigentlich dasselbe? Ich sehe keinen Unterschied und ich komme wirklich, wirklich nicht mehr weiter...

viele Grüsse,


Henry
Ich code, also bin ich.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Hallo.

Du solltest deinen Code in ein Pastebin auslagern (oben ist sogar eins verlinkt), sonst kann man dem Inhalt des Threads nur noch schwer folgen.

Ich habe es mal ganz kurz überfolgen und mir scheinen diese Zeilen etwas seltsam:

Code: Alles auswählen

for creep in wave:
    wave = creep.update(wave)
Sebastian
Das Leben ist wie ein Tennisball.
Benutzeravatar
Don Polettone
User
Beiträge: 115
Registriert: Dienstag 23. November 2010, 20:26
Wohnort: Schweiz

Ciao EyDu,

nun, ich habe das gerade "pastegebint" aber wo andert das denn hin..? Ist einfach weg... Sorry, hab noch dat noch nie gemacht...

??

Gruss,


Henry
Ich code, also bin ich.
Benutzeravatar
Don Polettone
User
Beiträge: 115
Registriert: Dienstag 23. November 2010, 20:26
Wohnort: Schweiz

Ach Du heilige...

sorry zusammen - Fehlalarm. Habe den Fehler gefunden. Echt peino... :shock:

Trotzdem danke für die Tpps.

Hellas,


Henry
Ich code, also bin ich.
Antworten