1. 程式人生 > >pygame遊戲程式設計心得(一)——轉向行為(目標追蹤)

pygame遊戲程式設計心得(一)——轉向行為(目標追蹤)

 最近自學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
這樣便可實現相對完美的目標追蹤運動了。 最後完整的測試程式碼,點選開啟連結