實例:二維矢量模擬玩家移動
在游戲中,一般使用二維矢量保存玩家的位置,使用矢量計算可以計算出玩家移動的位置,下面的 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~
