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

閱讀時間約 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)


15會員
128內容數
寫點東西自娛娛人
留言0
查看全部
發表第一個留言支持創作者!
ysf的沙龍 的其他內容
在這一節,我們要建立一個Emitter類別,讓我們能夠比較輕鬆地一次處理多個由許多粒子構成的系統。
有了描述個別粒子的Particle類別之後,這一節就來看看要怎麼做,才能同時掌握許多粒子的動向,特別是這些粒子的數量是隨時都在變動的。
在開始真正處理粒子系統之前,得先寫個用來描述單一粒子的類別。這個類別,就把它叫做Particle。
之所以要研究粒子系統,除了可以用來模擬許多自然界中的現象之外,另一個更重要的原因是:在我們的模擬世界中,會有許多物體存在,而這些物體可能會形成一群一群的群體
粒子系統(particle system)指的是,由許多微小粒子組成,呈現出模糊外觀的物體。這一章的重點會放在探討利用物件導向技術實作粒子系統時,該採用什麼樣的程式架構、描述個別粒子和整個系統的資料該如何管理等方面。
這一節要模擬的是擺(pendulum)這個裝置中,構造最簡單、具有理想化性質的單擺(simple pendulum)。
在這一節,我們要建立一個Emitter類別,讓我們能夠比較輕鬆地一次處理多個由許多粒子構成的系統。
有了描述個別粒子的Particle類別之後,這一節就來看看要怎麼做,才能同時掌握許多粒子的動向,特別是這些粒子的數量是隨時都在變動的。
在開始真正處理粒子系統之前,得先寫個用來描述單一粒子的類別。這個類別,就把它叫做Particle。
之所以要研究粒子系統,除了可以用來模擬許多自然界中的現象之外,另一個更重要的原因是:在我們的模擬世界中,會有許多物體存在,而這些物體可能會形成一群一群的群體
粒子系統(particle system)指的是,由許多微小粒子組成,呈現出模糊外觀的物體。這一章的重點會放在探討利用物件導向技術實作粒子系統時,該採用什麼樣的程式架構、描述個別粒子和整個系統的資料該如何管理等方面。
這一節要模擬的是擺(pendulum)這個裝置中,構造最簡單、具有理想化性質的單擺(simple pendulum)。
你可能也想看
Google News 追蹤
Thumbnail
這個秋,Chill 嗨嗨!穿搭美美去賞楓,裝備款款去露營⋯⋯你的秋天怎麼過?秋日 To Do List 等你分享! 秋季全站徵文,我們準備了五個創作主題,參賽還有機會獲得「火烤兩用鍋」,一起來看看如何參加吧~
Thumbnail
美國總統大選只剩下三天, 我們觀察一整週民調與金融市場的變化(包含賭局), 到本週五下午3:00前為止, 誰是美國總統幾乎大概可以猜到60-70%的機率, 本篇文章就是以大選結局為主軸來討論近期甚至到未來四年美股可能的改變
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
這個秋,Chill 嗨嗨!穿搭美美去賞楓,裝備款款去露營⋯⋯你的秋天怎麼過?秋日 To Do List 等你分享! 秋季全站徵文,我們準備了五個創作主題,參賽還有機會獲得「火烤兩用鍋」,一起來看看如何參加吧~
Thumbnail
美國總統大選只剩下三天, 我們觀察一整週民調與金融市場的變化(包含賭局), 到本週五下午3:00前為止, 誰是美國總統幾乎大概可以猜到60-70%的機率, 本篇文章就是以大選結局為主軸來討論近期甚至到未來四年美股可能的改變
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