Pygame:碰撞是从组中移除精灵但仍然blit到屏幕

时间:2015-10-27 05:52:38

标签: python pygame sprite collision kill

我有两艘船和一套药丸应该从屏幕顶部连续下雨。当我的船与药丸碰撞时,药丸应该消失,但它们不会消失。药片从y = win_height开始在屏幕下方消失约50个像素。

经过一些测试后,我可以说这些药片是通过“碰撞”来检测的。并且他们被从群组中删除了,但是他们仍然被屏蔽并直接通过船只。我希望药片能立即消失。

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

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)

以下是游戏的完整版本。请注意,我增加了船只尺寸以填满屏幕。尝试将船只移动到屏幕顶部,当它们到达屏幕底部而不是第一次接触船只时,您会看到药丸消失。

import sys, pygame, os, random

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

# Runs imported module
pygame.init()

# Constants
LEFT = 'left'
RIGHT = 'right'

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

SHIP_WIDTH = 600
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():
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.width = SHIP_WIDTH
        self.height = SHIP_HEIGHT
        self.speed = 5
        self.density = 0
        self.ship = pygame.Surface((self.width, self.height)).convert()
        self.rect = pygame.Rect(self.x, self.y, self.width, self.height)
        self.up = self.down = self.left = self.right= False

    def update(self, which_ship, left, right, down, up, pillGroup):
        # Adjust speed
        if up or down or left or right:
            if up:
                self.y -= self.speed
            if down:
                self.y += self.speed
            if left:
                self.x -= self.speed
            if right:
                self.x += self.speed

        # Ship movement
        if self.y < 0:
            self.y = 0
        if self.y > WIN_H - self.height:
            self.y = WIN_H - self.height
        if which_ship == 'left':
            if self.x < 0:
                self.x = 0
            if self.x > WIN_W/2 - self.width:
                self.x = WIN_W/2 - self.width
        elif which_ship == 'right':
            if self.x < WIN_W/2:
                self.x = WIN_W/2
            if self.x > WIN_W - self.width:
                self.x = WIN_W - self.width


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()
        self.rect = self.rect.move(RANDOM_PILL[PILL_COUNT], -PILL_HEIGHT) #RANDOM_PILL[PILL_COUNT], PILL_HEIGHT)
        PILL_COUNT += 1

    def restart(self):
        pass

    def update(self):
        if self.rect.y > WIN_H:
            del self
        else:
            self.rect = self.rect.move((0, self.speed))


def genRandom():
    for i in range(250):
        print random.randrange(PILL_WIDTH, WIN_W - PILL_WIDTH), ", ",

def main():
    fps = 60

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

    ship_left = Ship((WIN_W/4) - (SHIP_WIDTH/2), WIN_H - (SHIP_HEIGHT * 4))
    ship_right = Ship((WIN_W/1.3) - (SHIP_WIDTH/2), WIN_H - (SHIP_HEIGHT * 4))

    pillGroup = pygame.sprite.Group()

    pillAlter = 0

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

    lLeft = lRight = lUp = lDown = False
    rLeft = rRight = rUp = rDown = False

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

    #ranList = genRandom()

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

            # Keypresses
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    pygame.quit()
                    sys.exit()
                if event.key == pygame.K_a:
                    lLeft = True
                    lRight = False

                if event.key == pygame.K_d:
                    lLeft = False
                    lRight = True
                if event.key == pygame.K_w:
                    lDown = False
                    lUp = True
                if event.key == pygame.K_s:
                    lDown = True
                    lUp = False

                if event.key == pygame.K_LEFT:
                    rLeft = True
                    rRight = False
                if event.key == pygame.K_RIGHT:
                    rLeft = False
                    rRight = True
                if event.key == pygame.K_UP:
                    rDown = False
                    rUp = True
                if event.key == pygame.K_DOWN:
                    rUp = False
                    rDown = True

            elif event.type == pygame.KEYUP:
                if event.key == pygame.K_a:
                    lLeft = False
                if event.key == pygame.K_d:
                    lRight = False
                if event.key == pygame.K_w:
                    lUp = False
                if event.key == pygame.K_s:
                    lDown = False

                if event.key == pygame.K_RIGHT:
                    rRight = False
                if event.key == pygame.K_LEFT:
                    rLeft = False
                if event.key == pygame.K_UP:
                    rUp = False
                if event.key == pygame.K_DOWN:
                    rDown = False

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

        ship_left.update('left', lLeft, lRight, lDown, lUp, pillGroup)
        ship_right.update('right', rLeft, rRight, rDown, rUp, pillGroup)

        pillGroup.update()

        pill_hit_list = pygame.sprite.spritecollide(ship_right, pillGroup, True)
        pill_hit_list = pygame.sprite.spritecollide(ship_left, pillGroup, True)

        # Print background
        screen.fill(WHITE)
        print pillGroup.draw(screen)
        screen.blit(ship_left.ship, (ship_left.x, ship_left.y))
        screen.blit(ship_right.ship, (ship_right.x, ship_right.y))
        screen.blit(vert_partition, (WIN_W/2, WIN_H/15))
        screen.blit(hori_partition, (0, WIN_H/15))


        # Limits frames per iteration of while loop
        clock.tick(fps)
        # Writes to main surface
        pygame.display.flip()


if __name__ == "__main__":
    main()

1 个答案:

答案 0 :(得分:0)

问题是SELECT tag_name FROM tags inner JOIN term_tags on tags.tag_id=term_tags.tag_id WHERE term_id = ? 检查您传递的精灵的pygame.sprite.spritecollide属性作为第一个参数,并将其与精灵组中精灵的rect属性进行比较。

但是,您实际上并未更改rect个实例的rect属性。

删除Ship类的xy属性,并仅使用Ship属性存储精灵的位置。

这是一个更新版本:

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)。