實例:二維矢量模擬玩家移動
在游戲中,一般使用二維矢量保存玩家的位置,使用矢量計算可以計算出玩家移動的位置,下面的 demo 中,首先實現二維矢量對象,接着構造玩家對象,最后使用矢量對象和玩家對象共同模擬玩家移動的過程
1)實現二維矢量結構
矢量是數據中的概念,二維矢量擁有兩個方向的信息,同時可以進行加、減、乘(縮放)、距離、單位化等計算
在計算機中,使用擁有 x 和 y 兩個分量的 Vecor2 結構體實現數學中二維向量的概念,如下:
# coding=utf-8 import math import time # 坐標類 class Vector(object): def __init__(self, x=0, y=0): self.x = x self.y = y # 相加 def add(self, vector): self.x += vector.x self.y += vector.y # 相減 def sub(self, vector): x = self.x - vector.x y = self.y - vector.y return Vector(x, y) # 相乘 def multi(self, speed): self.x *= speed self.y *= speed return self # 計算距離 def distance(self, vector): dx = self.x - vector.x dy = self.y - vector.y return math.sqrt(dx ** 2 + dy ** 2) # 矢量單位化 def normalize(self): mag = self.x ** 2 + self.y ** 2 if mag > 0: one_over_mag = 1 / math.sqrt(mag) vector = Vector(x=self.x * one_over_mag, y=self.y * one_over_mag) else: vector = Vector() return vector
2)實現玩家對象
玩家對象負責存儲玩家的當前位置、目標位置和移動速度,使用 moveTo() 為玩家設定目的地坐標,使用 update() 更新玩家坐標
# 玩家類 class Player(object): def __init__(self, current_vector=None, target_vector=None, speed=0): self.current_vector = current_vector self.target_vector = target_vector self.speed = speed # 獲取玩家坐標 def get_current_vector(self): return self.current_vector # 判斷是否到達終點 def is_arrived(self): return self.current_vector.distance(self.target_vector) < self.speed # 更新玩家位置 def update_vector(self): # 獲取方向矢量(固定值) direction_vector = self.target_vector.sub(self.current_vector) # 矢量單位化(固定值) normalize_vector = direction_vector.normalize() # 根據速度計算 x, y 方向上前進的長度 ongoing_vector = normalize_vector.multi(self.speed) # 更新位置 self.current_vector.add(ongoing_vector)
更新坐標稍微復雜一些,需要通過矢量計算獲得玩家移動后的新位置,步驟如下:
- 使用矢量減法,將目標位置(targetPos)減去當前位置(currPos)即可計算出位於兩個位置之間的新矢量
- 使用 normalize() 方法將方向矢量變為模為 1 的單位化矢量,
- 然后用單位化矢量乘以玩家的速度,就能得到玩家每次分別在 x, y 方向上移動的長度
- 將目標當前位置的坐標與移動的坐標相加,得到新位置的坐標,並做修改
3)主程序
玩家移動是一個不斷更新位置的循環過程,每次檢測玩家是否靠近目標點附近,如果還沒有到達,則不斷地更新位置,並打印出玩家的當前位置,直到玩家到達終點
if __name__ == '__main__': p = Player() p.current_vector = Vector(0, 0) p.target_vector = Vector(2, 2) p.speed = 0.2 while not p.is_arrived(): p.update_vector() print(f"({p.current_vector.x}, {p.current_vector.y})") time.sleep(1) print("arrive at the destination")
- 將 Player 實例化,設定玩家終點坐標,當前坐標
- 更新玩家位置
- 每次移動后,打印玩家的位置坐標
- 延時 1 秒(便於觀察效果)
ending~