首页 > 解决方案 > 如何使用组碰撞?

问题描述

所以我一直想知道如何使用pygame groupcollide。我现在完全被难住了。因为我正在使用collide_rect,所以很好。但是对于 groupcollide 我似乎无法弄清楚如何调用该组内项目的属性。而且我不能做碰撞矩形,因为会有很多子弹。

def check_blast_collisions(player,bullet):
    hits = pg.sprite.groupcollide(player,bullet,False,True)
    for hit in hits:
        print (hits)
        if hit.vx == 20:
            player.vx += 40
        elif hit.vx == -20:
            player.vx += -40

这是我尝试使用 groupcollide 的片段。在我做了这个功能之后,子弹甚至都没有出现。(子弹应该被称为爆炸,但我在这个函数中忘记了它。)

import pygame as pg

#settings

CAPTION = "Knockback Arena"
resolution = 1600,900
WIDTH = resolution[0]
HEIGHT = resolution[1]
FPS = 60

player_jump_height = 30
player_max_fall_speed = 30
player_fall_speed_increase = 2
player_lives = 5

shoot_cooldown = 500

#initialize pygame
pg.init()
pg.mixer.init()
pg.font.init
screen = pg.display.set_mode(resolution)
pg.display.set_caption(CAPTION)
clock = pg.time.Clock()

#sprites
class Platform(pg.sprite.Sprite):
    def __init__(self,x,y,width,height,r,g,b):
        pg.sprite.Sprite.__init__(self)
        self.image = pg.Surface((width,height))
        self.image.fill((r,g,b))
        self.rect = self.image.get_rect()
        self.rect.center = (x,y)

class Player(pg.sprite.Sprite):
    def __init__(self,r,g,b,x,y):
        pg.sprite.Sprite.__init__(self)
        self.image = pg.Surface((40, 100))
        self.image.fill((r,g,b))
        self.rect = self.image.get_rect()
        self.rect.center = (x, y)
        self.startx = x
        self.starty = y
        self.vx = 0
        self.vy = 5
        self.vy_max = player_max_fall_speed
        self.vy_increase = player_fall_speed_increase
        self.lives = player_lives
        self.last_shot = 0
        self.facing_right = False
        self.facing_left = False

    def update(self):
        self.rect.x += self.vx
        self.rect.y += self.vy
        if self.vy >= self.vy_max:
            self.vy = self.vy_max
            self.vy_increase = 0
        if self.vy < self.vy_max:
            self.vy_increase = player_fall_speed_increase
        if self.rect.bottom < HEIGHT:
            self.vy += self.vy_increase
        if self.rect.top >= HEIGHT:
            self.rect.x = self.startx
            self.rect.y = self.starty
            self.lives -= 1
            if self.lives <= 0:
                self.kill()
        if self.rect.right >= WIDTH:
            self.rect.right = WIDTH
            self.vx = 0
        if self.rect.left <= 0:
            self.rect.left = 0
            self.vx = 0

    def jump(self):
        if self.rect.bottom >= main_platform.rect.top:
            self.vy -= player_jump_height
        if self.rect.bottom >= HEIGHT:
            self.vy -= player_jump_height

    def shoot(self):
        if pg.time.get_ticks() - self.last_shot >= shoot_cooldown:
            if self.facing_left == True:
                return "shoot_left"
            elif self.facing_right == True:
                return "shoot_right"
        else:
            return "cd_not_done"

class Blast(pg.sprite.Sprite):
    def __init__(self,player,direction):
        pg.sprite.Sprite.__init__(self)
        self.image = pg.Surface((20,10))
        self.image.fill((0,255,255))
        self.rect = self.image.get_rect()
        self.rect.center = (player.rect.center)
        self.direction = direction
        if self.direction == 0:
            self.vx = -20
        elif self.direction == 1:
            self.vx = 20
    def update(self):
        self.rect.x += self.vx
        if self.rect.right < 0:
            self.kill()
        if self.rect.left > WIDTH:
            self.kill()

#functions
def check_for_collisions(player,platform):
    hits = pg.sprite.collide_rect(player,platform)
    if hits:
        if hits and player.vy > 0:
            player.rect.bottom = platform.rect.top
            player.vy = 0

def check_blast_collisions(player,bullet):
    hits = pg.sprite.groupcollide(player,bullet,False,True)
    for hit in hits:
        print (hits)
        if hit.vx == 20:
            player.vx += 40
        elif hit.vx == -20:
            player.vx += -40

font = pg.font.Font('font/Roboto-Light.ttf', 30)

all_sprites = pg.sprite.Group()
players = pg.sprite.Group()
platforms = pg.sprite.Group()
blasts = pg.sprite.Group()

main_platform = Platform(WIDTH/2,650,1000,100,0,200,0)
player_1 = Player(0,0,255,WIDTH/2 + -100,200)
player_2 = Player(255,0,0,WIDTH/2 + 100,200)

platforms.add(main_platform)
players.add(player_1)
players.add(player_2)
all_sprites.add(player_1)
all_sprites.add(player_2)
all_sprites.add(main_platform)

menu = True
run = True
while run:
    #check for closing window
    for event in pg.event.get():
        if event.type == pg.KEYDOWN:
            if event.key == pg.K_w:
                player_1.jump()
            if event.key == pg.K_a:
                player_1.vx = -10
                player_1.facing_left = True
                player_1.facing_right = False
            elif event.key == pg.K_d:
                player_1.vx = 10
                player_1.facing_right = True
                player_1.facing_left = False

            if event.key == pg.K_UP:
                player_2.jump()
            if event.key == pg.K_LEFT:
                player_2.vx = -10
                player_2.facing_left = True
                player_2.facing_right = False
            elif event.key == pg.K_RIGHT:
                player_2.vx = 10
                player_2.facing_right = True
                player_2.facing_left = False

            if event.key == pg.K_j:
                if player_1.shoot() == "shoot_left":
                    b = Blast(player_1,0)
                    all_sprites.add(b)
                    blasts.add(b)
                elif player_1.shoot() == "shoot_right":
                    b = Blast(player_1,1)
                    all_sprites.add(b)
                    blasts.add(b)
            if event.key == pg.K_KP1:
                if player_2.shoot() == "shoot_left":
                    b = Blast(player_2,0)
                    all_sprites.add(b)
                    blasts.add(b)
                elif player_2.shoot() == "shoot_right":
                    b = Blast(player_2,1)
                    all_sprites.add(b)
                    blasts.add(b)

        elif event.type == pg.KEYUP:
            if event.key == pg.K_a:
                player_1.vx = 0
            if event.key == pg.K_d:
                player_1.vx = 0

            if event.key == pg.K_LEFT:
                player_2.vx = 0
            if event.key == pg.K_RIGHT:
                player_2.vx = 0
        if event.type == pg.QUIT:
            pg.quit()
            exit()

    #update all sprites
    all_sprites.update()
    check_for_collisions(player_1,main_platform)
    check_for_collisions(player_2,main_platform)
    check_blast_collisions(players,blasts)

    #draw sprites
    screen.fill((255,255,255))
    all_sprites.draw(screen)

    #draw other stuff
    p1lives = font.render(str(player_1.lives), False, (0,0,255))
    screen.blit(p1lives,(20,50))

    p2lives = font.render(str(player_2.lives), False, (255,0,0))
    screen.blit(p2lives,(1580,50))

    clock.tick(FPS)
    pg.display.flip()

这是整个代码。任何帮助深表感谢。谢谢。

标签: pythonpygame

解决方案


你不能pygame.sprite.groupcollide()在这里使用,因为子弹会与发射子弹的玩家发生碰撞。
您必须使用pygame.sprite.spritecollide(), 与一名玩家和对手的子弹一起使用。为每个玩家调用一次。


推荐阅读