我一直在玩游戏,有两个玩家[在这种情况下只是因为它易于绘制而且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()
答案 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