pygame遊戲程式設計心得(一)——轉向行為(目標追蹤)
阿新 • • 發佈:2019-01-27
最近自學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
這樣便可實現相對完美的目標追蹤運動了。
最後完整的測試程式碼,點選開啟連結