2011-01-13 32 views
1

Ich versuche mit Kollisionserkennung zu erkennen, wenn meine Maus ein Bild, das ich importiert habe, trifft. Ich den Fehler „Tupel nicht Attribut haben rect“Kollisionserkennung mit Sprites in Pygame

def main(): 


    #Call the SDL arg to center the window when it's inited, and then init pygame 
    os.environ["SDL_VIDEO_CENTERED"] = "1" 
    pygame.init() 

    #Set up the pygame window 
    screen = pygame.display.set_mode((600,600)) 


    image_one = pygame.image.load("onefinger.jpg").convert() 

    screen.fill((255, 255, 255)) 
    screen.blit(image_one, (225,400)) 
    pygame.display.flip() 

    while 1: 
     mousecoords = pygame.mouse.get_pos() 
     left = (mousecoords[0], mousecoords[1], 10, 10) 
     right = image_one.get_bounding_rect() 
     if pygame.sprite.collide_rect((left[0]+255, left[1]+400, left[2], left[3]), right): 
      print('Hi') 

Antwort

1

Das Problem ist, dass pygame.sprite.collide_rect() zwei Sprite-Objekte nimmt. Sie übergeben es zwei Tupel - weder der Cursor noch das Bild sind Sprites und daher fehlt ein rect-Attribut.

Sie könnten einen Sprite mit image_one erstellen, aber es wird schwieriger, den Cursor in einen Sprite zu konvertieren. Ich denke, es wäre einfacher, manuell zu testen, ob der Cursor innerhalb des Bildes ist.

#Set up the pygame window 
screen = pygame.display.set_mode((200,200)) 
screen.fill((255, 255, 255)) 

#Set up image properties (would be better to make an object) 
image_one = pygame.image.load("image_one.png").convert() 
image_x = 225 
image_y = 400 
image_width = image_one.get_width() 
image_height = image_one.get_height() 

# Mouse properties 
mouse_width = 10 
mouse_height = 10 

screen.blit(image_one, (image_x, image_y)) 
pygame.display.flip() 

while 1: 
    for event in pygame.event.get(): 
     if event.type == pygame.MOUSEMOTION: 
      mouse_x, mouse_y = pygame.mouse.get_pos() 

      # Test for 'collision' 
      if image_x - mouse_width < mouse_x < image_x + image_width and image_y - mouse_height < mouse_y < image_y + image_height: 
       print 'Hi!' 

Beachten Sie, dass ich testen, ob die Maus vor der Prüfung bewegt hat, ob er im Bild ist, zu vermeiden, dass die Berechnung unnötig zu wiederholen.

+0

Ausgezeichnete Hilfe! Ich habe einen noch einfacheren Weg gefunden, es zu lösen. Wenn Sie ein Bild auf einen Bildschirm "blit", gibt es ein Rect zurück. Sie ordnen einfach eine Variable zu, die gleich diesem Rect ist, z. B. FirstL_Rect = screen.blit (image_one, (185,400)), und führen dann die Kollisionserkennung mit der Funktion "colliderect" durch. Sie können Ihre mous auch in ein rect verwandeln, indem Sie einfach folgendes tun: mousecoords = pygame.mouse.get_pos() coordinateRect = Rect (mousecoords [0], mousecoords [1], 10, 10) – Parseltongue

+0

Nice one. Ich hatte nicht bemerkt, dass Blitting ein Rect zurückgibt. Das ist sehr nützlich zu wissen. –

+0

@Parseltongue: Sie müssen nicht das von '.blit()' zurückgegebene rect verwenden: 'image_one' ist eine * Surface *, und als solche können Sie immer mit 'image_one.get_rect()' rect abrufen. Keine Notwendigkeit, blit überhaupt;) – MestreLion

0

Dies ist nicht auf PyGame oder Python, kann aber helfen.

Lazy Foo hat eine Reihe von großartigen Tutorials für SDL, aber sie sind in C++. Sie sind jedoch sehr gut kommentiert. Der Link zu ihnen ist hier: http://www.lazyfoo.net/SDL_tutorials/index.php

0

Peter schlug vor, und man dachte, es auch heraus, dass es einfacher ist, mit Rects statt Positionen zu arbeiten, wenn sie mit Kollisionserkennung zu tun.

Ich würde diesen einen Schritt weiter gehen: immer mit Sprites arbeiten!

Mit Sprites erhalten Sie Zugriff auf alle diese praktischen Kollisionserkennungsfunktionen in pygame.sprite. Und wenn Sie sich dazu entschließen, das Bild zu verschieben, ist es viel einfacher, die Position zu aktualisieren und zu animieren. Es enthält auch die Bildoberfläche, alles in einem einzigen Objekt. Nicht zu erwähnen Sprite Gruppen!

Sprites haben auch ein .rect Attribut, so dass Sie immer geringe rect Manipulation tun können, wenn Sie wollen mit mysprite.rect

Das heißt, hier ist, wie Sie ein Sprite aus Ihrem Bild zu bekommen:

image_one = pygame.sprite.Sprite() 
image_one.image = pygame.image.load("image_one.png").convert() 
image_one.rect = pygame.Rect((image_x, image_y), image_one.image.get_size()) 

erstellen mehr Sprites für image_two, _three usw. oder eine Funktion (oder, noch besser, Unterklasse Sprite) erstellen, die Position und den Dateinamen als Argumente empfangen, so dass Sie Sprites in einer einzigen Linie erstellen kann als:

image_two = MySprite(filename, x, y) 

Jetzt können Sie gruppieren optional:

my_images = pygame.sprite.Group(image_one, image_two, image_three) 

Zeichnung ist so einfach wie:

my_images.draw(screen) 

Das alle Bilder auf einmal blitten wird, von denen jeder in ihrer eigene Positionen! Cool was?

ist ein "fake" Sprite für Mauszeigers Lassen Sie erstellen:

mouse = pygame.sprite.Sprite() 
mouse.rect = pygame.Rect(pygame.mouse.get_pos(), (1, 1)) 

ich es ein 1x1 Sprite gemacht haben, so dass es nur auf Maus-Hotspot kollidieren. Beachten Sie, dass es kein .image Attribut (daher "falsches" Sprite) hat, aber pygame ist es egal, da wir es sowieso nicht zeichnen werden.

Und nun das Beste:

imagehit = pygame.sprite.spritecollideany(mouse, my_images) 
print imagehit 

In einer einzigen Zeile Sie Kollision gegen getestet Alle Bilder, und nicht nur Sie wissen, wenn die Maus mit jeder kollidierte, sondern auch welches hat es getan!

Es lohnt sich wirklich, Sprites zu verwenden;)