好的,在我的 2d 游戏中,我有几个在初始化时具有空 self.target = [] 属性的“单元格”对象实例( Sprite 对象)。
然后它们会在附近找到一个有效的“植物”目标对象,这将成为细胞的“ self 目标”。
然后“细胞”将导航到植物,最终与植物发生碰撞并吃掉它,然后植物被设置为“.kill()”,另一个在随机的新坐标处重生。有几个植物实例(spr_plant_group 的一部分)和几个单元格(属于 spr_cell_group)。
每株植物“存活”X 个游戏刻(我认为是 200 个),如果到那时还没有被吃掉,就会被 .kill()-ed 并在随机坐标处生成一个新植物。
问题是这样的:如果一个细胞的目标植物碰巧因年龄而消失,或者被什么东西吃掉,细胞的 self.target 信息仍然指向旧的“植物”对象的数据。这意味着细胞正在追逐一个幻影对象,显然仍然具有有效的 x 和 y 坐标。
问题:如何告诉单元格它的目标已死、消失、无效?如果我能做到这一点,我认为它会修复“幻影”目标对象。
相关代码片段:
class Agent(sprite.Sprite):
def __init__(self, sense_range, size, food, maxspeed):
sprite.Sprite.__init__(self)
self.x = randint(0,450)
self.y = randint(0,450)
self.ang = randint(0,359)
self.turn_rate = 2
self.dx = 0
self.dy = 0
self.speed = 1
self.maxspeed = maxspeed
self.food = int(food)
self.max_food = food*1.5
self.target = []
self.sense_range = sense_range
# Snip------This part below is supposed to find a new target, but it only
# works for the first one when the cell spawns, then I can't seem to
# get it to become 'empty' so that the "if self.target == []" can do its
# thing....
def seek_food(self):
if (self.target == []):
#find cell a target within "sense_range" distance (say 200 pixels)
dist = self.sense_range
targ = []
for t in spr_plant_group:
t_dist = abs(self.x - t.x)
if t_dist <= dist:
targ = t
dist = t_dist
self.target = targ
print ("Found target...",dist, self.target)
else:
#already have a target, so move cell toward target
dx = self.target.x - self.x
dy = self.target.y - self.y
rads = atan2(dy,dx)
rads %= 2*pi
degs = degrees(rads)
direction = degs - self.ang
if direction > 0:
self.ang = self.ang + self.turn_rate
elif direction < 0:
self.ang = self.ang - self.turn_rate
# Correct for angle being out of 0-360* range
if self.ang > 360:
self.ang -= 360
elif self.ang < 0:
self.ang += 360
#---This is just a piece of the Plant class for your reference
class Plant (sprite.Sprite):
def __init__(self):
sprite.Sprite.__init__(self)
self.x = randint(0,450)
self.y = randint(0,450)
self.age = 1 + randint(0,50)
供引用,如下。植物的年龄会增加到 200 ticks,然后它们会被杀死,然后新的植物会重生...
def update_plants():
for shrub in spr_plant_group:
shrub.age += 1
# Respawn a new plant in a different place
if shrub.age >= 200:
shrub.kill()
plant.append (Plant())
最佳答案
编辑:实际上,它要简单得多。 Pygame's Sprite class supports an alive method ,所以只需这样做:
def seek_food(self):
if (self.target == [] or not self.target.alive()):
# Find a new target that isn't dead...
else:
# Move to the (alive) target...
您可以使用 the Observer design pattern 的一些变体.使用额外的属性扩展您的 Plant
类,该属性跟踪任何以植物为目标的 Cell
实例。当一个细胞以植物为目标时,它会将自己添加到植物的列表中。在植物死亡之前,它会通知它的所有细胞。
Plant 类中的新属性:
class Plant (sprite.Sprite):
def __init__(self):
# ...
self.followers = []
# ...
细胞订阅植物的追随者列表:
def seek_food(self):
if (self.target == []):
# ...
self.target = targ
self.target.followers.append(self)
# ...
else:
# ...
Plant 类重写其父类的 kill 函数,以便它在死亡前通知其追随者:
(这里,细胞类直接修改每个植物的目标,但如果你愿意,你可以封装不同的行为)
def kill(self):
for follower in self.followers:
follower.target = []
self.followers = []
super().kill()
关于Python如何检查目标对象是否不再是同一个实例或 "valid",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46231449/