The Nature of Code閱讀心得與Python實作:2.2 Force Accumulation

閱讀時間約 11 分鐘

這一節要來看看,有許多個力同時作用時,該怎麼處理。

如果想要讓windgravity這兩個力同時作用在mover上,程式可以這樣寫

mover.apply_force(wind+gravity)

這樣子的寫法,其實就是先算出合力,然後讓合力作用在mover上。

另一種處理合力的方法,是將apply_force()改寫為

def apply_force(self, force):
    self.acceleration += force

這樣當每次呼叫apply_force()時,新的作用力就會累加進去,而不是取代掉前面的作用力。所以,上一節程式的寫法

mover.apply_force(wind)
mover.apply_force(gravity)

就不會發生windgravity取代掉而沒有作用的情形,而可以達到讓windgravity同時作用在mover上的目的。

處理完合力的問題之後,還有個地方必須要處理,否則mover將會感受到永不停止的作用力。

假設當我們按下滑鼠左鍵時,會有一陣風吹向mover,而當放開滑鼠左鍵時,風就停止。寫成程式就是

if pygame.mouse.get_pressed()[0]:
    mover.apply_force(wind)

放開滑鼠左鍵後,因為已經沒有風了,所以沒有力量作用在mover上,它的加速度會是0,而根據牛頓第一運動定律,mover會維持等速運動。但是,當我們呼叫update()來計算mover的速度和位置時,因為update()的寫法是

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

這時候acceleration的值,還是維持著呼叫apply_force()時所得到的值;即便來自wind的作用力早就不存在了。這顯然不是我們所要的結果,我們要的是當合力為0時,acceleration的值是0。那程式該怎麼寫呢?其實挺簡單的,在update()的最後,讓acceleration的值歸零就可以了:

def update(self):
    self.velocity += self.acceleration
    self.position += self.velocity
    self.acceleration *= 0

這樣子,對於acceleration來說,每一幀畫面都是新的開始,不會留有從上一幀畫面而來的記憶,在現在這一幀畫面中有多大的作用力,mover的加速度就會有多大的值,完全符合牛頓運動定律。

在模擬時,有個東西很重要:時間步長(time step)。時間步長一般記做dt,指的是「delta time」、「時間的變化量」的意思,它的大小會影響模擬的準確度;這也就是為什麼許多物理引擎會把時間步長當成一個可以調整的參數,讓使用者可以調整其大小,來得到更好的模擬結果。

既然時間步長這麼重要,那它究竟是什麼東西,又為什麼會影響模擬的準確度呢?原書在這裡並沒有詳細解釋,而只用「the rate at which the simulation updates」這樣一句話來說明什麼是時間步長。單憑這句話就想搞清楚什麼是時間步長,實在是挺困難的。下面就試著用一個例子來解釋什麼是時間步長。透過這個例子,應該就能比較清楚的知道,原書那句關於時間步長的說明,到底是在說些什麼。

假設我們要模擬一顆被揮棒打擊出去的棒球的運動軌跡,因為我們是使用電腦進行模擬,而電腦每次只能針對某一個時間點,計算出當時棒球的各項運動數據。所以,整個模擬的過程,就是一個時間點接著一個時間點,計算出棒球的運動數據,直到模擬結束為止;而這一個一個時間點之間的間隔,就是時間步長。很明顯的,如果我們要模擬某段時間內棒球的運動軌跡,時間點之間的間隔,也就是時間步長,如果越小,那電腦必須計算並更新數據的時間點數量就會越多;反之,如果時間步長越大,電腦必須計算並更新數據的時間點數量就會越少。原書關於時間步長的那句話,說的其實就是這個。

知道了時間步長到底是什麼之後,接下來就來看看,它的大小會如何影響模擬的準確度。還是用棒球的運動軌跡那個例子來說明。假設我們想知道棒球在落地前飛了多久,那我們會看看,在哪個時間點棒球還在飛,而在下一個時間點則在地上滾,這樣就可以知道棒球至少飛了多少時間。例如,假設時間步長設定為1秒,而棒球在第5秒鐘時還在飛,但在第6秒鐘時則在地上滾,這時就可以知道,棒球的飛行時間介於5~6秒鐘之間。所以,時間步長設定為1秒,我們所得到的棒球飛行時間,誤差範圍會在1秒鐘內。同樣的道理,如果時間步長設定為0.1秒,那我們應該可以得到誤差範圍在0.1秒內的棒球飛行時間。這也就是說,時間步長越小,模擬的準確度會越高。

既然時間步長越小,模擬的準確度越高,那是不是不管三七二十一,就把時間步長設定得非常非常小就好了?這樣一來,不就不用擔心準確度不夠了嗎?理論上是如此啦!但是,你有那麼多時間、有那麼雄厚的資本嗎?時間步長從1秒改成0.1秒,需要計算的時間點數量會變成10倍。電腦模擬需要時間,計算量越大,需要的時間會越長;換台速度快一點的電腦可以縮短模擬的時間,但這也意味著要從口袋掏出更多的錢出來。

總之,時間步長不管太大或太小都有缺點,剛剛好就好。但是多大才是剛剛好呢?這沒有標準答案,只能視情況而定;不過為了能夠專注於瞭解在模擬時所用到的主要原理,一直到第六章介紹物理引擎之前,我們都會假設,主程式中跑完一次while迴圈,就相當於一個時間步長。

Exercise 2.1

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

# 氣球半徑
self.size = 16

# 物件的起始位置、初始速度、初始加速度
self.position = pygame.Vector2(self.width//2, self.height-self.size)
self.velocity = pygame.Vector2(0, 0)
self.acceleration = pygame.Vector2(0, 0)

def apply_force(self, force):
self.acceleration += force

def update(self):
self.velocity += self.acceleration
self.position += self.velocity
self.acceleration *= 0

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

def check_edges(self):
# 非彈性碰撞恢復係數。氣球撞壁後,依據此係數來降低移動速率
restitution = 0.5

if self.position.x > self.width:
self.position.x = self.width
self.velocity.x = -restitution*self.velocity.x
elif self.position.x < 0:
self.position.x = 0
self.velocity.x = -restitution*self.velocity.x

if self.position.y < 0:
self.position.y = 0
self.velocity.y = -restitution*self.velocity.y


# python version 3.10.9
import random
import sys

import noise # version 1.2.2
import pygame # version 2.3.0


pygame.init()

pygame.display.set_caption("Exercise 2.1")

WHITE = (255, 255, 255)

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

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

balloon = Balloon()

# 浮力
buoyancy = pygame.Vector2(0, -0.01)

# 最大風力強度
maximum_intensity = 0.03

# Perlin noise的參數起始值
xoff, yoff = 0, 10000

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

screen.fill(WHITE)

# 依循Perlin noise變化的風力
xoff, yoff = xoff+0.01, yoff+0.01
wind = maximum_intensity*pygame.Vector2(noise.pnoise1(xoff), noise.pnoise1(yoff))

balloon.apply_force(buoyancy)
balloon.apply_force(wind)

balloon.update()
balloon.check_edges()
balloon.show()

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





avatar-img
15會員
129內容數
寫點東西自娛娛人
留言0
查看全部
avatar-img
發表第一個留言支持創作者!
ysf的沙龍 的其他內容
這一節談的是牛頓的三大運動定律,以及力對於物體運動狀態的影響。
這一章介紹的是力(force),以及力與加速度間的關係。
介紹以物件導向的方式,以向量來實作物體運動的模擬程式。
介紹如何在模擬物體運動時,引入加速度這個物理量。
這一節談的是牛頓的三大運動定律,以及力對於物體運動狀態的影響。
這一章介紹的是力(force),以及力與加速度間的關係。
介紹以物件導向的方式,以向量來實作物體運動的模擬程式。
介紹如何在模擬物體運動時,引入加速度這個物理量。
你可能也想看
Google News 追蹤
Thumbnail
這個秋,Chill 嗨嗨!穿搭美美去賞楓,裝備款款去露營⋯⋯你的秋天怎麼過?秋日 To Do List 等你分享! 秋季全站徵文,我們準備了五個創作主題,參賽還有機會獲得「火烤兩用鍋」,一起來看看如何參加吧~
Thumbnail
11/20日NVDA即將公布最新一期的財報, 今天Sell Side的分析師, 開始調高目標價, 市場的股價也開始反應, 未來一週NVDA將重新回到美股市場的焦點, 今天我們要分析NVDA Sell Side怎麼看待這次NVDA的財報預測, 以及實際上Buy Side的倉位及操作, 從
Thumbnail
Hi 大家好,我是Ethan😊 相近大家都知道保濕是皮膚保養中最基本,也是最重要的一步。無論是在畫室裡長時間對著畫布,還是在旅途中面對各種氣候變化,保持皮膚的水分平衡對我來說至關重要。保濕化妝水不僅能迅速為皮膚補水,還能提升後續保養品的吸收效率。 曾經,我的保養程序簡單到只包括清潔和隨意上乳液
Nature is a profound source of inspiration and tranquility. From the vibrant colors of blooming flowers to the soothing sounds of flowing rivers, the
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
這個秋,Chill 嗨嗨!穿搭美美去賞楓,裝備款款去露營⋯⋯你的秋天怎麼過?秋日 To Do List 等你分享! 秋季全站徵文,我們準備了五個創作主題,參賽還有機會獲得「火烤兩用鍋」,一起來看看如何參加吧~
Thumbnail
11/20日NVDA即將公布最新一期的財報, 今天Sell Side的分析師, 開始調高目標價, 市場的股價也開始反應, 未來一週NVDA將重新回到美股市場的焦點, 今天我們要分析NVDA Sell Side怎麼看待這次NVDA的財報預測, 以及實際上Buy Side的倉位及操作, 從
Thumbnail
Hi 大家好,我是Ethan😊 相近大家都知道保濕是皮膚保養中最基本,也是最重要的一步。無論是在畫室裡長時間對著畫布,還是在旅途中面對各種氣候變化,保持皮膚的水分平衡對我來說至關重要。保濕化妝水不僅能迅速為皮膚補水,還能提升後續保養品的吸收效率。 曾經,我的保養程序簡單到只包括清潔和隨意上乳液
Nature is a profound source of inspiration and tranquility. From the vibrant colors of blooming flowers to the soothing sounds of flowing rivers, the
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》第一眼看會以為又是另一個關於天才兒童戰無不勝或者自甘墮落的故事。其實這一套劇集,講的是一個高敏感又內向的女生,如何在女權崛起之前的冷戰年代,以人生輸家之姿,晉身頂級棋手的故事,同時講述一個女孩子的前半生。