Python(pygame)碰撞检测 - 精灵和组

时间:2014-08-08 17:00:13

标签: python class pygame sprite collision

我是python的新手,我正在尝试编写一个启动角色的游戏,当他与地面上的精灵交互时,会发生一些变化,例如速度。我为我的代码中的混乱道歉。我从一些教程中抽取了样本,但我无法让它们协同工作。

如何使玩家与炸弹的碰撞可以检测到?

import pygame
import random
import math

drag = 1
gravity = (math.pi, .4)
elasticity = .75

# Colors
BLACK    = (   0,   0,   0)
WHITE    = ( 255, 255, 255)
BLUE     = (   0,   0, 255)
RED      = ( 255,   0,   0)
GREEN    = (   0, 255,   0)

# Screen dimensions
SCREEN_WIDTH  = 800
SCREEN_HEIGHT = 600

def addVectors((angle1, length1), (angle2, length2)):
    x = math.sin(angle1) * length1 + math.sin(angle2) * length2
    y = math.cos(angle1) * length1 + math.cos(angle2) * length2

    angle = 0.5 * math.pi - math.atan2(y, x)
    length = math.hypot(x, y)

    return (angle, length)

class Player(pygame.sprite.Sprite):

    change_x = 0
    change_y = 0

    level = None

    def __init__(self, x, y):

        pygame.sprite.Sprite.__init__(self)

        self.image = pygame.image.load('player.png')
        image_rect = self.image.get_rect()
        self.rect = pygame.rect.Rect(x, y, image_rect.width, image_rect.height)

    def update(self):
        pass

    def move(self):
        (self.angle, self.speed) = addVectors((self.angle, self.speed), gravity)
        self.rect.x += math.sin(self.angle) * self.speed
        self.rect.y -= math.cos(self.angle) * self.speed
        self.speed *= drag



    def bounce(self):
        if self.rect.x > 800 - self.rect.width:
            self.rect.x = 2*(800 - self.rect.width) - self.rect.x
            self.angle = - self.angle
            self.speed *= elasticity

        elif self.rect.x < 0:
            self.rect.x = 2*self.rect.width - self.rect.x
            self.angle = - self.angle
            self.speed *= elasticity

        if self.rect.y > SCREEN_HEIGHT - self.rect.height:
            self.rect.y = 2*(SCREEN_HEIGHT - self.rect.height) - self.rect.y
            self.angle = math.pi - self.angle
            self.speed *= elasticity

class Bomb(pygame.sprite.Sprite):

    def __init__(self, x, y):

        pygame.sprite.Sprite.__init__(self)

        self.image = pygame.image.load('cherry.png')
        image_rect = self.image.get_rect()
        self.rect = pygame.rect.Rect(x, y, image_rect.width, image_rect.height)


class Level():

    bomb_list = None
    world_shift = 0

    def __init__(self, player):
        self.bomb_list = pygame.sprite.Group()
        self.player = player

    def update(self):
        self.bomb_list.update()

    def draw(self, screen):
        screen.fill(BLACK)

        self.bomb_list.draw(screen)

    def shift_world(self, shift_x):

        self.world_shift += shift_x

        for bomb in self.bomb_list:
            bomb.rect.x += shift_x

            if bomb.rect.x < 0:
                self.bomb_list.remove(bomb)
                self.bomb_list.add(Bomb(random.randint(SCREEN_WIDTH, 2*SCREEN_WIDTH), 580)) 

我不确定这个Level_01类是否必要:

class Level_01(Level):

    def __init__(self, player):

        Level.__init__(self, player)

        bombs = 0
        for n in range(10):
            self.bomb_list.add(Bomb(random.randint(0, SCREEN_WIDTH), 580))

这是我尝试碰撞检测方法。我不确定它应该是在课堂上,主要的还是分开的。我似乎无法同时获得炸弹和玩家的名单。

def detectCollisions(sprite1, sprite_group):
    if pygame.sprite.spritecollideany(sprite1, sprite_group):
        sprite_group.remove(pygame.sprite.spritecollideany(sprite1, sprite_group))
        print True
    else:
        print False


def main():

    pygame.init()

    size = [SCREEN_WIDTH, SCREEN_HEIGHT]
    screen = pygame.display.set_mode(size)


    active_sprite_list = pygame.sprite.Group()
    enemy_list = pygame.sprite.Group()

    player = Player(0, 0)
    player.speed = 30
    player.angle = math.radians(45)

    player.rect.x = 500
    player.rect.y = SCREEN_HEIGHT - player.rect.height
    active_sprite_list.add(player)

    done = False

    clock = pygame.time.Clock()

    current_level = Level_01(player)

    while not done:

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                done = True

            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LEFT:
                    player.go_left()
                if event.key == pygame.K_RIGHT:
                    player.go_right()           

        active_sprite_list.update()
        enemy_list.update()
        player.level = current_level
        player.move()
        player.bounce()

        if player.rect.x >= 500:
            diff = player.rect.x - 500
            player.rect.x = 500
            current_level.shift_world(-diff)

        if player.rect.x <= 120:
            diff = 120 - player.rect.x
            player.rect.x = 120
            current_level.shift_world(diff)

        current_level.draw(screen)
        active_sprite_list.draw(screen)
        enemy_list.draw(screen)

        clock.tick(60)

        pygame.display.flip()

    pygame.quit()

if __name__ == "__main__":
    main()

感谢您帮助我!

2 个答案:

答案 0 :(得分:0)

最简单的做法可能是绘制像素(或虚拟像素),如果在绘制炸弹/人物像素时发现重叠,则表示发生了碰撞。

如果您需要更高性能的解决方案,您可以在碰撞检测中获得更复杂(和更高效)的方法。有关参考,请参阅维基百科碰撞检测。

答案 1 :(得分:0)

我建议为每个类使用pygame.sprite.Group()创建精灵组; BombPlayer。然后,使用pygame.sprite.spritecollide()

例如:

def Main()   
    ...
    player_list = pygame.sprite.Group()
    bomb_list = pygame.sprite.Group()
    ...

然后在您的逻辑处理循环中,在创建PlayerBomb实例后,您可以执行以下操作:

for bomb in bomb_list:
    # See if the bombs has collided with the player.
        bomb_hit_list = pygame.sprite.spritecollide(bomb, player_list, True)

        # For each bomb hit, remove bomb 
        for bomb in bomb_hit_list:
            bomb_list.remove(bomb)
            # --- Put code here that will trigger with each collision ---