[英]Two sprites spotting each other
Hello again Stack Overflow. 您好再次堆栈溢出。 you probably remember me from my unit spawning problem in my pygame program, "Table Wars." 您可能从pygame程序“ Table Wars”中的单元生成问题中记得我。 I decided to change the scope of my game to a real-time strategy rather than a turn-based game. 我决定将游戏范围改为实时策略,而不是回合制游戏。 I want the game to play along the lines of top Flash game: "Age of War." 我希望游戏能够按照Flash游戏的最高水平:“战争年代”进行游戏。 Almost everything works in the game: spawning units, the HUD for the game, and even base health. 游戏中几乎所有的东西都起作用:生成单元,游戏的HUD甚至基础生命值。 Unfortunately, I can't seem to figure out how to implement the ability for units to attack enemies or the enemy base. 不幸的是,我似乎无法弄清楚如何实现部队攻击敌人或敌人基地的能力。 Here is the concepts going on for the units themselves: 这是单元本身正在进行的概念:
K_1
spawns a sprite from the Red_Infantry
class 该单位在围绕团队基地的按键上生成: K_1
从Red_Infantry
类生成一个Sprite Group
class. 生成该单元后,会将其添加到Group
类。 There are two Group
s, one for each team. 有两个Group
,每个团队一个。 move_ip
call within a def update
until it reaches a point close to the enemy base, where it stops. 该单位在def update
通过move_ip
调用移动,直到到达靠近敌人基地的地点为止。 Here is how I want combat to go for the different units: 这是我希望战斗适用于不同单位的方式:
Here is a sample of my code, showing the Red_Infantry
class: 这是我的代码示例,显示了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
The main loop only contains the ability to spawn each of the units. 主循环仅包含生成每个单元的功能。
It's not entirely clear from your question how groups interact with each for spotting. 从您的问题尚不清楚,小组如何与每个小组互动以进行发现。 In the following, I'm going to assume that Group A "spots" Group B if any member a of A is within some specified range of any member b of B. 在下文中,如果A的任何成员a在B的任何成员b的指定范围内,我将假定A组“发现” B组。
The simplest way to do this would be to just iterate over all (a,b) pairs. 最简单的方法是对所有(a,b)对进行迭代。 To do this, you can use the itertools library, something like... 为此,您可以使用itertools库,例如...
spotted = False
for a, b in itertools.product(A.sprites( ), B.sprites( )):
if is_in_range(a, b):
spotted = True
break
The problem with this approach is that the computational cost is rather high. 这种方法的问题是计算成本相当高。 (It's n**2 in complexity.) Furthermore, without some kind of pruning and optimization, you have to run this block of code for each pair of friendly/enemy group, too. (复杂度为n ** 2。)此外,如果不进行任何修剪和优化,则也必须为每对友好/敌对组运行此代码块。 Now, if each group is guaranteed to have some constant geometry, then we can make the cost of computing MUCH cheaper. 现在,如果保证每个组都具有恒定的几何形状,那么我们可以使MUCH的计算成本降低。 However, assuming that groups have no fixed geometry, then I'd recommend looking into using a geometry package to do a lot of the work for you. 但是,假设组没有固定的几何图形,那么我建议您考虑使用几何图形软件包为您完成很多工作。 These packages are very powerful and very efficient...and a lot of them are also surprisingly easy to use. 这些软件包功能非常强大且非常高效……而且其中许多还非常易于使用。 There may be geometry packages specific to PyGame...I can't think of any at the moment. 可能会有特定于PyGame的几何图形包...我暂时无法想到。
I often use the shapely package . 我经常使用匀称的包装 。 If we use shapely, then the problem of determining groups that are within detection range is something more like... 如果我们使用得体,则确定检测范围内的组的问题更像是...
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
NOTE that I haven't tested the code above...it's only to demonstrate the general idea of using the shapely library to help with the geometry computations. 请注意,我还没有测试上面的代码...这只是演示使用形状库帮助进行几何计算的一般想法。
If you're new to game programming, you might also want to look into using quadtrees as a means of pruning how much geometry computation needs to be done. 如果您是游戏编程的新手,您可能还想研究使用四叉树作为修剪需要完成多少几何计算的一种方法。
Here's a starting point 这是一个起点
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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.