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)





15會員
112內容數
寫點東西自娛娛人
留言0
查看全部
發表第一個留言支持創作者!
ysf的沙龍 的其他內容
這一節談的是牛頓的三大運動定律,以及力對於物體運動狀態的影響。
這一章介紹的是力(force),以及力與加速度間的關係。
介紹以物件導向的方式,以向量來實作物體運動的模擬程式。
介紹如何在模擬物體運動時,引入加速度這個物理量。
這一節談的是牛頓的三大運動定律,以及力對於物體運動狀態的影響。
這一章介紹的是力(force),以及力與加速度間的關係。
介紹以物件導向的方式,以向量來實作物體運動的模擬程式。
介紹如何在模擬物體運動時,引入加速度這個物理量。
你可能也想看
Thumbnail
「設計不僅僅是外觀和感覺。設計是其運作的方式。」 — Steve Jobs 身為一個獨立文案,許多人會以為我們的生活只需要面對電腦,從無到有,用精巧的文字填滿空白的螢幕,呈現心目中獨具風格的作品。 ——有的時候可以如此,但其實這是我們夢寐以求的偶發日常。 更多的時候,白天的工作時間總被各種繁雜
Thumbnail
台股、美股近期明顯回檔,市場敘事發生改變,壞消息一樁接一樁出現,下一步該怎麼走呢?本文將探討近期的宏觀經濟事件,並分享個人的操作思考。
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
「設計不僅僅是外觀和感覺。設計是其運作的方式。」 — Steve Jobs 身為一個獨立文案,許多人會以為我們的生活只需要面對電腦,從無到有,用精巧的文字填滿空白的螢幕,呈現心目中獨具風格的作品。 ——有的時候可以如此,但其實這是我們夢寐以求的偶發日常。 更多的時候,白天的工作時間總被各種繁雜
Thumbnail
台股、美股近期明顯回檔,市場敘事發生改變,壞消息一樁接一樁出現,下一步該怎麼走呢?本文將探討近期的宏觀經濟事件,並分享個人的操作思考。
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》第一眼看會以為又是另一個關於天才兒童戰無不勝或者自甘墮落的故事。其實這一套劇集,講的是一個高敏感又內向的女生,如何在女權崛起之前的冷戰年代,以人生輸家之姿,晉身頂級棋手的故事,同時講述一個女孩子的前半生。