The Nature of Code閱讀心得與Python實作:4.5 A System of Systems

更新於 2024/10/11閱讀時間約 12 分鐘

集合許多個別的粒子可以形成一個粒子系統,那集合許多粒子系統,是不是也能形成一個系統呢?

當然可以!

既然集合許多粒子系統可以形成一個系統,那集合許多由粒子系統形成的系統,可不可以又形成一個系統呢?

當然也可以!

接下來,我們會以同樣的思路來處理含有許多粒子系統的系統。

在上一節中,我們讓許多粒子形成一個發射器系統;在這一節中,我們會來處理由許多發射器所構成的系統。

在Example 4.3中,我們處理的是單一的粒子系統:畫面上就只有一個不斷冒出粒子的發射器粒子系統。程式的寫法,是把那個系統指定給一個變數emitter,然後不斷把新的粒子加進emitter中,並呼叫emitterrun()方法:

現在,如果我們希望一開始的時候畫面上沒有任何發射器粒子系統,然後每當按下滑鼠左鍵時,就會在滑鼠游標所在的地方放置一個發射器粒子系統,那程式要怎麼寫呢?在設計Emitter這個類別時,我們是把系統所含的粒子放在一個list中。現在的做法也一樣,就把粒子系統放在一個叫做emitterslist中來處理;當按下滑鼠左鍵時,就新增一個發射器粒子系統到list中,然後針對所有在list中的發射器粒子系統,逐一新增粒子,並呼叫run()方法。

Example 4.4: A System of Systems

# python version 3.10.9
import random
import sys

import pygame # version 2.3.0


pygame.init()

pygame.display.set_caption("Example 4.4: A System of Systems")

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)

# 一開始的時候,畫面上沒有任何粒子系統
emitters = []

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

screen.fill(WHITE)

# 當按下滑鼠左鍵時,就把粒子系統新增到list中
if pygame.mouse.get_pressed()[0]:
x, y = pygame.mouse.get_pos()
emitters.append(Emitter(x, y, 1))

# 針對所有在list中的粒子系統,逐一新增粒子,並呼叫run()方法
for emitter in emitters:
emitter.add_particle()
emitter.run()

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

Exercise 4.5

Emitter類別的__init__()加入紀錄粒子庫存數量的變數:

self.inventory = 100

修改add_particle()

def add_particle(self):
if self.inventory > 0:
self.particles.append(Particle(self.origin.x, self.origin.y, self.mass))
self.inventory -= 1

主程式如下:

# python version 3.10.9
import random
import sys

import pygame # version 2.3.0


pygame.init()

pygame.display.set_caption("Exercise 4.5")

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)

emitters = []

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

screen.fill(WHITE)

if pygame.mouse.get_pressed()[0]:
x, y = pygame.mouse.get_pos()
emitters.append(Emitter(x, y, 1))

for emitter in emitters:
emitter.add_particle()
emitter.run()

# 移除已經沒有粒子的粒子系統
emitters = list(filter(lambda emitter: bool(emitter.particles), emitters))

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

Exercise 4.6

一開始的時候,讓粒子系統的粒子聚在一起,形成一個大的團塊。這時候,僅在畫面上顯示粒子,而不更新其狀態,等偵測到滑鼠點擊團塊時,才開始更新粒子的狀態。

修改Emitter類別。

修改__init__()方法,讓粒子系統的粒子在一開始的時候,就在畫面上結成團塊,同時加入用來紀錄粒子系統狀態的變數,以便判斷粒子系統是否正碎裂四散。

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

# 一開始的粒子團塊
self.particles = [Particle(x+3*i, y+3*j, mass)
for i in range(10) for j in range(10)]

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

# 粒子系統是否正碎裂四散?
self.shattering = False

修改run()方法,加入判斷粒子系統是否正碎裂四散的功能

def run(self):
if not self.shattering:
for particle in self.particles:
particle.show()
else:
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()

新增check_click()方法,用來偵測滑鼠是否點擊粒子團塊。當滑鼠點擊任何團塊中的粒子時,即表示滑鼠正點擊該粒子團塊。

def check_click(self, x, y):
for particle in self.particles:
d = pygame.Vector2(x, y).distance_to(particle.position)
if d <= particle.radius:
self.shattering = True
break

主程式如下:

# python version 3.10.9
import random
import sys

import pygame # version 2.3.0


pygame.init()

pygame.display.set_caption("Exercise 4.6")

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)

emitters = [Emitter(100*i, 130, 1) for i in range(1, 6)]

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

screen.fill(WHITE)

for emitter in emitters:
if pygame.mouse.get_pressed()[0]:
x, y = pygame.mouse.get_pos()
emitter.check_click(x, y)

emitter.run()

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


avatar-img
15會員
130內容數
寫點東西自娛娛人
留言0
查看全部
avatar-img
發表第一個留言支持創作者!
ysf的沙龍 的其他內容
在這一節,我們要建立一個Emitter類別,讓我們能夠比較輕鬆地一次處理多個由許多粒子構成的系統。
有了描述個別粒子的Particle類別之後,這一節就來看看要怎麼做,才能同時掌握許多粒子的動向,特別是這些粒子的數量是隨時都在變動的。
在開始真正處理粒子系統之前,得先寫個用來描述單一粒子的類別。這個類別,就把它叫做Particle。
之所以要研究粒子系統,除了可以用來模擬許多自然界中的現象之外,另一個更重要的原因是:在我們的模擬世界中,會有許多物體存在,而這些物體可能會形成一群一群的群體
粒子系統(particle system)指的是,由許多微小粒子組成,呈現出模糊外觀的物體。這一章的重點會放在探討利用物件導向技術實作粒子系統時,該採用什麼樣的程式架構、描述個別粒子和整個系統的資料該如何管理等方面。
這一節要模擬的是擺(pendulum)這個裝置中,構造最簡單、具有理想化性質的單擺(simple pendulum)。
在這一節,我們要建立一個Emitter類別,讓我們能夠比較輕鬆地一次處理多個由許多粒子構成的系統。
有了描述個別粒子的Particle類別之後,這一節就來看看要怎麼做,才能同時掌握許多粒子的動向,特別是這些粒子的數量是隨時都在變動的。
在開始真正處理粒子系統之前,得先寫個用來描述單一粒子的類別。這個類別,就把它叫做Particle。
之所以要研究粒子系統,除了可以用來模擬許多自然界中的現象之外,另一個更重要的原因是:在我們的模擬世界中,會有許多物體存在,而這些物體可能會形成一群一群的群體
粒子系統(particle system)指的是,由許多微小粒子組成,呈現出模糊外觀的物體。這一章的重點會放在探討利用物件導向技術實作粒子系統時,該採用什麼樣的程式架構、描述個別粒子和整個系統的資料該如何管理等方面。
這一節要模擬的是擺(pendulum)這個裝置中,構造最簡單、具有理想化性質的單擺(simple pendulum)。
你可能也想看
Google News 追蹤
Thumbnail
*合作聲明與警語: 本文係由國泰世華銀行邀稿。 證券服務係由國泰世華銀行辦理共同行銷證券經紀開戶業務,定期定額(股)服務由國泰綜合證券提供。   剛出社會的時候,很常在各種 Podcast 或 YouTube 甚至是在朋友間聊天,都會聽到各種市場動態、理財話題,像是:聯準會降息或是近期哪些科
Thumbnail
這篇內容,將會講解什麼是陣列,以及與陣列相關的知識。包括陣列的簡介、陣列的資料限制、陣列的維度、一維陣列、二維陣列。
上兩篇有關List的文章,此篇文上兩章的延續,整理一些常用的方法和操作。 [Python]List(列表)新增、修改、刪除元素 [Python基礎]容器 list(列表),tuple(元組) 還有一些常用的 list 方法和操作,讓你能更靈活地處理列表數據
Thumbnail
在 Python 中,print( ) 函數用於將結果輸出到螢幕上。當你嘗試將不同資料型別(例如字串和數字)混合在一起輸出時,print( )函數無法直接處理這些不同型別的資料,因此你需要先將它們轉換為相同的資料型別。通常,這意味著需要將數字轉換為字串型別,以便與其他字串一同輸出。 雖然我們也可以
Thumbnail
打開 jupyter notebook 寫一段 python 程式,可以完成五花八門的工作,這是玩程式最簡便的方式,其中可以獲得很多快樂,在現今這種資訊發達的時代,幾乎沒有門檻,只要願意,人人可享用。 下一步,希望程式可以隨時待命聽我吩咐,不想每次都要開電腦,啟動開發環境,只為完成一個重複性高
在Python中, 要寫一個完整的「符元化類 Tokenizer Class」, 這個Class需要的功能有: 1.「編碼 Encode」:將「文本 Text」分割成「符元 Token」。 2.「詞彙 Vocabulary」:將「符元 Token」映射到「符元ID TokenID
Thumbnail
建構Anytype之前..... 1.清晰劃分工作區 2.選擇模板套用 3.改變外觀界面
Thumbnail
先前學到自定函式的使用方法,那如果在一個很龐大的程式架構中發散了一推自定函式,有沒有辦法可以整理一下,讓程式結構整齊又簡潔呢? 可以使用裝飾器staticmethod 定義靜態方法,全部整理到一個類別去,想像成是一個工具箱的概念,工具箱就是類別,靜態方法就像是裡面的工具一樣。
Thumbnail
題目敘述 題目會給我們一組定義好的界面和需求,要求我們設計一個資料結構,可以滿足平均O(1)的插入元素、刪除元素、隨機取得元素的操作。 RandomizedSet() 類別建構子 bool insert(int val) 插入元素的function界面 bool remove(int val
Thumbnail
本文讓我們來淺談一下類別是什麼? 若想看詳細一點的python官方教學可點此連結 Python 的類別(Class)是一種面向物件導向程式設計的概念,讓你能夠創建具有屬性和方法的物件。類別是對現實世界中事物的抽象,它包含數據和操作這些數據的方法。它非常的抽象,想像一個類別就像是一個蛋糕模具,
Thumbnail
關於多執行緒/多行程的使用方式 在Python 3.2版本之後加入了「concurrent.futures」啟動平行任務, 它可以更好的讓我們管理多執行緒/多行程的應用場景,讓我們在面對這種併發問題時可以不必害怕, 用一個非常簡單的方式就能夠處裡, 底下我們將為您展示一段程式碼: imp
Thumbnail
*合作聲明與警語: 本文係由國泰世華銀行邀稿。 證券服務係由國泰世華銀行辦理共同行銷證券經紀開戶業務,定期定額(股)服務由國泰綜合證券提供。   剛出社會的時候,很常在各種 Podcast 或 YouTube 甚至是在朋友間聊天,都會聽到各種市場動態、理財話題,像是:聯準會降息或是近期哪些科
Thumbnail
這篇內容,將會講解什麼是陣列,以及與陣列相關的知識。包括陣列的簡介、陣列的資料限制、陣列的維度、一維陣列、二維陣列。
上兩篇有關List的文章,此篇文上兩章的延續,整理一些常用的方法和操作。 [Python]List(列表)新增、修改、刪除元素 [Python基礎]容器 list(列表),tuple(元組) 還有一些常用的 list 方法和操作,讓你能更靈活地處理列表數據
Thumbnail
在 Python 中,print( ) 函數用於將結果輸出到螢幕上。當你嘗試將不同資料型別(例如字串和數字)混合在一起輸出時,print( )函數無法直接處理這些不同型別的資料,因此你需要先將它們轉換為相同的資料型別。通常,這意味著需要將數字轉換為字串型別,以便與其他字串一同輸出。 雖然我們也可以
Thumbnail
打開 jupyter notebook 寫一段 python 程式,可以完成五花八門的工作,這是玩程式最簡便的方式,其中可以獲得很多快樂,在現今這種資訊發達的時代,幾乎沒有門檻,只要願意,人人可享用。 下一步,希望程式可以隨時待命聽我吩咐,不想每次都要開電腦,啟動開發環境,只為完成一個重複性高
在Python中, 要寫一個完整的「符元化類 Tokenizer Class」, 這個Class需要的功能有: 1.「編碼 Encode」:將「文本 Text」分割成「符元 Token」。 2.「詞彙 Vocabulary」:將「符元 Token」映射到「符元ID TokenID
Thumbnail
建構Anytype之前..... 1.清晰劃分工作區 2.選擇模板套用 3.改變外觀界面
Thumbnail
先前學到自定函式的使用方法,那如果在一個很龐大的程式架構中發散了一推自定函式,有沒有辦法可以整理一下,讓程式結構整齊又簡潔呢? 可以使用裝飾器staticmethod 定義靜態方法,全部整理到一個類別去,想像成是一個工具箱的概念,工具箱就是類別,靜態方法就像是裡面的工具一樣。
Thumbnail
題目敘述 題目會給我們一組定義好的界面和需求,要求我們設計一個資料結構,可以滿足平均O(1)的插入元素、刪除元素、隨機取得元素的操作。 RandomizedSet() 類別建構子 bool insert(int val) 插入元素的function界面 bool remove(int val
Thumbnail
本文讓我們來淺談一下類別是什麼? 若想看詳細一點的python官方教學可點此連結 Python 的類別(Class)是一種面向物件導向程式設計的概念,讓你能夠創建具有屬性和方法的物件。類別是對現實世界中事物的抽象,它包含數據和操作這些數據的方法。它非常的抽象,想像一個類別就像是一個蛋糕模具,
Thumbnail
關於多執行緒/多行程的使用方式 在Python 3.2版本之後加入了「concurrent.futures」啟動平行任務, 它可以更好的讓我們管理多執行緒/多行程的應用場景,讓我們在面對這種併發問題時可以不必害怕, 用一個非常簡單的方式就能夠處裡, 底下我們將為您展示一段程式碼: imp