Python如何检查目标对象是否不再是同一个实例或 "valid"

标签 python list object pygame

好的,在我的 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/

相关文章:

python - "Parseltongue": get Ruby to Speak a bit of Python?

python-requests 钩子(Hook)类似于 pycurl.WRITEFUNCTION?

c++ - 在 C++ 中打印链表

c++ - C++ 中的意外破坏

javascript - 将对象转换为适合 ajax post 的数组

python - 组合/平均多个数据文件

python - 用 python (NumPy) 求解热方程

java - 这两个代码片段之间有区别吗?如果有区别是什么?

r - 根据列表对象中的条件过滤 R 中的列表

java - 使用 .length 和 .length() 求长度有什么区别