再次问好Stack Overflow。你可能还记得我在pygame程序中的单位产生问题,“桌上战争”。我决定将我的游戏范围改为实时策略而不是回合制游戏。我希望游戏能够与顶级Flash游戏一起发挥:“战争时代”。几乎所有东西都在游戏中起作用:产卵单位,游戏的HUD,甚至基础健康。不幸的是,我似乎无法弄清楚如何实现单位攻击敌人或敌人基地的能力。以下是单位本身的概念:
K_1
从Red_Infantry
类产生一个精灵Group
课程中。有两个Group
,每个团队一个。move_ip
内的def update
呼叫移动,直到它到达靠近敌人基地的位置,然后停在那里。以下是我希望战斗不同单位的方法:
以下是我的代码示例,显示了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
主循环只包含产生每个单位的能力。
答案 0 :(得分:3)
从您的问题来看,并不完全清楚群体如何与每个群体互动以进行发现。在下文中,如果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库来帮助进行几何计算的一般想法。
如果您不熟悉游戏编程,您可能还希望使用四叉树作为修剪需要完成多少几何计算的方法。
答案 1 :(得分:1)
这是一个起点
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