首页 文章

两个精灵互相发现

提问于
浏览
2

你好再次Stack Overflow . 你可能还记得我在pygame程序中的单位产生问题,“桌上战争” . 我决定将我的游戏范围改为实时策略而不是回合制游戏 . 我希望游戏能够与顶级Flash游戏一起发挥:“战争时代” . 几乎所有东西都在游戏中起作用:产卵单位,游戏的HUD,甚至基础 Health . 不幸的是,我似乎无法弄清楚如何实现单位攻击敌人或敌人基地的能力 . 以下是单位本身的概念:

  • 该单位在团队基地周围的按键上产生: K_1Red_Infantry 类产生一个精灵

  • 生成时,单位将添加到 Group 类中 . 有两个 Group ,每个团队一个 .

  • 该单位通过 def update 内的 move_ip 呼叫移动,直到它到达靠近敌人基地的一个点,然后停在那里 .

以下是我想要为不同单位进行战斗的方法:

  • 只要在攻击范围内发现敌人,该装置就会停止 . 不同的单位有不同的攻击范围

  • 然后该单位每隔一秒攻击一次 .

  • 如果该单位成功地将敌方单位的生命值降低到0,则敌人死亡,另一个可能继续

  • 这个循环重复直到该单位到达敌人基地,然后它将以一秒的间隔攻击敌人基地 . 其中一个单位将能够对基地造成三倍的正常伤害 .

以下是我的代码示例,显示了 Red_Infantry 类:

class Red_Infantry(pygame.sprite.Sprite):
def __init__(self, screen):
    pygame.sprite.Sprite.__init__(self)
    self.image, self.rect = load_image('Soldier_red.png', -1)
    self.rect.move_ip(random.randint(75, 100), random.randint(275, 325))
    self.selected = 0
    self.area = screen.get_rect()
    self.health = 100 #Soldiers are have mediocre toughness.
    self.attack_damage = 25 #The amount of damage it deals
    self.range = 20 #The attack range of the unit.
    self.update()
def update(self):
    self.rect.move_ip(1, 0)
    if self.rect.right >= 725: #This position is close to the enemy base...
        self.rect.right = 725 #...where it will then stop
    if self.health <= 0:  
        self.kill() #a simple code that kills the sprite if his health reaches 0

主循环仅包含产生每个单元的能力 .

2 回答

  • 3

    这是一个起点

    class RedInfantry(pygame.sprite.Sprite):
        def __init__(self):
            self.screen = pygame.display.get_surface()
            self.image, self.rect = load_image('Soldier_red.png', -1)    
            self.rect.move_ip(random.randint(75, 100), random.randint(275, 325))
            self.target = None
            self.range = 20
            self.attack_cooldown = 200
            self.attack_last = 0
    
        def move_toward(self, target):
            # move toward players click destination, if one is set.
            # else toward my attack target
    
        def update(self):
            # move...
            self.find_target()
            self.move_toward(self.target)
            self.attack()
            # check HP
            if self.health <= 0:
                self.kill()
    
        def find_target(self):
            """finds new targets in range:
            for speed: only call this once every 200ms."""
            if self.target is not None: return
            for enemy in B.sprites():
                if distance(self.rect.center, enemy.rect.center) <= self.range:
                    self.target = enemy
                    return
            # else no targets in range
            self.target = None  
    
    
        def attack(self):
            """attack, if able.
            target exists? still alive? gun cooldown good?"""
            if self.target is None: return
            if self.target.health <= 0: return
            if not self.cooldown_ready(): return
    
            # all good, fire. could verify still in range. 
            self.target.damage(self.attack_damage)
    
        def cooldown_ready(self):
            # gun ready to fire? has cooldown in MS elapsed.
            now = pygame.time.get_ticks()
            if now - self.attack_last >= self.attack_cooldown:
                self.attack_last = now
                return True
            return False
    
  • 1

    从你的问题来看,并不完全清楚群体如何与每个群体互动以进行发现 . 在下文中,如果A的任何成员a在B的任何成员b的某个指定范围内,我将假设A组“发现”B组 .

    最简单的方法是迭代所有(a,b)对 . 要做到这一点,你可以使用itertools库,比如...

    spotted = False
    for a, b in itertools.product(A.sprites( ), B.sprites( )):
        if is_in_range(a, b):
            spotted = True
            break
    

    这种方法的问题在于计算成本相当高 . (它的复杂性是n ** 2.)此外,如果没有某种修剪和优化,你必须为每对友方/敌人组运行这段代码 . 现在,如果保证每个组具有一些恒定的几何形状,那么我们可以使计算MUCH的成本更便宜 . 但是,假设组没有固定的几何体,那么我建议您考虑使用几何包来为您完成大量工作 . 这些包非常强大且非常高效......而且它们中的很多也非常容易使用 . 可能有PyGame特有的几何包...我现在想不到任何东西 .

    我经常使用shapely package . 如果我们使用匀称,那么确定在检测范围内的组的问题更像是......

    import shapely
    import shapely.geometry
    
    #-- Build a polygon envelope around the members of the group.
    pointsA = shapely.geometry.MultiPoint(map(lambda r: r.center, A.sprites( )))
    pointsB = shapely.geometry.MultiPoint(map(lambda r: r.center, B.sprites( )))
    
    #-- Ask shapely to give the minimum distance between the hulls that
    #-- encompass the two groups.
    distance = pointsA.convex_hull.distance(pointsB.convex_hull)
    
    if distance < RANGE_OF_DETECTION:
       detected = True
    else:
       detected = False
    

    请注意,我还没有测试上面的代码...它只是为了演示使用shapely库来帮助进行几何计算的一般想法 .

    如果您不熟悉游戏编程,您可能还需要研究使用四叉树作为修剪需要完成多少几何计算的方法 .

相关问题