The Nature of Code閱讀心得與Python實作:1.7 Motion with Vectors

閱讀時間約 8 分鐘

在Example 1.2中,我們利用向量來寫模擬物體運動的程式。在程式中,我們先算出球的位置,然後在那個位置畫出球:

position += velocity
pygame.draw.circle(screen, BLACK, position, RADIUS)

這就是模擬物體運動的最基本做法,這個做法,可以歸納為如下的演算法:

Motion 101
1. 將位置向量加上速度以得到新的位置向量
2. 在新位置畫出物體

題外話。看到101這個數字,大概可以猜到代表的意思。不過,實在很好奇,為什麼是101,不是100或123?網上搜尋了一下,在維基百科:101 (number)找到了答案。

言歸正傳。在那個例子中,是把Motion 101相關的程式直接寫在主程式中,但這並不是個好做法。比較好的做法,是把這部分的程式封裝在一個類別中,以發揮物件導向設計的優勢。接下來,就來設計一個叫做Mover的類別,把這部分的程式封裝在其中。

在設計Mover這個類別時,必須考慮兩個問題:

  1. Mover的物件裡頭包含了哪些資料?
  2. Mover的物件具有哪些功能?

這兩個問題的答案就在Motion 101這個演算法中。

一個Mover的物件,應該含有兩份資料:位置及速度,也就是positionvelocity這兩個向量。至於它應具備的功能,其實也很簡單,就是移動及現身被看見。我們會把移動相關的程式碼寫在update()這個方法中;而現身被看見,其實也就是在畫面上畫出物件樣貌,這部分的程式碼,則寫在show()這個方法中。程式碼如下:

def update(self):
    self.position += self.velocity

def show(self):
    pygame.draw.circle(self.screen, (0, 0, 0), self.position, 24)

在建立Mover的物件時,需要先設定,也就是初始化(initialize)的東西,如起始位置、初始速度等,就寫在__init__()中:

def __init__(self):
# 取得顯示畫面的大小
self.screen = pygame.display.get_surface()
self.width, self.height = self.screen.get_size()

# 設定物件的起始位置
x = random.uniform(0, self.width)
y = random.uniform(0, self.height)
self.position = pygame.Vector2(x, y)

# 設定物件的初始速度
vx = random.uniform(-2, 2)
vy = random.uniform(-2, 2)
self.velocity = pygame.Vector2(vx, vy)

最後,我們要決定物件碰到邊界時,會怎麼反應。假設我們希望碰到邊界時,物件會繞一圈從另一邊跑出來,程式的寫法如下:

def check_edges(self):
if self.position.x > self.width:
self.position.x = 0
elif self.position.x < 0:
self.position.x = self.width

if self.position.y > self.height:
self.position.y = 0
elif self.position.y < 0:
self.position.y = self.height

這樣就完成了Mover這個類別的設計。

下面的例子,就是使用Mover這個類別產生一個物件mover,然後讓這個mover在畫面上移動。程式如下:

Example 1.7: Motion 101 (Velocity)

class Mover:
def __init__(self):
# 取得顯示畫面的大小
self.screen = pygame.display.get_surface()
self.width, self.height = self.screen.get_size()

# 設定物件的起始位置
x = random.uniform(0, self.width)
y = random.uniform(0, self.height)
self.position = pygame.Vector2(x, y)

# 設定物件的初始速度
vx = random.uniform(-2, 2)
vy = random.uniform(-2, 2)
self.velocity = pygame.Vector2(vx, vy)

def update(self):
self.position += self.velocity

def show(self):
pygame.draw.circle(self.screen, (0, 0, 0), self.position, 24)

def check_edges(self):
if self.position.x > self.width:
self.position.x = 0
elif self.position.x < 0:
self.position.x = self.width

if self.position.y > self.height:
self.position.y = 0
elif self.position.y < 0:
self.position.y = self.height


# python version 3.10.9
import random
import sys

import pygame # version 2.3.0

pygame.init()

pygame.display.set_caption("Example 1.7: Motion 101 (Velocity)")

WHITE = (255, 255, 255)

screen_size = (640, 360)
screen = pygame.display.set_mode(screen_size)

FPS = 60
frame_rate = pygame.time.Clock()

mover = Mover()

while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()

screen.fill(WHITE)

mover.update()
mover.check_edges()
mover.show()

pygame.display.update()
frame_rate.tick(FPS)

Motion 101這個例子其實挺單調的,因為那顆球永遠都是氣定神閒地以相同的速度移動著,既不會加速,也不會減速。想要讓球的移動方式更多變、更真實一些,就必須引入加速度(acceleration)這個大家耳熟能詳的物理量。


15會員
112內容數
寫點東西自娛娛人
留言0
查看全部
發表第一個留言支持創作者!
ysf的沙龍 的其他內容
介紹如何在模擬物體運動時,引入加速度這個物理量。
介紹pygame支援的向量運算,以及向量的減法、乘法、除法實際上是怎麼計算的。
這一節談的是向量的定義,以及如何運用向量來建立模擬物體運動時,關於位置和速度間的關係式。
介紹如何在模擬物體運動時,引入加速度這個物理量。
介紹pygame支援的向量運算,以及向量的減法、乘法、除法實際上是怎麼計算的。
這一節談的是向量的定義,以及如何運用向量來建立模擬物體運動時,關於位置和速度間的關係式。
你可能也想看
Thumbnail
「設計不僅僅是外觀和感覺。設計是其運作的方式。」 — Steve Jobs 身為一個獨立文案,許多人會以為我們的生活只需要面對電腦,從無到有,用精巧的文字填滿空白的螢幕,呈現心目中獨具風格的作品。 ——有的時候可以如此,但其實這是我們夢寐以求的偶發日常。 更多的時候,白天的工作時間總被各種繁雜
Thumbnail
台股、美股近期明顯回檔,市場敘事發生改變,壞消息一樁接一樁出現,下一步該怎麼走呢?本文將探討近期的宏觀經濟事件,並分享個人的操作思考。
Thumbnail
As we navigate through 2024, the mobile app development landscape continues to evolve, driven by changing consumer behaviors...
Thumbnail
"You live for yourselves, not for humans." About trees and their feelings of sadness due to human interference.
Now I understand: there is no need for futile treatment or ineffective care, allowing our mother nature to take over may be the kindest approach for t
Thumbnail
  簡直像站在球場中看著真實的比賽讓人目不轉睛,呼吸為之屏息——傳說中灌籃高手動畫版的遺珠之憾:湘北對山王之戰終於出世。當年所有人期盼卻沒盼得的最重要的一場比賽,在生父手下脫胎而出,讓這部作品畫下奇蹟的句點。  
Thumbnail
《The Writer And Her Story》是香港漫畫家智海在1999年的作品,黑白色調的漫畫,描寫一個抑鬱的作者,被自己腦袋裡沉重的想法壓駝了背,寫下作品想為腦袋「減重」,卻被各種瑣碎問題所困,就連繪者也彷彿以上帝之手,延伸再延伸,給他沒有盡頭的樓梯和前路...
Thumbnail
在海上看美景,也不忘笑話別人的英語口音👉「It's gorgis, ain't it?」一起來領略一世紀前馬克•吐溫的不倒幽默!
Thumbnail
英文有一些慣用的句子,字面上怎麼讀都參不透,因為不知道背後隱含的思考邏輯。「給他懷疑的好處(give him the benefit of the doubt)」這種話在中文的邏輯中根本不成文也說不通,到底是在講什麼鬼?你只能用外國人的邏輯來想!
Thumbnail
《Queen’s Gambit》第一眼看會以為又是另一個關於天才兒童戰無不勝或者自甘墮落的故事。其實這一套劇集,講的是一個高敏感又內向的女生,如何在女權崛起之前的冷戰年代,以人生輸家之姿,晉身頂級棋手的故事,同時講述一個女孩子的前半生。
Thumbnail
「設計不僅僅是外觀和感覺。設計是其運作的方式。」 — Steve Jobs 身為一個獨立文案,許多人會以為我們的生活只需要面對電腦,從無到有,用精巧的文字填滿空白的螢幕,呈現心目中獨具風格的作品。 ——有的時候可以如此,但其實這是我們夢寐以求的偶發日常。 更多的時候,白天的工作時間總被各種繁雜
Thumbnail
台股、美股近期明顯回檔,市場敘事發生改變,壞消息一樁接一樁出現,下一步該怎麼走呢?本文將探討近期的宏觀經濟事件,並分享個人的操作思考。
Thumbnail
As we navigate through 2024, the mobile app development landscape continues to evolve, driven by changing consumer behaviors...
Thumbnail
"You live for yourselves, not for humans." About trees and their feelings of sadness due to human interference.
Now I understand: there is no need for futile treatment or ineffective care, allowing our mother nature to take over may be the kindest approach for t
Thumbnail
  簡直像站在球場中看著真實的比賽讓人目不轉睛,呼吸為之屏息——傳說中灌籃高手動畫版的遺珠之憾:湘北對山王之戰終於出世。當年所有人期盼卻沒盼得的最重要的一場比賽,在生父手下脫胎而出,讓這部作品畫下奇蹟的句點。  
Thumbnail
《The Writer And Her Story》是香港漫畫家智海在1999年的作品,黑白色調的漫畫,描寫一個抑鬱的作者,被自己腦袋裡沉重的想法壓駝了背,寫下作品想為腦袋「減重」,卻被各種瑣碎問題所困,就連繪者也彷彿以上帝之手,延伸再延伸,給他沒有盡頭的樓梯和前路...
Thumbnail
在海上看美景,也不忘笑話別人的英語口音👉「It's gorgis, ain't it?」一起來領略一世紀前馬克•吐溫的不倒幽默!
Thumbnail
英文有一些慣用的句子,字面上怎麼讀都參不透,因為不知道背後隱含的思考邏輯。「給他懷疑的好處(give him the benefit of the doubt)」這種話在中文的邏輯中根本不成文也說不通,到底是在講什麼鬼?你只能用外國人的邏輯來想!
Thumbnail
《Queen’s Gambit》第一眼看會以為又是另一個關於天才兒童戰無不勝或者自甘墮落的故事。其實這一套劇集,講的是一個高敏感又內向的女生,如何在女權崛起之前的冷戰年代,以人生輸家之姿,晉身頂級棋手的故事,同時講述一個女孩子的前半生。