Pygame:碰撞将精灵从组中移除,但仍会在屏幕上闪动

2024-10-01 04:55:26 发布

您现在位置:Python中文网/ 问答频道 /正文

我有两艘飞船和一套药丸,这些药片应该会从屏幕的顶部不断往下滴。当我的飞船与一颗药丸相撞时,药丸应该会消失,但它们不会消失。药丸会在离y=win峈高度50像素的地方消失。在

在运行了一些测试之后,我可以说药丸是由“碰撞精灵”检测到的,它们被从“pillGroup”组中移除,但是它们仍然被快速地传送到屏幕上并通过飞船。我要药片立刻消失。在

以下是我的算法的编辑版本:

pillGroup = pygame.sprite.Group()

# Gameplay
while play:
    # Checks if window exit button pressed
    for event in pygame.event.get():
        if event.type == pygame.QUIT: sys.exit()

        # Keypresses

    pill = Pill()
    pill.add(pillGroup)

    pillGroup.update()
    pygame.sprite.spritecollide(ship_right, pillGroup, True)

    # Print background
    screen.fill(WHITE)
    pillGroup.draw(screen)

这是游戏的完整版本。请注意,我增加了船的尺寸来填充屏幕。试着把飞船移到屏幕的顶部,你会看到药丸在到达屏幕底部时消失,而不是第一次接触到飞船时。在

^{pr2}$

Tags: 版本eventif屏幕exitscreenpygamesprite
1条回答
网友
1楼 · 发布于 2024-10-01 04:55:26

问题是pygame.sprite.spritecollide检查作为第一个参数传递的精灵的rect属性,并将其与精灵组中精灵的rect属性进行比较。在

但是,实际上并没有更改Ship实例的rect属性。在

去掉xy属性,只使用rect属性来存储精灵的位置。在


以下是更新版本:

import sys, pygame, os, random

# Force static position of screen
os.environ['SDL_VIDEO_CENTERED'] = '1'

pygame.init()

BLACK = (0, 0, 0)
WHITE = (255, 255, 255)

SHIP_WIDTH = 30
SHIP_HEIGHT = 10
PILL_WIDTH = 5
PILL_HEIGHT = 20

WIN_W = 1200
WIN_H = 570

RANDOM_PILL = [700 ,  658 ,  58 ,  795 ,  687 ,  308 ,  785 ,  828 ,  670 ,  187 ,  603 ,  994 ,  990 ,  923 ,  523 ,  849 ,  229 ,  804 ,  618 ,  733 ,  614 ,  209 ,  941 ,  872 ,  528 ,  438 ,  793 ,  879 ,  327 ,  539 ,  571 ,  886 ,  452 ,  627 ,  267 ,  662 ,  655 ,  772 ,  904 ,  769 ,  197 ,  1009 ,  281 ,  867 ,  31 ,  30 ,  545 ,  519 ,  866 ,  66 ,  202 ,  580 ,  1172 ,  792 ,  131 ,  980 ,  83 ,  999 ,  120 ,  916 ,  956 ,  1166 ,  391 ,  1127 ,  675 ,  868 ,  851 ,  725 ,  869 ,  702 ,  767 ,  692 ,  695 ,  564 ,  978 ,  834 ,  866 ,  340 ,  78 ,  396 ,  195 ,  480 ,  1113 ,  223 ,  725 ,  36 ,  660 ,  973 ,  597 ,  734 ,  1129 ,  91 ,  720 ,  610 ,  1020 ,  861 ,  887 ,  350 ,  235 ,  39 ,  282 ,  698 ,  856 ,  236 ,  1077 ,  191 ,  1147 ,  605 ,  825 ,  1179 ,  978 ,  320 ,  985 ,  125 ,  475 ,  1009 ,  166 ,  528 ,  100 ,  455 ,  485 ,  1066 ,  38 ,  408 ,  235 ,  410 ,  1064 ,  57 ,  653 ,  177 ,  836 ,  228 ,  224 ,  534 ,  789 ,  1129 ,  370 ,  1008 ,  529 ,  62 ,  752 ,  654 ,  785 ,  916 ,  281 ,  235 ,  921 ,  945 ,  727 ,  1138 ,  585 ,  168 ,  1048 ,  708 ,  144 ,  968 ,  974 ,  1118 ,  555 ,  251 ,  1135 ,  805 ,  1121 ,  360 ,  968 ,  228 ,  988 ,  49 ,  536 ,  117 ,  726 ,  65 ,  177 ,  925 ,  923 ,  239 ,  1117 ,  678 ,  329 ,  180 ,  1019 ,  47 ,  147 ,  235 ,  279 ,  841 ,  383 ,  211 ,  971 ,  309 ,  452 ,  335 ,  1121 ,  1091 ,  247 ,  790 ,  418 ,  961 ,  323 ,  458 ,  970 ,  752 ,  888 ,  719 ,  318 ,  930 ,  797 ,  537 ,  1006 ,  696 ,  309 ,  1102 ,  728 ,  497 ,  553 ,  266 ,  67 ,  504 ,  763 ,  158 ,  944 ,  108 ,  553 ,  517 ,  470 ,  1016 ,  93 ,  243 ,  570 ,  136 ,  67 ,  893 ,  241 ,  571 ,  515 ,  616 ,  986 ,  561 ,  148 ,  351 ,  78 ,  862 ,  685 ,  286 ,  414 ,  756 ,  730 ,  381 ,  141 ,  896]
PILL_COUNT = 0

class Entity(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)

class Ship(Entity):
    def __init__(self, container):
        Entity.__init__(self)
        self.speed = 5
        self.density = 0
        self.image = pygame.Surface((SHIP_WIDTH, SHIP_HEIGHT)).convert()
        self.rect = self.image.get_rect(center=container.center)
        self.container = container

    def update(self):
        self.rect.clamp_ip(self.container)

    def move(self, vector):
        self.rect.move_ip([self.speed * a for a in vector])

class Pill(Entity):
    def __init__(self, density):
        Entity.__init__(self)
        global PILL_COUNT
        self.speed = 3
        self.density = density
        self.image = pygame.Surface((PILL_WIDTH, PILL_HEIGHT)).convert()
        self.rect = self.image.get_rect(topleft=(RANDOM_PILL[PILL_COUNT], -PILL_HEIGHT))
        PILL_COUNT += 1

    def update(self):
        self.rect.move_ip((0, self.speed))

        if self.rect.y > WIN_H:
            self.kill()

def main():
    fps = 60

    pygame.display.set_caption('Pong')
    screen = pygame.display.set_mode((WIN_W, WIN_H), pygame.SRCALPHA)

    ship_left = Ship(pygame.rect.Rect(0, 0, WIN_W/2, WIN_H))
    ship_right = Ship(pygame.rect.Rect(WIN_W/2, 0, WIN_W/2, WIN_H))

    pillGroup = pygame.sprite.Group()
    shipGroup = pygame.sprite.Group(ship_left, ship_right)

    pillAlter = 0

    vert_partition = pygame.Surface((1, WIN_H))
    hori_partition = pygame.Surface((WIN_W, 1))

    clock = pygame.time.Clock()
    play = True

    movement = {ship_left:  { pygame.K_w: ( 0, -1),
                              pygame.K_s: ( 0,  1),
                              pygame.K_a: (-1,  0),
                              pygame.K_d: ( 1,  0)},
                ship_right: { pygame.K_UP:    ( 0, -1),
                              pygame.K_DOWN:  ( 0,  1),
                              pygame.K_LEFT:  (-1,  0),
                              pygame.K_RIGHT: ( 1,  0)}}

    while play:
        for event in pygame.event.get():
            if event.type == pygame.QUIT: 
                sys.exit()
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    pygame.quit()
                    sys.exit()


        pressed = pygame.key.get_pressed()
        for ship in shipGroup:
            for key, vector in movement[ship].iteritems():
                if pressed[key]:
                    ship.move(vector) #TODO: use real vector math

        if PILL_COUNT < 250 and pillAlter % 10 == 0:
            pill = Pill(random.randrange(1,4))
            pillGroup.add(pill)
        pillAlter += 1

        pillGroup.update()
        shipGroup.update()

        pygame.sprite.groupcollide(shipGroup, pillGroup, False, True)

        # Print background
        screen.fill(WHITE)
        pillGroup.draw(screen)
        shipGroup.draw(screen)

        screen.blit(vert_partition, (WIN_W/2, WIN_H/15))
        screen.blit(hori_partition, (0, WIN_H/15))

        clock.tick(fps)
        pygame.display.flip()


if __name__ == "__main__":
    main()

注意移动代码是如何简化的。我还使用了kill()来删除屏幕外的药片,并使用了Rect类的一些特性,比如设置初始位置、移动到位(move_ip)以及确保Rect不会离开特定区域(clamp_ip)。在

相关问题 更多 >