简体   繁体   English

pygame sprite.Group - 从组中传递 arguments

[英]pygame sprite.Group - passing arguments out of a Group

I'm trying out pygame, using Sprites & Groups, and getting myself a little confused around passing arguments.我正在尝试 pygame,使用 Sprites & Groups,并且让自己对通过 arguments 感到有些困惑。

Basically I have a wrapper class MyGame() as my_game().基本上我有一个包装器 class MyGame() 作为 my_game()。 In that I have pygame.sprite.Group() - all_sprites.我有 pygame.sprite.Group() - all_sprites。

I then have a class Alien(pygame.sprite.Sprite) for my aliens, and I add each alien to my all_sprites Group.然后我有一个 class Alien(pygame.sprite.Sprite) 用于我的外星人,我将每个外星人添加到我的 all_sprites 组中。

I want my Group of aliens to track across the screen (which they do) and then all drop as a block, a group (which they don't).我希望我的外星人小组在屏幕上跟踪(他们这样做),然后全部作为一个块下降,一个小组(他们没有)。

I can loop through my all_sprites.Group in my main loop after the self.all_sprites.update() and see if alien.rect.right > WIDTH or alien.rect.left < 0, then loop through the Group again calling alien.end_row() then break the loop so it doesn't run for each alien on the screen edge, but that seems very clunky.我可以在 self.all_sprites.update() 之后在我的主循环中循环我的 all_sprites.Group 并查看是否 alien.rect.right > WIDTH 或 alien.rect.left < 0,然后再次循环通过 Group 调用 alien.end_row () 然后打破循环,这样它就不会为屏幕边缘的每个外星人运行,但这看起来很笨拙。

I've tried setting a flag in MyGame self.alien_drop = False but when I try to set my_game.alien_drop = True in the Alien class, it doesn't recognise my_game - not defined.我尝试在 MyGame self.alien_drop = False 中设置一个标志,但是当我尝试在 Alien class 中设置 my_game.alien_drop = True 时,它无法识别 my_game - 未定义。 I'm a little confused as MyGame is creating the instances of Alien, so they should be enclosed by the scope of MyGame?我有点困惑,因为 MyGame 正在创建 Alien 的实例,所以它们应该被 MyGame 的 scope 包围?

I can pass MyGame self.alien_drop into my Alien init() but when I update the Alien self.alien_drop it doesn't update MyGame.alien_drop.我可以将 MyGame self.alien_drop 传递给 Alien init(),但是当我更新 Alien self.alien_drop 时,它不会更新 MyGame.alien_drop。 Which I get because it's created a new variable local to Alien.我得到它是因为它创建了 Alien 本地的一个新变量。

There doesn't seem to be a way to pass an argument through Group.update() which I guess is because it's just calling the.update() on all Sprite inside the group.似乎没有办法通过 Group.update() 传递参数,我猜这是因为它只是在组内的所有 Sprite 上调用 the.update() 。 I can't see an easy way to modify the Group.update() function so that I can pass values, and in fairness I probably don't want to go mucking around in there anyway.我看不到一种简单的方法来修改 Group.update() function 以便我可以传递值,而且公平地说,我可能不想 go 在那里乱七八糟。

I also can't return True back through update().我也无法通过 update() 返回 True。

I'm kinda stuck at this point...我有点卡在这一点上......

I know the self.aliens.row_end() probably won't work, I'll have to loop through self.aliens and call each alien.row_end(), but at the moment it's not even getting to that point.我知道 self.aliens.row_end() 可能不起作用,我将不得不遍历 self.aliens 并调用每个 alien.row_end(),但目前它甚至还没有达到这一点。

import pygame

WIDTH = 360 # width of our game window
HEIGHT = 480 # height of our game window
BLACK = (0, 0, 0)
GREEN = (0, 255, 0)

class MyGame():
    def __init__(self):
        pygame.init()
        self.screen = pygame.display.set_mode((WIDTH, HEIGHT))
        self.clock = pygame.time.Clock()
        self.all_sprites = pygame.sprite.Group()
        self.alien_drop = False
        for row_index in range(4):
            for column_index in range(6):
                alien = Alien(20 + (column_index * 40), 20 + (row_index *40))
                alien.add(self.all_sprites)
        while True:
            self.screen.fill(BLACK)
            self.all_sprites.update()
            if self.alien_drop:
                self.aliens.row_end()
            self.all_sprites.draw(self.screen)
            pygame.display.update()
            self.clock.tick(60)

class Alien(pygame.sprite.Sprite):
    def __init__(self, x, y):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.Surface((25, 25))
        self.rect = self.image.get_rect()
        self.rect.center = (x, y)
        self.image.fill(GREEN)
        self.dx = 1

    def update(self):
        self.rect.x += self.dx
        if self.rect.right >= WIDTH or self.rect.left <= 0:
            my_game.alien_drop = True

    def row_end(self):
        self.dx *= -1
        self.rect.y += 40

if __name__ == "__main__":
    my_game = MyGame()

So to do the traditional Space Invaders move and drop, the entire row drops when any of the invaders hits either side.因此,要让传统的太空入侵者移动和下降,当任何入侵者击中任一侧时,整排都会下降。

In the example below I have modified the Alien.update() to detect when the screen-side is hit, but if-so, only set a Boolean flag Alien.drop to True.在下面的示例中,我修改了Alien.update()以检测屏幕侧何时被击中,但如果是这样,只需将 Boolean 标志Alien.drop设置为 True。

The algorithm becomes: First move all the aliens.算法变为:首先移动所有的外星人。 Next, check if any alien hit the side-wall by checking this flag.接下来,通过检查此标志检查是否外星人撞到侧壁。 If so, move every alien down 1 step & stop checking.如果是这样,请将每个外星人向下移动 1 步并停止检查。

The Alien.row_end() function moves the aliens down. Alien.row_end() function 将外星人向下移动。 It also needs to clear the Alien.drop flag, so they don't all move down again.它还需要清除Alien.drop标志,因此它们不会再次向下移动。

import pygame

WIDTH = 360 # width of our game window
HEIGHT = 480 # height of our game window
BLACK = (0, 0, 0)
GREEN = (0, 255, 0)

class MyGame():
    def __init__(self):
        pygame.init()
        self.screen = pygame.display.set_mode((WIDTH, HEIGHT))
        self.clock = pygame.time.Clock()
        self.all_sprites = pygame.sprite.Group()
        self.alien_drop = False
        for row_index in range(4):
            for column_index in range(6):
                alien = Alien(20 + (column_index * 40), 20 + (row_index *40))
                alien.add(self.all_sprites)

        exiting = False
        while not exiting:
            # Handle events
            for event in pygame.event.get():
                if ( event.type == pygame.QUIT ):
                    exiting = True  # exit this loop

            self.screen.fill(BLACK)
            self.all_sprites.update()
            for alien1 in self.all_sprites:
                if ( alien1.shouldDrop() ):
                    ### If any alien drops, we all drop
                    for alien2 in self.all_sprites:
                        alien2.row_end()
                    break  # only drop once

            if self.alien_drop:
                self.aliens.row_end()
            self.all_sprites.draw(self.screen)
            pygame.display.update()
            self.clock.tick(60)

class Alien(pygame.sprite.Sprite):
    def __init__(self, x, y):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.Surface((25, 25))
        self.rect = self.image.get_rect()
        self.rect.center = (x, y)
        self.image.fill(GREEN)
        self.dx = 1
        self.drop = False  # should I drop-down a level

    def update(self):
        self.rect.x += self.dx
        if self.rect.right >= WIDTH or self.rect.left <= 0:
            self.drop = True
        else:
            self.drop = False

    def shouldDrop( self ):
        """ In this alien in a position where it should drop down
            one row in the screen-space (i.e.: it's hit a side)  """
        return self.drop

    def row_end(self):
        self.dx *= -1
        self.rect.y += 40
        self.drop = False    # drop drop again just yet

if __name__ == "__main__":
    my_game = MyGame()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM