首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >python游戏玩家与敌人和子弹相撞

python游戏玩家与敌人和子弹相撞
EN

Stack Overflow用户
提问于 2021-11-14 10:18:14
回答 2查看 435关注 0票数 0

我在玩一款“射击”游戏,里面有角色类和5种不同的子弹类。玩家和敌人是角色类的目标。我把子弹的起始位置设置在字符的中间(所以子弹是从字符中出来的)。

碰撞是由碰撞定义的。当玩家向敌人射击时,"enemy.rect.colliderect(bullet1)“的效果很好。如果敌人因为子弹而开始向玩家射击,那么问题就开始了。

我可以通过多个“子弹”类来解决这个问题。玩家和敌人将从不同的类中射击,但每个角色得到5个不同的子弹类,每个类都有不同的变量,而较短的类则有大量的代码。

我确信有一个聪明的解决方案,而不是重复我的代码行(~500行)

有什么建议吗?谢谢:)

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-11-14 10:30:54

一个简单的解决方案是,您可以简单地为项目提供一个额外的参数:一个不应该检查的矩形。因此,在检查子弹碰撞时,不需要检查这个矩形。

最小示例(代码注释中的解释):

代码语言:javascript
复制
import pygame


pygame.init()
screen = pygame.display.set_mode((500, 400))
clock = pygame.time.Clock()


class Bullet:
    # provide an argument for what to check and what to exclude
    def __init__(self, start_pos, x_direction, check, exclude):
        self.image = pygame.Surface((10, 10))
        self.image.fill((255, 255, 0))
        self.rect = self.image.get_rect(center=start_pos)
        self.x_direction = x_direction
        self.check, self.exclude = check, exclude
        self.x_velocity = 5 * self.x_direction
        self.damage = 5
        self.destroy = False

    def draw(self, surf):
        surf.blit(self.image, self.rect)

    def update(self):
        # go over the list of entities to check
        for entity in self.check:
            # if the entity is not the one that is excluded and the entity has
            # attributes that are needed here check for collision
            # and if there is then set the destroy flag to True
            # and stop updating. Also some check to see if the bullet has traveled
            # too far or somethin like that could be added
            if (entity is not self.exclude and hasattr(entity, 'health')
                    and hasattr(entity, 'rect')):
                if self.rect.colliderect(entity.rect):
                    entity.health -= self.damage
                    self.destroy = True
                    return
        self.rect.move_ip(self.x_velocity, 0)


# simple entity class to represent entities (in this case
# only the players and enemies since theoretically this could
# be base class both for bullets and players and enemies)
class Entity:
    def __init__(self, x, y, color, name):
        self.color, self.name = color, name
        self.rect = pygame.Rect(x, y, 30, 60)
        self.health = 100
        self.prev_health = self.health

    def draw(self, surf):
        pygame.draw.rect(surf, self.color, self.rect)

    def update(self):
        # if health has been reduced print the current health
        if self.health < self.prev_health:
            print(f'{self.name} health: {self.health}')
            self.prev_health = self.health


# create the entities
player = Entity(100, 200, (0, 255, 0), 'player')
enemy = Entity(370, 200, (255, 0, 0), 'enemy')
# create a list to store bullets in
bullets = []

while True:
    screen.fill((0, 0, 0))
    
    # create a list for bullets to remove
    # so that they can be removed later
    # without interfering with the checking for loop
    remove_bullets = []
    for bullet in bullets:
        # if the bullet should be destroyed don't update it
        # and add to the bullets to remove
        if bullet.destroy:
            remove_bullets.append(bullet)
        else:
            bullet.update()
            bullet.draw(screen)
    # remove destroyed bullets from the main list
    for bullet in remove_bullets:
        bullets.remove(bullet)
    
    # update
    enemy.update()
    enemy.draw(screen)

    player.update()
    player.draw(screen)

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            exit()
        if event.type == pygame.KEYDOWN:
            # usually you would just pass a list of entities that are not like
            # this but rather referenced by name so you would use that
            # instead of passing a list like this. In that case it would make more
            # sense to have an excluded entity as in this case you could just not include
            # in the list at all. Also going over a list to remove a single element
            # would likely be more wasteful
            if event.key == pygame.K_a:
                # if a pressed create a bullet traveling from enemy to player
                bullet = Bullet(enemy.rect.center, -1, [player, enemy], enemy)
                bullets.append(bullet)
            if event.key == pygame.K_d:
                # if d pressed create a bullet traveling from player to enemy
                bullet = Bullet(player.rect.center, 1, [player, enemy], player)
                bullets.append(bullet)

    pygame.display.update()
    clock.tick(60)

另外,我觉得你不需要5个子弹类(敌人和玩家绝对不需要5个),如果子弹的行为类似,你应该可以简单地更改子弹的一些参数,而不是创建5个类。

票数 2
EN

Stack Overflow用户

发布于 2021-11-15 03:47:16

代码语言:javascript
复制
bullets = []
to shoot, append this V to list
[[positionX, positionY], [directionX, directionY], Rect for the bullet]

collisions:
for bullet in bullets:
  <update stuff here>
  if bullet[2].colliderect(playerrect): # (rect)
    bullets.remove(bullet)
    pass
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69962095

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档