2014-07-22 242 views
0

我是一般的PyGame和python的新用户。话虽如此,我已经创造了一些精灵并将它们组合在一起。例如,PyGame组的精灵

gems = pygame.sprite.Group() 

for i in range (0,4): 
    gem = Gem() 
    all_sprite_list.add(gem) 
    gems.add(gem) 

现在在我的主,我想通过敲击特定按键来操纵创业板的组中的一个。我目前正在通过为每个gem设置一个id属性并遍历该组来完成此操作,直到我将id与我想要处理的id相匹配。即:

if event.type == pygame.KEYDOWN and event.key == pygame.K_F1: 
    for gem in gems: 
     if gem.id == 1: 
      gem.state = normal 
elif event.type == pygame.KEYDOWN and event.key == pygame.K_F2: 
    for gem in gems: 
     if gem.id == 2: 
      gem.state = normal 

我知道这是一个肮脏伎俩,我敢肯定有一个更好的办法,而不是通过迭代组。我看了一下参考资料,并试着做类似

gems.sprites().index(0) 

无济于事。有什么建议么?

+0

你可以额外保留字典中的精灵并使用'id'作为键。 – furas

回答

0

好像你知道哪些键对应于该ID的,所以你可以把一个字典的信息,然后只能通过宝石做一个迭代:

gem_keys = { 
    1: pygame.K_F1, 
    2: pygame.K_F2, 
} 

if event.type == pygame.KEYDOWN: 
    for gem in gems: 
     # Check if key pressed corresponds to current gem 
     if event.key == gem_keys[gem.id]: 
      gem.state = normal 

是你有超越任何具体问题代码感觉笨重?

0

在PyGame的Sprite类中,您有一个函数update(*args)documentation)。

(顺便说一句,*args意味着你可以在尽可能多的参数传递,只要你想:

>>> def f(*args): 
...  print args 
... 
>>> f(1,2) 
(1, 2) 
>>> f(3) 
(3,) 
>>> f(3,5,6) 
(3, 5, 6) 
>>> def g(*args): 
...  print args[0] 
... 
>>> g(1,2) 
1 

默认情况下update什么也不做,但你可以通过创建一个覆盖它自己的目的,例如类覆盖基Sprite类:

class MySprite(Sprite): 
    def update(self,*args): 
     key = args[0] 
     if key == pygame.K_F1 and self.id == 1 : 
      self.state = normal 
     elif key == pygame.K_F2 and self.id == 2 : 
      self.state = normal 

现在,雪碧组也有一个update功能(具有相同签名update(*args)

Official documentation

什么这个函数的作用是它调用update在参数传递的每个精灵

# group has sprite1 and sprite2 
group.update(1,2,3) # same as calling sprite1.update(1,2,3) 
        # and sprite2.update(1,2,3) 

所以如果gems是你的团队,你可以这样做(假设你正在使用类似的MySprite类以上)

if event.type == pygame.KEYDOWN: 
    gems.update(event.key) 
    # this will call the MySprite.update function for all the gems 
+0

这当然看起来更清洁,而且几乎是我在寻找的东西......但它是否尽可能高效?我们是否真的需要更新组中的每个项目?有没有办法只操纵我想要的精灵? – imjojo42

+0

当你有一个更全面的更新周期时(这里你可能会检查每个宝石上的很多不同的属性),这是“最好的”解决方案,但我正在为你的更具体的案例写一个答案 – rtpg

0

我写another answer,似乎像规范答案更新pygame的小精灵(特别是如果你UPD每次更新都会有很多精灵)。但是,对于更新众多小精灵的情况来说,这是另一种解决方案。


目标是在大集合中找到一小组对象。这里我提出的解决方案是在你的精灵组中使用一个平行字典。该字典将被键入触发它的键。

这里我们将使用defaultdict(查看这个question(特别是第二个答案),以了解如何使用这些)。基本上它是一个带有默认值的字典(因为它是list它充满了空列表)。

key_dict = defaultdict(list) 
# add the sprite triggered by F1 
key_dict[pygame.K_F1].append(gem1) 
# you can add multiple sprites as well (these are lists) 
key_dict[pygame.K_F2].append(gem2) 
key_dict[pygame.K_F2].append(gem3) 

#... in your update loop 
if event.type == pygame.KEYDOWN: 
    for gem in key_dict[event.key] : #this gets all the gems for this key event 
            # (empty if not defined because defaultdict) 
     gem.state = normal 

这个解决方案是好的,如果你有宝石的很多只有真正需要轻按几个小的。

也存在一些问题:

  • 需要十个分量两个集合(你的精灵群体和这个)

  • ,如果你用这个了很多宝石,那么速度优势会越来越

  • 这会让你的代码混乱

我认为这是值得的,只有当你处于需要更新的宝石数量远远少于总宝石数量的情况下。如果你还更新了很多其他属性,我会建议我的其他答案,因为它更清洁。

+0

“你需要维护两个集合(你的精灵组和这个)“ 这正是我想尝试使用精灵组的原因,如果我可以的话。如果我不需要,我不想保留2个列表。 – imjojo42

+0

我查看了精灵组代码,并且似乎没有一种简单的方法来查询它,所以这可能是您最好的选择。 – rtpg