Habe versucht einen Spritecounter (classenvariable blogcounter) mit pygame zu erstellen, dabei tritt aber manchmal folgende ignorierte Fehlermeldung auf:
und der Spritezähler der Classenvariable (blogcounter) liefert andere (falsche) Werte als der zähler der Spritegruppe len(spritegroup).Exception exceptions.AttributeError: "'NoneType' object has no attribute 'blobcounter'" in <bound method Blob.__del__ of <Blob sprite(in 0 groups)>> ignored
Was muss ich machen um die Anzahl der Sprites per Klassenvariable fehlerfrei anzeigen zu können ?
Das Programm dazu schaut so aus, bitte öfter auf "+" oder "-" drücken um die Diskrepanz zwischen len(spritegroup) und blogcounter zu sehen.
Code: Alles auswählen
# -*- coding: utf-8 -*-
"""
problem3.py
problem counting the sprites in a group
python 2.5, pygame 1.8.1
author: Horst JENS, www.spielend-programmieren.at
email: pygamebook@gmail.com
press + and - (several times) to see the effect.
len(spritegroup) gives (after a while) different result than blobcounter (class variable)
"""
import pygame
import random
pygame.init()
screen=pygame.display.set_mode((640,480))
pygame.display.set_caption("press Esc to exit")
background = pygame.Surface(screen.get_size()) # background
background.fill((255,255,255)) #fill the background white
class Blob(pygame.sprite.Sprite):
"""a small independent moving Circle"""
blobcounter = 0 # class variable, not an object variable, therfore no "self."
def __init__(self, border = False):
self.crash = False
self.border = border
pygame.sprite.Sprite.__init__(self)
mycircle = pygame.Surface((50,50))
pygame.draw.circle(mycircle, (0,255,0), (25,25), 25, 0)
mycircle.set_colorkey((0,0,0))
self.imageN = mycircle
self.imageN.convert()
self.imageB = self.imageN.copy()
pygame.draw.rect(self.imageB, (255,0,255), (0,0,50,50),1)
self.imageB.convert()
self.image = self.imageN
self.rect = self.image.get_rect()
self.TrueX = random.randint(0,screen.get_width()) + 0.0
self.TrueY = random.randint(0,screen.get_height())+ 0.0
self.rect.centerx = round(self.TrueX,0)
self.rect.centery = round(self.TrueY,0)
self.speedx = 0.0
self.speedy = 0.0
self.newspeed()
Blob.blobcounter += 1 # change Class-variable, no self !
def __del__(self):
print "i leave" # the Spritemethod kill() calls __del__ and remove the sprite from all groups
print "Blobs before:", Blob.blobcounter
Blob.blobcounter -= 1
print "Blobs after:", Blob.blobcounter
if Blob.blobcounter >0:
print "len(blobsprites):",len(blobsprites)
def newspeed(self):
self.speedx = random.random() * 4 -2 # a float between -2 and +2
self.speedy = random.random() * 4 -2
def avoid(self, othercenterx, othercentery):
if othercenterx > self.TrueX:
self.TrueX -= 1.0
else:
self.TrueX += 1.0
if othercentery > self.TrueY:
self.TrueY -= 1.0
else:
self.TrueY += 1.0
self.crash = True
def update(self, border = False):
if border:
self.image = self.imageB # routine to draw border if necessary
else:
self.image = self.imageN
if not self.crash:
self.TrueX += self.speedx #move
self.TrueY += self.speedy
else:
self.crash = False
if self.TrueX > screen.get_width():
self.TrueX = screen.get_width() #bounce
self.newspeed()
if self.TrueX < 0:
self.TrueX = 0
self.newspeed()
if self.TrueY > screen.get_height():
self.TrueY = screen.get_height()
self.newspeed()
if self.TrueY < 0:
self.TrueY = 0
self.newspeed()
# calculate new position
self.rect.centerx = round(self.TrueX,0) # make integer out of float
self.rect.centery = round(self.TrueY,0)
blobsprites = pygame.sprite.Group()
blobsprites.add(Blob(),Blob(), Blob(), Blob(),Blob()) # add five Blobs into the world
allsprites = pygame.sprite.LayeredUpdates(blobsprites) # later, put other sprites here
showBorder = False
myFont = pygame.font.SysFont("None",20)
textsurface1 = myFont.render("pres + or - (several times) to add or remove sprites. pres b to toggle border", True, (0,0,255))
textsurface2 = myFont.render("press ESC or q to quit", True, (0,0,255))
textsurface3 = myFont.render("why does the len(spritegroup) does not always sync with blobcounter ?", True, (255,0,0))
background.blit(textsurface1, (100, screen.get_height()/2))
background.blit(textsurface2, (100, screen.get_height()/2+20))
background.blit(textsurface3, (100, screen.get_height()/2+40))
screen.blit(background, (0,0)) # blit the backgroundsurface on the screen
clock = pygame.time.Clock()
playmainloop = True
#main loop
while playmainloop:
#deltatime = clock.tick(30)
clock.tick(30)
#event handler
for event in pygame.event.get():
if event.type == pygame.QUIT:
playmainloop = False #user close pygame window with mouse
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE or event.key == pygame.K_q:
playmainloop = False #quit
elif event.key == pygame.K_b:
showBorder = not showBorder # toggle between True and False
elif event.key == pygame.K_PLUS:
blobsprites.add(Blob()) # create a new Blob
allsprites = pygame.sprite.LayeredUpdates(blobsprites) # recalculate the allsprites group
screen.blit(background,(0,0)) #redraw the background to remove artefachts
elif event.key == pygame.K_MINUS:
for killblob in blobsprites:
killblob.kill() # spritemethod, remove the sprite from all groups
break # only kill one sprite at this time
# collision detection
#Blob crash into Blob ?
for blob in blobsprites:
othergroup = blobsprites.copy()
othergroup.remove(blob) # a copy of the group without the current penguin
if pygame.sprite.spritecollideany(blob, othergroup):
# there was a collision, but with whom ?
for crashblob in pygame.sprite.spritecollide(blob, othergroup, False):
blob.avoid(crashblob.rect.centerx, crashblob.rect.centery)
#blob.newspeed()
# decorate pygame window
pygame.display.set_caption("Border: %s , Blobs (len spritegroup): %i ,blobcounter (class Variable) %i "
% (str(showBorder), len(blobsprites), Blob.blobcounter))
allsprites.clear(screen, background)
if showBorder:
allsprites.update(True)
else:
allsprites.update(False)
allsprites.draw(screen)
pygame.display.flip()
#--end of loop
pygame.quit() #idle-friendly quit