Pygame - 两名球员的射击功能

时间:2017-11-03 14:36:52

标签: python pygame

我一直在玩游戏,有两个玩家[在这种情况下只是因为它易于绘制而且sprite.collide_rect函数返回一个bool],它们互相争斗。我想为游戏增加一个拍摄功能,但是在双人游戏中没有真正的解决方案。

我想要做的是,当第一个玩家按下空格或第二个玩家按下f时,他们都会射击他们自己的子弹类型,不会与他们发生碰撞,但会与敌人发生碰撞,反之亦然。

有没有办法在pygame中执行此操作? (对不起,如果我的解释不是最好的)

以下是相关代码的一些部分

    #Sprite Config
    class Player(pygame.sprite.Sprite):

        def __init__(self, image):

            super().__init__()

             self.image = image
             self.rect = self.image.get_rect()

        def right(self, pixels):
            self.rect.x += pixels

        def left (self, pixels):
            self.rect.x -= pixels

        def up(self, pixels):
            self.rect.y -= pixels

        def down(self, pixels):
            self.rect.y += pixels

        def dashleft(self, pixels):
            self.rect.x -= pixels

        def dashright(self, pixels):
            self.rect.x += pixels


    # Collision Logic

    collision = pygame.sprite.collide_rect(Player1, Player2)

    if collision == True:
        AllSprites.remove(Player1, Player2)
        pygame.display.set_caption("They Destroyed Eachother! Space to retry")
        Player1.rect.x = BlueSpawnX
        Player1.rect.y = BlueSpawnY
        Player2.rect.x = OrangeSpawnX
        Player2.rect.y = OrangeSpawnY
        Again = True

    if Again == True and keys[pygame.K_SPACE]:
        AllSprites.add(Player1, Player2)
        pygame.display.set_caption("Circles Fight!")

    AllSprites.update()

    # Drawing
    Screen.fill(Black)
    Screen.blit(Text,
               (250 - Text.get_width() // 2, 240 - Text.get_height() // 2))
    AllSprites.draw(Screen)

    # Closing
    pygame.display.flip()
    Clock.tick(FPS)

pygame.quit()

2 个答案:

答案 0 :(得分:1)

你走在正确的轨道上。 现在就阅读sprite Groups on pygame文档的文档。

然后,为子弹本身创建另一个继承自pygame.spite.Sprite的类,每当一个玩家射击时,只需创建新的子弹,然后将其添加到“player1_shoots”组。您可以在组上调用碰撞方法,这将检查该组中所有精灵的碰撞,因此,通过使用这种面向对象的方法,玩家基本上可以免费获得多个镜头。

另外,请注意,您应该在子弹类上编写一个“更新”方法,以便朝正确的方向移动子弹。然后,您只需致电group.update()即可立即更新所有项目符号。

作为旁注,如果你愿意,尝试使用不同于矩形的不同图像 - 你会注意到,对于大多数游戏运行的速度,如果针对实际图像或逐像素游戏计算碰撞,则几乎没有差别。你需要一个非常具体的游戏,而不是直接碰撞。当你这样做时,Pyagme甚至会为此提供支持。

答案 1 :(得分:1)

这是一个示例,其中我存储了对玩家内部两个子弹组的引用。如果按下开火键('f'或空格),子弹实例将添加到播放器的项目组和all_sprites组中,然后更新它们。

碰撞检测在update方法中进行,我检查玩家是否与self.enemy_bullets组的子弹发生碰撞。如果存在冲突,我会减少self.health,如果它是<= 0,我会调用self.kill()从所有精灵组中删除精灵。

import pygame as pg
from pygame.math import Vector2


class Player(pg.sprite.Sprite):

    def __init__(self, pos, color, left, right, up, down, fire,
                 all_sprites, bullets, enemy_bullets):
        super().__init__()
        self.image = pg.Surface((30, 50))
        self.image.fill(color)
        self.rect = self.image.get_rect(topleft=pos)
        self.vel = Vector2(0, 0)
        self.pos = Vector2(self.rect.topleft)
        self.dt = 0.03
        self.key_left = left
        self.key_right = right
        self.key_up = up
        self.key_down = down
        self.key_fire = fire
        # Store the groups as attributes, so that you can add bullets
        # and use them for the collision detection in the update method.
        self.all_sprites = all_sprites
        self.bullets = bullets
        self.enemy_bullets = enemy_bullets
        self.fire_direction = Vector2(350, 0)
        self.health = 3

    def update(self, dt):
        self.dt = dt
        self.pos += self.vel
        self.rect.center = self.pos

        # Check if enemy bullets collide with the player, reduce
        # health and kill self if health is <= 0.
        collided_bullets = pg.sprite.spritecollide(self, self.enemy_bullets, True)
        for bullet in collided_bullets:
            self.health -= 1
            if self.health <= 0:
                self.kill()

    def handle_event(self, event):
        if event.type == pg.KEYDOWN:
            if event.key == self.key_left:
                self.vel.x = -90 * self.dt
                self.fire_direction = Vector2(-350, 0)
            elif event.key == self.key_right:
                self.vel.x = 90 * self.dt
                self.fire_direction = Vector2(350, 0)
            elif event.key == self.key_up:
                self.vel.y = -90 * self.dt
                self.fire_direction = Vector2(0, -350)
            elif event.key == self.key_down:
                self.vel.y = 90 * self.dt
                self.fire_direction = Vector2(0, 350)
            elif event.key == self.key_fire:  # Add a bullet to the groups.
                bullet = Bullet(self.rect.center, self.fire_direction)
                self.bullets.add(bullet)
                self.all_sprites.add(bullet)
        elif event.type == pg.KEYUP:
            if event.key == self.key_left and self.vel.x < 0:
                self.vel.x = 0
            elif event.key == self.key_right and self.vel.x > 0:
                self.vel.x = 0
            elif event.key == self.key_up and self.vel.y < 0:
                self.vel.y = 0
            elif event.key == self.key_down and self.vel.y > 0:
                self.vel.y = 0


class Bullet(pg.sprite.Sprite):

    def __init__(self, pos, velocity):
        super().__init__()
        self.image = pg.Surface((5, 5))
        self.image.fill(pg.Color('aquamarine1'))
        self.rect = self.image.get_rect(center=pos)
        self.pos = pos
        self.vel = velocity

    def update(self, dt):
        self.pos += self.vel * dt
        self.rect.center = self.pos


class Game:

    def __init__(self):
        self.fps = 30
        self.done = False
        self.clock = pg.time.Clock()
        self.screen = pg.display.set_mode((800, 600))
        self.bg_color = pg.Color('gray30')

        # Sprite groups that contain the players and bullets.
        self.all_sprites = pg.sprite.Group()
        self.bullets1 = pg.sprite.Group()  # Will contain bullets of player1.
        self.bullets2 = pg.sprite.Group()  # Will contain bullets of player2.
        player1 = Player(
            (100, 300), pg.Color('dodgerblue2'),
            pg.K_a, pg.K_d, pg.K_w, pg.K_s, pg.K_f,
            self.all_sprites, self.bullets1, self.bullets2)  # Pass the groups.
        player2 = Player(
            (300, 400),  pg.Color('sienna2'),
            pg.K_j, pg.K_l, pg.K_i, pg.K_k, pg.K_SPACE,
            self.all_sprites, self.bullets2, self.bullets1)  # Pass the groups.
        self.all_sprites.add(player1, player2)
        self.players = pg.sprite.Group(player1, player2)

    def run(self):
        while not self.done:
            self.dt = self.clock.tick(self.fps) / 1000
            self.handle_events()
            self.run_logic()
            self.draw()

    def handle_events(self):
        for event in pg.event.get():
            if event.type == pg.QUIT:
                self.done = True
            for player in self.players:
                player.handle_event(event)

    def run_logic(self):
        self.all_sprites.update(self.dt)

    def draw(self):
        self.screen.fill(self.bg_color)
        self.all_sprites.draw(self.screen)
        pg.display.flip()


if __name__ == '__main__':
    pg.init()
    Game().run()
    pg.quit()

如果您希望直接在事件循环中执行事件处理,可以将Player的{​​{1}}方法中的代码移动到handle_event的{​​{1 }} 方法。这是一个缩短的例子:

Game