The Nature of Code閱讀心得與Python實作:4.7 Particle Systems with...

更新於 2024/10/18閱讀時間約 8 分鐘
這一節的標題是
4.7 Particle Systems with Forces
因為方格子標題字數限制,所以沒完整顯現

到目前為止,我們所設計的粒子系統,都只有受到重力的作用。那如果作用力是風力呢?又該怎麼設計?

原書在處理作用在粒子系統上的重力時,是在Particle類別中設計一個run()方法,並把重力的作用寫死在裡頭,像這樣:

def run(self):
gravity = pygame.Vector2(0, 0.05)
self.apply_force(gravity)

self.update()
self.show()

當粒子系統中的粒子呼叫這個方法時,就能把重力作用在粒子上。

這個寫法的主要缺點,就是太沒彈性了。如果現在作用力要改成風力,那就得去改run()裡頭的東西。除此之外,另一個缺點是,在主程式裡頭,是看不到重力存在的。

因為覺得原書的寫法不是很好,所以改成在主程式中設定gravity,然後在Emitter類別的run()方法中處理重力:

def run(self):
for particle in self.particles:
particle.apply_force(gravity)
particle.update()

# 移除壽命已到的粒子
self.particles = list(filter(lambda particle: not particle.is_dead(), self.particles))

for particle in self.particles:
particle.show()

這樣子gravity就會以全域變數的身份出現在run()這個方法中。這樣寫的好處是,可以清楚的在主程式中看到有個作用力存在,而且可以進行設定、調整。

雖然讓gravity以全域變數的身份出現在Emitter類別的run()方法中有些好處,但是也有些缺點;最大的缺點是,在主程式中可以看到有個作用力,但卻看不出這個作用力是作用在哪裡。另外,眾所周知,使用全域變數,始終就不是個好主意,除了程式比較雜亂難以閱讀之外,在除錯時也比較難以找到bug。

既然兩種寫法都不是那麼的好,那有沒有比較好的寫法呢?

這個問題沒有標準答案,不同的情境可能會有各自比較好的寫法。下面介紹的是原書提供的寫法,可以避免前面提到的那兩種寫法的一些問題,但要注意的是,並非在所有的情境下,都一定要這樣寫。

既然粒子系統的頭頭是Emitter這個類別,所有粒子都歸它管,那就幫它加個apply_force()方法,用來讓作用力作用在系統內的所有粒子上:

def apply_force(self, force):
for particle in self.particles:
particle.apply_force(force)

當在主程式中要讓作用力作用在粒子系統上時,只要呼叫這個方法就可以了:

gravity = pygame.Vector2(0, 0.05)
:
:
emitter.add_particle()
emitter.apply_force(gravity)
emitter.run()

當然,這時候run()方法裡頭對粒子施加重力的部分,也就是

particle.apply_force(gravity)

就必須拿掉。

Emitter類別處理作用力的部分改成這樣寫,不僅主程式清楚明瞭,而且寫起來彈性也比較大,下面這個例子就是採用這樣子的寫法。

Example 4.6: A Particle System with Force

因為Particle類別並沒有任何更動,所以就只列出Emitter類別和主程式。

class Emitter:
def __init__(self, x, y, mass):
self.mass = mass
self.size = 16*self.mass

self.particles = []

# 發射器位置
self.origin = pygame.Vector2(x, y)

def add_particle(self):
self.particles.append(Particle(self.origin.x, self.origin.y, self.mass))

def apply_force(self, force):
for particle in self.particles:
particle.apply_force(force)

def run(self):
for particle in self.particles:
particle.apply_force(gravity)
particle.update()

# 移除壽命已到的粒子
self.particles = list(filter(lambda particle: not particle.is_dead(), self.particles))

for particle in self.particles:
particle.show()


# python version 3.10.9
import random
import sys

import pygame # version 2.3.0


pygame.init()

pygame.display.set_caption("Example 4.6: A Particle System with Forces")

WHITE = (255, 255, 255)

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

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

gravity = pygame.Vector2(0, 0.05)

emitter = Emitter(320, 50, 1)

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

screen.fill(WHITE)

emitter.add_particle()
emitter.apply_force(gravity)
emitter.run()

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


avatar-img
15會員
130內容數
寫點東西自娛娛人
留言0
查看全部
avatar-img
發表第一個留言支持創作者!
ysf的沙龍 的其他內容
接下來,我們會藉由繼承(inheritance)和多型(polymorphism)這兩個物件導向程式設計的技術,來製作更多樣化、更有趣的粒子系統。
有了描述個別粒子的Particle類別之後,這一節就來看看要怎麼做,才能同時掌握許多粒子的動向,特別是這些粒子的數量是隨時都在變動的。
在開始真正處理粒子系統之前,得先寫個用來描述單一粒子的類別。這個類別,就把它叫做Particle。
之所以要研究粒子系統,除了可以用來模擬許多自然界中的現象之外,另一個更重要的原因是:在我們的模擬世界中,會有許多物體存在,而這些物體可能會形成一群一群的群體
粒子系統(particle system)指的是,由許多微小粒子組成,呈現出模糊外觀的物體。這一章的重點會放在探討利用物件導向技術實作粒子系統時,該採用什麼樣的程式架構、描述個別粒子和整個系統的資料該如何管理等方面。
接下來,我們會藉由繼承(inheritance)和多型(polymorphism)這兩個物件導向程式設計的技術,來製作更多樣化、更有趣的粒子系統。
有了描述個別粒子的Particle類別之後,這一節就來看看要怎麼做,才能同時掌握許多粒子的動向,特別是這些粒子的數量是隨時都在變動的。
在開始真正處理粒子系統之前,得先寫個用來描述單一粒子的類別。這個類別,就把它叫做Particle。
之所以要研究粒子系統,除了可以用來模擬許多自然界中的現象之外,另一個更重要的原因是:在我們的模擬世界中,會有許多物體存在,而這些物體可能會形成一群一群的群體
粒子系統(particle system)指的是,由許多微小粒子組成,呈現出模糊外觀的物體。這一章的重點會放在探討利用物件導向技術實作粒子系統時,該採用什麼樣的程式架構、描述個別粒子和整個系統的資料該如何管理等方面。
你可能也想看
Google News 追蹤
Thumbnail
*合作聲明與警語: 本文係由國泰世華銀行邀稿。 證券服務係由國泰世華銀行辦理共同行銷證券經紀開戶業務,定期定額(股)服務由國泰綜合證券提供。   剛出社會的時候,很常在各種 Podcast 或 YouTube 甚至是在朋友間聊天,都會聽到各種市場動態、理財話題,像是:聯準會降息或是近期哪些科
到目前為止,我們所模擬的萬有引力,是一個物體吸引另一個物體,或者是一個物體吸引多個物體。然而,在真實世界中,每個物體都會互相吸引,所以在這一節中,就來把模擬的情境,擴展成多個物體互相吸引。
Thumbnail
模擬世界是我們寫程式造出來的,我們就是模擬世界的主宰,所以各種作用力要長什麼樣子、要怎麼個作用法,都由我們決定。不過,如果希望這些作用力看起來像真實世界的作用力一樣,那在寫程式的時候,套用這些作用力在真實世界中的物理公式,會是比較省時省力的做法。
在真實世界中有各式各樣的作用力影響著我們,那在模擬世界中呢?要怎麼在本來無一物的模擬世界中,製造出作用力呢?
到目前為止,為了簡化問題,我們都假設物體的質量是1。接下來,我們將移除這個假設,然後將完全符合牛頓第二運動定律的apply_force()方法,整合到Mover這個類別中。
這一節談的是牛頓的三大運動定律,以及力對於物體運動狀態的影響。
介紹以物件導向的方式,以向量來實作物體運動的模擬程式。
介紹如何在模擬物體運動時,引入加速度這個物理量。
Thumbnail
這一節談的是向量的定義,以及如何運用向量來建立模擬物體運動時,關於位置和速度間的關係式。
這一章介紹向量(vector)這個在物理、工程等領域非常重要的數學工具,以及如何用它來模擬一些物理現象。
Thumbnail
*合作聲明與警語: 本文係由國泰世華銀行邀稿。 證券服務係由國泰世華銀行辦理共同行銷證券經紀開戶業務,定期定額(股)服務由國泰綜合證券提供。   剛出社會的時候,很常在各種 Podcast 或 YouTube 甚至是在朋友間聊天,都會聽到各種市場動態、理財話題,像是:聯準會降息或是近期哪些科
到目前為止,我們所模擬的萬有引力,是一個物體吸引另一個物體,或者是一個物體吸引多個物體。然而,在真實世界中,每個物體都會互相吸引,所以在這一節中,就來把模擬的情境,擴展成多個物體互相吸引。
Thumbnail
模擬世界是我們寫程式造出來的,我們就是模擬世界的主宰,所以各種作用力要長什麼樣子、要怎麼個作用法,都由我們決定。不過,如果希望這些作用力看起來像真實世界的作用力一樣,那在寫程式的時候,套用這些作用力在真實世界中的物理公式,會是比較省時省力的做法。
在真實世界中有各式各樣的作用力影響著我們,那在模擬世界中呢?要怎麼在本來無一物的模擬世界中,製造出作用力呢?
到目前為止,為了簡化問題,我們都假設物體的質量是1。接下來,我們將移除這個假設,然後將完全符合牛頓第二運動定律的apply_force()方法,整合到Mover這個類別中。
這一節談的是牛頓的三大運動定律,以及力對於物體運動狀態的影響。
介紹以物件導向的方式,以向量來實作物體運動的模擬程式。
介紹如何在模擬物體運動時,引入加速度這個物理量。
Thumbnail
這一節談的是向量的定義,以及如何運用向量來建立模擬物體運動時,關於位置和速度間的關係式。
這一章介紹向量(vector)這個在物理、工程等領域非常重要的數學工具,以及如何用它來模擬一些物理現象。