2017-04-18 70 views
1

我在PyGame中創建了兩個簡單的精靈,其中一個是傘,另一個是雨滴。 雨滴被添加到名爲all_sprites的精靈組中。傘形精靈有自己的組Umbrella_spritePygame - 雪碧與Sprite組的碰撞

雨滴從屏幕頂部「下降」,如果其中一個接觸雨傘/與其碰撞..雨滴應該被刪除。 但是,而不是那個特定的雨滴所有其他受這個影響。

主文件(rain.py)

#!/usr/bin/python 
VERSION = "0.1" 
import os, sys, raindrop 
from os import path 

try: 
    import pygame 
    from pygame.locals import * 
except ImportError, err: 
    print 'Could not load module %s' % (err) 
    sys.exit(2) 

# main variables 
WIDTH, HEIGHT, FPS = 300, 300, 30 

# initialize game 
pygame.init() 
screen = pygame.display.set_mode((WIDTH,HEIGHT)) 
pygame.display.set_caption("Rain and Rain") 

# background 
background = pygame.Surface(screen.get_size()) 
background = background.convert() 
background.fill((40,44,52)) 

# blitting 
screen.blit(background,(0,0)) 
pygame.display.flip() 

# clock for FPS settings 
clock = pygame.time.Clock() 


def main(): 
    all_sprites = pygame.sprite.Group() 
    umbrella_sprite = pygame.sprite.Group() 
    # a function to create new drops 
    def newDrop(): 
     nd = raindrop.Raindrop() 
     all_sprites.add(nd) 

    # creating 10 rain drops 
    for x in range(0,9): newDrop() 

    # variable for main loop 
    running = True 

    # init umbrella 
    umb = raindrop.Umbrella() 
# all_sprites.add(umb) 
    umbrella_sprite.add(umb) 

    # event loop 
    while running: 
     clock.tick(FPS) 
     for event in pygame.event.get(): 
      if event.type == pygame.QUIT: 
       running = False 

     for enemy in all_sprites: 
      gets_hit = pygame.sprite.spritecollideany(umb, all_sprites) 
      if gets_hit: 
       all_sprites.remove(enemy) 

     screen.blit(background,(100,100)) 

     # clear 
     all_sprites.clear(screen,background) 
     umbrella_sprite.clear(screen,background) 

     # update 
     all_sprites.update() 
     umbrella_sprite.update() 

     # draw 
     all_sprites.draw(screen) 
     umbrella_sprite.draw(screen) 

     # flip the table 
     pygame.display.flip() 
    pygame.quit() 

if __name__ == '__main__': 
    main() 

raindrop.py(雨滴()&傘())

import pygame 
from pygame.locals import * 
from os import path 
from random import randint 
from rain import HEIGHT, WIDTH 

img_dir = path.join(path.dirname(__file__), 'img') 

class Raindrop(pygame.sprite.Sprite): 
    def __init__(self): 
     pygame.sprite.Sprite.__init__(self) 
     self.width = randint(32, 64) 
     self.height = self.width + 33 
     self.image = pygame.image.load(path.join(img_dir, "raindrop.png")).convert_alpha() 
     self.image = pygame.transform.scale(self.image, (self.width, self.height)) 
     self.speedy = randint(1, 15) 
     self.rect = self.image.get_rect() 
     self.rect.x = randint(0, 290) 
     self.rect.y = -self.height 

    def reset(self): 
     self.rect.y = -self.height 

    def update(self): 
     self.rect.y += self.speedy 
     if self.rect.y >= HEIGHT: 
      self.rect.y = -self.height 
      self.rect.x = randint(0, 290) 

class Umbrella(pygame.sprite.Sprite): 
    def __init__(self): 
     pygame.sprite.Sprite.__init__(self) 
     self.width = 50 
     self.height = 50 
     self.image = pygame.image.load(path.join(img_dir,"umbrella.png")).convert_alpha() 
     self.image = pygame.transform.scale(self.image, (self.width, self.height)) 
     self.speedx = 10 
     self.rect = self.image.get_rect() 
     self.rect.x = (WIDTH/2) - self.width 
     self.rect.y = (0.7 * HEIGHT) 

    def update(self): 
     keys = pygame.key.get_pressed() 
     if keys[pygame.K_LEFT] and self.rect.x > 0: 
      self.rect.x -= self.speedx 
     elif keys[pygame.K_RIGHT] and self.rect.x < (WIDTH - self.width): 
      self.rect.x += self.speedx 
+1

不要在問題中發佈您的代碼。創建一個[mcve]來代替它,這將使其對具有相同問題的其他人更有益,因爲它使得它更易讀,更易於理解和更一般化(而不是將它作爲問題呈現爲問題)。 –

+0

我認爲這實際上是一個非常簡單和完整的例子。 (Py)遊戲例子往往比較大。標題應改爲「for循環中的spritecollideany刪除太多精靈」,並且bug for循環可以單獨發佈。 – skrx

回答

1

這是你的問題:

for enemy in all_sprites: 
    gets_hit = pygame.sprite.spritecollideany(umb, all_sprites) 
    if gets_hit: 
     all_sprites.remove(enemy) 

你正在循環組中,如果有任何精靈發生衝突,則刪除它們。

你不需要在組中循環 - 碰撞函數會處理這個問題。你只需要使用spritecollide函數,它比較一個精靈和一個組。該函數將返回碰撞的列表,以及使用DOKILL標誌自動刪除:如果精靈跟團返回此精靈任何精靈碰撞

 gets_hit = pygame.sprite.spritecollide(umb, all_sprites, True) 
+0

非常感謝你的男人! :d –

1

spritecollideany檢查,所以gets_hit是trueish值,只要該組中的碰撞的精靈不被移除並且if gets_hit:塊被執行。這意味着for循環中的代碼只是保持刪除碰撞後的精靈到達並刪除之前出現的組中的每個精靈。一個簡單的解決方法是檢查命中精靈是否爲敵人:if enemy == gets_hit:,但代碼仍然效率不高,因爲spritecollideany必須在for循環內再次遍歷all_sprites組。

我推薦使用spritecollide而不是spritecollideany,因爲它更高效,只需一行代碼。