最近自学python语言的过程中接触到了Pygame,这也是我第一次接触到游戏引擎。作为一个男生对游戏有天然的兴趣,所以当看到pygame时自己做个小游戏的想法便油然而生,在这个过程中遇到了很多问题。基于学习和讨论的基于学习和讨论的目的写了这个文章。
遇到的问题:怎么实现敌方精灵的自动追踪?
在查阅了相关资料后有了解决办法—— 转向力 = 所需速度 - 当前速度
在上述公式中,我们已知精灵的当前速度和目标位置只需要计算施加的速度即可,我们可以这样设计敌人精灵,
(假设我们的目标位置是鼠标位置)
class Mob(pg.sprite.Sprite):
def __init__(self):
self.groups = all_sprites
pg.sprite.Sprite.__init__(self, self.groups)
self.image = pg.Surface((MOB_SIZE, MOB_SIZE))
self.image.fill(YELLOW)
self.rect = self.image.get_rect()
self.pos = vec(randint(0, WIDTH), randint(0, HEIGHT))#当前位置
self.vel = vec(MAX_SPEED, 0).rotate(uniform(0, 360))#当前速度
self.acc = vec(0, 0)#施加速度
self.rect.center = self.pos
按照上述公式我们不难得出如下方法,
def follow_mouse(self):
mpos = pg.mouse.get_pos()#鼠标位置
self.acc = (mpos - self.pos)
但这样并不能得到理想的效果,因为如果鼠标位置距离精灵当前位置很大,所求得的施加速度self.acc可能
非常大,
“瞬间”就会将敌人精灵拉到目标位置,或者
运动轨迹比较生硬。
我们可以控制转向力的大小来解决这个问题,在精灵类之外添加如下常量,
MAX_SPEED = 5 #最大速度
MAX_FORCE = 0.1 #最大力量
改进函数
def follow_mouse(self),对施加速度进行限制。
def seek(self, target):
self.desired = (target - self.pos).normalize() * MAX_SPEED
steer = (self.desired - self.vel)
if steer.length() > MAX_FORCE:
steer.scale_to_length(MAX_FORCE)
return steer
如此运动轨迹已经变得“优美”起来了,但还有一个BUG,当敌人精灵到达目标地点后,
无法停止运动,
出现持续
“抖动”现象。查看我们的代码就会发现,施加给敌人精灵的速度一直存在,并没有在到达目标地点
后消失。为解决抖动现象,我们可以设定一个常量表示到目标位置的临界距离,大于这个距离时,敌人精灵
“全速”接近目标位置,小于这个距离时慢慢减小施加的速度。
APPROACH_RADIUS = 120 #表示距离的常量
继续改进def seek(self, target)函数,
def seek_with_approach(self, target):
self.desired = (target - self.pos)#需要目标向量
dist = self.desired.length()#目标向量大小
self.desired.normalize_ip()
if dist < APPROACH_RADIUS:
self.desired *= dist / APPROACH_RADIUS * MAX_SPEED
else:
self.desired *= MAX_SPEED
steer = (self.desired - self.vel)
if steer.length() > MAX_FORCE:
steer.scale_to_length(MAX_FORCE)
return steer
这样便可实现相对完美的目标追踪运动了。
最后完整的测试代码,点击打开链接