The Nature of Code閱讀心得與Python實作:3.8 Waves

閱讀時間約 1 分鐘

如果在x軸上依序取一些點,然後算出在這些點上對應的sin函數的值,那麼,當我們把這些由x軸上的點以及其對應的sin函數的值所構成的二維座標點畫出來時,就可以看到由這個sin函數所產生的像波一樣的圖案,也就是波型(wave pattern)。不同樣式的波型,可以用來設計生物的軀幹或肢體,也可以用來模擬像水這類柔軟的表面。

在計算波型時,我們需要設定三個變數:

angle = 0
delta_angle = 0.2
amplitude = 25

接著利用for迴圈,把所有要畫的點的座標位置算出來,然後畫上去。例如,在x軸上每隔24個像素取點,程式可以這樣寫:

for x in range(0, WIDTH, 24):
y = amplitude*math.sin(angle) + HEIGHT//2
pygame.draw.circle(screen, (0, 0, 0), (x, y), 12, 1)

angle += delta_angle

這裡的WIDTHHEIGHT,分別是畫面的寬度和高度。另外,從這段程式的最後一行也可以看出來,delta_angle的角色,其實就類似於角速度的角色。

下面這個例子,就是用上述的方式來畫出波型的。

Example 3.8: Static Wave

raw-image
# python version 3.10.9
import math
import sys

import pygame # version 2.3.0


pygame.init()

pygame.display.set_caption("Example 3.8: Static Wave")

BLACK = (0, 0, 0)
WHITE = (255, 255, 255)

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

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

delta_angle = 0.2
amplitude = 100

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

screen.fill(WHITE)

angle = 0
for x in range(0, WIDTH, 24):
y = amplitude*math.sin(angle) + HEIGHT//2
pygame.draw.circle(screen, BLACK, (x, y), 24, 1)

angle += delta_angle

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

不同的delta_angle值對波型有什麼影響呢?下面這張圖,就是使用不同的delta_angle值所畫出來的波型。

raw-image

在描述波的時候,週期是指波運動一個完整的循環所需的時間;而「波長」(wavelength),則是指波運動一個完整的循環所行經的距離。從這張圖可以看出來,delta_angle值越大,則所得到的波長會越短。

從圖中還可以觀察到一個現象,當波長越短時,因為圖形的變化越大,所以相鄰兩個圓圈越難以緊密地連接在一起,嚴重時,會讓圖形看起來像是中間斷掉一樣。要避免這樣子的問題,可以多取一些點,讓圓圈圈更密集一些;但是這種做法,很明顯的會增加很多計算量,電腦速度不夠快的話,在模擬時,很可能會出現畫面卡頓的現象。另一種比較好的做法,是把相鄰的兩個點用直線連接起來。這樣子做,額外增加的計算量會少很多,而且在pygame中,也提供了draw.lines()這個函數來做這件事,不需要自己寫。

上面的寫法所畫出來的圖是靜態的,也就是說,那個波完全不會動。那要怎麼讓它動呢?

要讓畫出來的波會動,做法其實挺簡單的。先前畫出來的波之所以不會動,是因為我們每次都從同樣的地方開始畫起。所以,每一幀畫面顯示出來的,都會是一模一樣的波,不僅形狀一樣,連位置都一樣,這樣子當然就看不到波動的效果。所以,要讓波動起來,關鍵就在每一次畫的時候,起始點都給它稍微變動一下,從不同的位置開始畫。要這麼做,可以設定一個值會慢慢增加的變數start_angle,然後把原本的

angle = 0

改成

angle += start_angle

因為start_angle的值會慢慢增加,所以每次畫的時候,就會從不同的起始點開始畫。值得一提的是,start_angle改變的速度,會影響波動的速度,start_angle改變的速度越快,波動的速度也會越快。因此,我們可以藉由調整start_angle改變的速度,來調控波動的速度。

Example 3.9: The Wave

# python version 3.10.9
import math
import sys

import pygame # version 2.3.0


pygame.init()

pygame.display.set_caption("Example 3.9: The Wave")

BLACK = (0, 0, 0)
WHITE = (255, 255, 255)

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

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

start_angle = 0
delta_angle = 0.23
amplitude = HEIGHT//2

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

screen.fill(WHITE)

angle = start_angle
for x in range(0, WIDTH, 24):
y = amplitude*math.sin(angle) + HEIGHT//2
pygame.draw.circle(screen, BLACK, (x, y), 24, 1)

angle += delta_angle

start_angle += 0.02

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

Exercise 3.10

# python version 3.10.9
import math
import sys

import noise # version 1.2.2
import pygame # version 2.3.0


pygame.init()

pygame.display.set_caption("Exercise 3.10")

BLACK = (0, 0, 0)
WHITE = (255, 255, 255)

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

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

start_angle = 0
delta_angle = 0.03
amplitude = HEIGHT//2

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

screen.fill(WHITE)

angle = start_angle
for x in range(0, WIDTH, 24):
y = amplitude*noise.pnoise1(angle) + HEIGHT//2
pygame.draw.circle(screen, BLACK, (x, y), 24, 1)

angle += delta_angle

start_angle += 0.02

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

Exercise 3.11

raw-image
class Wave:
def __init__(self, amplitude, delta_angle, wave_width, position):
# 取得顯示畫面
self.screen = pygame.display.get_surface()

self.amplitude = amplitude
self.delta_angle = delta_angle
self.wave_width = wave_width
self.position = position
self.start_angle = 0
self.body = []

def generate(self):
self.body = []
angle = self.start_angle
for x in range(0, self.wave_width, 6):
y = self.amplitude*math.sin(angle)
self.body.append((x+self.position[0], y+self.position[1]))

angle += self.delta_angle

self.start_angle += 0.02

def show(self):
x, y = self.position
x += self.wave_width//2
y -= 100
for i in range(len(self.body)):
pygame.draw.line(self.screen, (0, 0, 0), (x, y), self.body[i], 1)


# python version 3.10.9
import math
import sys

import pygame # version 2.3.0


pygame.init()

pygame.display.set_caption("Exercise 3.11")

WHITE = (255, 255, 255)

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

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

delta_angle = 0.08
amplitude = 20
position = (75, 200)
wave_width = 100
wave1 = Wave(amplitude, delta_angle, wave_width, position)

delta_angle = 0.3
amplitude = 40
position = (275, 200)
wave_width = 300
wave2 = Wave(amplitude, delta_angle, wave_width, position)

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

screen.fill(WHITE)

wave1.generate()
wave1.show()

wave2.generate()
wave2.show()

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

Exercise 3.12

raw-image
# python version 3.10.9
import math
import sys

import pygame # version 2.3.0


pygame.init()

pygame.display.set_caption("Exercise 3.12")

BLACK = (0, 0, 0)
WHITE = (255, 255, 255)

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

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

start_angle = 0
delta_angle = 0.2

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

screen.fill(WHITE)

angle = start_angle
for x in range(0, WIDTH, 8):
y = 50*math.cos(angle) + 35*math.sin(1.5*angle) + HEIGHT//2
pygame.draw.circle(screen, BLACK, (x, y), 24, 1)

angle += delta_angle

start_angle += 0.02

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


15會員
128內容數
寫點東西自娛娛人
留言0
查看全部
發表第一個留言支持創作者!
ysf的沙龍 的其他內容
藉由設定振幅、頻率、週期等性質,我們可以模擬出真實世界中的振盪現象。其實,用稍微簡單一點的方式來處理,依舊可以得到相同的效果。
這一節談的是振盪(oscillation)。日常生活中,隨處都可見到振盪的現象。例如,彈奏弦樂器時,弦的振動、盪鞦韆時的來回擺動、音叉的振動、單擺的來回擺動、彈簧的振動等。除了這些眼睛看得到的之外,麥克風、交流電、收音機、手機等許許多多的電子產品,也都是利用振盪的原理來運作的。
除了直角座標系統外,極座標(polar coordinate)系統是另一種相當有用的座標系統。
在模擬運動中的物體時,如果物體是圓形,那就不需要考慮旋轉的問題,畢竟不管怎麼轉,圓還是圓,看起來都一樣。但是,如果物體不是圓形而是其他形狀呢?
這一節主要在談三角函數和向量的分量、角度間的關聯性。這個關聯性在向量的應用上,非常重要。
角運動(angular motion)指的是物體的旋轉運動。物體進行直線運動時,可以用速度和加速度來描述它的運動。同樣的做法也可以運用在描述角運動上,我們可以用角速度(angular velocity)和角加速度(angular acceleration)來描述角運動。
藉由設定振幅、頻率、週期等性質,我們可以模擬出真實世界中的振盪現象。其實,用稍微簡單一點的方式來處理,依舊可以得到相同的效果。
這一節談的是振盪(oscillation)。日常生活中,隨處都可見到振盪的現象。例如,彈奏弦樂器時,弦的振動、盪鞦韆時的來回擺動、音叉的振動、單擺的來回擺動、彈簧的振動等。除了這些眼睛看得到的之外,麥克風、交流電、收音機、手機等許許多多的電子產品,也都是利用振盪的原理來運作的。
除了直角座標系統外,極座標(polar coordinate)系統是另一種相當有用的座標系統。
在模擬運動中的物體時,如果物體是圓形,那就不需要考慮旋轉的問題,畢竟不管怎麼轉,圓還是圓,看起來都一樣。但是,如果物體不是圓形而是其他形狀呢?
這一節主要在談三角函數和向量的分量、角度間的關聯性。這個關聯性在向量的應用上,非常重要。
角運動(angular motion)指的是物體的旋轉運動。物體進行直線運動時,可以用速度和加速度來描述它的運動。同樣的做法也可以運用在描述角運動上,我們可以用角速度(angular velocity)和角加速度(angular acceleration)來描述角運動。
你可能也想看
Google News 追蹤
Thumbnail
這個秋,Chill 嗨嗨!穿搭美美去賞楓,裝備款款去露營⋯⋯你的秋天怎麼過?秋日 To Do List 等你分享! 秋季全站徵文,我們準備了五個創作主題,參賽還有機會獲得「火烤兩用鍋」,一起來看看如何參加吧~
到目前為止,我們所模擬的萬有引力,是一個物體吸引另一個物體,或者是一個物體吸引多個物體。然而,在真實世界中,每個物體都會互相吸引,所以在這一節中,就來把模擬的情境,擴展成多個物體互相吸引。
Thumbnail
模擬世界是我們寫程式造出來的,我們就是模擬世界的主宰,所以各種作用力要長什麼樣子、要怎麼個作用法,都由我們決定。不過,如果希望這些作用力看起來像真實世界的作用力一樣,那在寫程式的時候,套用這些作用力在真實世界中的物理公式,會是比較省時省力的做法。
介紹以物件導向的方式,以向量來實作物體運動的模擬程式。
Thumbnail
1.0 從函數到函算語法 1.2 函數概念小史 1.2.1 中譯的來源 1.2.2 一個速度問題 1.2.3 幾何的方法 1.2.4 微積分的記法 1.2.5 弦的振動 1.2.6 熱的傳導 1.2.7 十九世紀的尾聲 三 必須說一下波希米亞數學家/邏輯學家/哲學家/神學
Thumbnail
這一節談的是向量的定義,以及如何運用向量來建立模擬物體運動時,關於位置和速度間的關係式。
Thumbnail
1.0 從函數到函算語法 1.2 函數概念小史 1.2.1 中譯的來源 1.2.2 一個速度問題 1.2.3 幾何的方法 1.2.4 微積分的記法 1.2.5弦的振動 1.2.6熱的傳導 二 傅立葉認為他的結果對任一函數皆有效,並將函數定義為 (FF) 在一般情況下,函數
Thumbnail
1.0 從函數到函算語法 1.2 函數概念小史 1.2.1 中譯的來源 1.2.2 一個速度問題 1.2.3 幾何的方法 1.2.4 微積分的記法 1.2.5弦的振動 八 在關於振動弦通解的這場論爭之中,函數概念默默地向兩個方面推前了一大步。 一方面,特朗貝爾和歐拉等擴大了
這一章介紹向量(vector)這個在物理、工程等領域非常重要的數學工具,以及如何用它來模擬一些物理現象。
Thumbnail
這個秋,Chill 嗨嗨!穿搭美美去賞楓,裝備款款去露營⋯⋯你的秋天怎麼過?秋日 To Do List 等你分享! 秋季全站徵文,我們準備了五個創作主題,參賽還有機會獲得「火烤兩用鍋」,一起來看看如何參加吧~
到目前為止,我們所模擬的萬有引力,是一個物體吸引另一個物體,或者是一個物體吸引多個物體。然而,在真實世界中,每個物體都會互相吸引,所以在這一節中,就來把模擬的情境,擴展成多個物體互相吸引。
Thumbnail
模擬世界是我們寫程式造出來的,我們就是模擬世界的主宰,所以各種作用力要長什麼樣子、要怎麼個作用法,都由我們決定。不過,如果希望這些作用力看起來像真實世界的作用力一樣,那在寫程式的時候,套用這些作用力在真實世界中的物理公式,會是比較省時省力的做法。
介紹以物件導向的方式,以向量來實作物體運動的模擬程式。
Thumbnail
1.0 從函數到函算語法 1.2 函數概念小史 1.2.1 中譯的來源 1.2.2 一個速度問題 1.2.3 幾何的方法 1.2.4 微積分的記法 1.2.5 弦的振動 1.2.6 熱的傳導 1.2.7 十九世紀的尾聲 三 必須說一下波希米亞數學家/邏輯學家/哲學家/神學
Thumbnail
這一節談的是向量的定義,以及如何運用向量來建立模擬物體運動時,關於位置和速度間的關係式。
Thumbnail
1.0 從函數到函算語法 1.2 函數概念小史 1.2.1 中譯的來源 1.2.2 一個速度問題 1.2.3 幾何的方法 1.2.4 微積分的記法 1.2.5弦的振動 1.2.6熱的傳導 二 傅立葉認為他的結果對任一函數皆有效,並將函數定義為 (FF) 在一般情況下,函數
Thumbnail
1.0 從函數到函算語法 1.2 函數概念小史 1.2.1 中譯的來源 1.2.2 一個速度問題 1.2.3 幾何的方法 1.2.4 微積分的記法 1.2.5弦的振動 八 在關於振動弦通解的這場論爭之中,函數概念默默地向兩個方面推前了一大步。 一方面,特朗貝爾和歐拉等擴大了
這一章介紹向量(vector)這個在物理、工程等領域非常重要的數學工具,以及如何用它來模擬一些物理現象。