The Nature of Code閱讀心得與Python實作:3.7 Oscillation with...

更新於 發佈於 閱讀時間約 1 分鐘
這一節的標題是
3.7 Oscillation with Angular Velocity
因為方格子標題字數限制,所以沒完整顯現

在上一節,藉由設定振幅、頻率、週期等性質,我們可以模擬出真實世界中的振盪現象。在這一節,我們會用稍微簡單一點的方式來處理,但依舊可以得到相同的效果。

在上一節,我們在處理振盪時,使用的式子是

x = amplitude*math.sin(2*math.pi*frame_count/period)

現在把它改寫成

x = amplitude*math.sin(某個慢慢增加的數值)

也就是說,我們不再乖乖的去算sin裡頭的那一串東西,而是直接把某個數字當成那一串東西算出來的結果。畢竟現在我們要的是最後的結果,而不是多大的週期和幀數可以得到這樣的結果。

結合第二節角速度的觀念,就可以用比較簡單的方式,來改寫上一節的例子。假設

angle = 0
angular_velocity = 0.05

把那個處理振盪的式子改寫成

angle += angular_velocity
x = amplitude*math.sin(angle)

這裡的angle,就是那個慢慢增加的數值,而這也意味著,其中隱含了下面的關係式:

angle = 2*math.pi*frame_count/period

因為在每一幀畫面中,angle的值都會加上angular_velocity的值,所以更進一步拆解後可以發現

angular_velocity = 2*math.pi/period

移項之後得到

period = 2*math.pi/angular_velocity

這也就是說,採用這樣子的處理方式時,雖然程式中並沒有看到週期這個變數,但這並不表示週期這個變數已經被捨棄掉了,它只是在角速度的掩護下隱藏起來而已。

改寫後的程式如下:

Example 3.6: Simple Harmonic Motion II

# python version 3.10.9
import math
import sys

import pygame # version 2.3.0


pygame.init()

pygame.display.set_caption("Example 3.6: Simple Harmonic Motion II")

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

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

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

amplitude = 100

angle = 0
angular_velocity = 0.05

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

screen.fill(WHITE)

# 球的位置
x = amplitude*math.sin(angle)
position = (x+WIDTH//2, HEIGHT//2)

pygame.draw.circle(screen, BLACK, position, 20)
pygame.draw.line(screen, BLACK, position, screen_center, 3)

angle += angular_velocity

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

接下來,把這個例子再進一步推廣,並造出名為Oscillator的類別,然後讓振盪同時沿著x軸和y軸進行。要達到這樣子的目的,會需要分別設定x軸和y軸上的振幅、角速度,還有那個慢慢增加的數值;這些用向量來處理,會方便很多。

Example 3.7: Oscillator Objects

class Oscillator:
def __init__(self):
# 取得顯示畫面的大小
self.screen = pygame.display.get_surface()
self.width, self.height = self.screen.get_size()

# 樞軸,拴住oscillator的地方
self.pivot = pygame.Vector2(self.width//2, self.height//2)

self.angle = pygame.Vector2(0, 0)
self.angular_velocity = pygame.Vector2(random.uniform(-0.05, 0.05), random.uniform(-0.05, 0.05))
self.amplitude = pygame.Vector2(random.randint(0, self.width//2), random.randint(0, self.height//2))

# 設定oscillator所在surface的格式為per-pixel alpha
self.surface = pygame.Surface((self.width, self.height), pygame.SRCALPHA)

def oscillate(self):
self.angle += self.angular_velocity

def show(self):
# 使用具透明度的白色把oscillator所在的surface清空
self.surface.fill((255, 255, 255, 0))

# oscillator的位置
x = self.amplitude.x*math.sin(self.angle.x)
y = self.amplitude.y*math.sin(self.angle.y)
position = pygame.Vector2(x, y) + self.pivot

# 畫出具有透明度的oscillator
color = (0, 0, 0, 100)
pygame.draw.circle(self.surface, color, position, 20)
pygame.draw.line(self.surface, color, position, self.pivot, 3)

# 把oscillator所在的surface貼到最後要顯示的畫面上
self.screen.blit(self.surface, (0, 0))


# python version 3.10.9
import math
import random
import sys

import pygame # version 2.3.0


pygame.init()

pygame.display.set_caption("Example 3.7: Oscillator Objects")

WHITE = (255, 255, 255)

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

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

oscillators = [Oscillator() for i in range(10)]

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

screen.fill(WHITE)

for oscillator in oscillators:
oscillator.oscillate()
oscillator.show()

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

Exercise 3.8

raw-image
class Oscillator:
def __init__(self, joint, leg, angular_velocity, amplitude):
# 取得顯示畫面的大小
self.screen = pygame.display.get_surface()
self.width, self.height = self.screen.get_size()

# 關節位置
self.joint = joint

# 腿長
self.leg = leg

self.angle = 0
self.angular_velocity = angular_velocity
self.amplitude = amplitude

# 設定oscillator所在surface的格式為per-pixel alpha
self.surface = pygame.Surface((self.width, self.height), pygame.SRCALPHA)

def oscillate(self):
self.angle += self.angular_velocity

def show(self):
self.surface.fill((255, 255, 255, 0))

# 腳尖位置
x = self.leg
y = self.amplitude*math.sin(self.angle)
position = pygame.Vector2(x, y) + self.joint

color = (0, 0, 0, 100)
pygame.draw.circle(self.surface, color, position, 5)
pygame.draw.line(self.surface, color, position, self.joint, 3)

# 把oscillator所在的surface貼到最後要顯示的畫面上
self.screen.blit(self.surface, (0, 0))


# python version 3.10.9
import math
import sys

import pygame # version 2.3.0


pygame.init()

pygame.display.set_caption("Exercise 3.8")

WHITE = (255, 255, 255)

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

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

oscillators = []

# 腿長,負號代表左腳,正號代表右腳
legs = [-50, 50]

for leg in legs:
for i in range(10):
joint = pygame.Vector2(320+leg/50, 100+20*i)
angular_velocity = 0.08
amplitude = 10
oscillators.append(Oscillator(joint, leg, angular_velocity, amplitude))

# 讓各oscillator的初始位置不一樣,這樣腳的動作才不會過於整齊劃一,像是在划龍舟一樣
for i in range(20):
oscillators[i].angle = 0.2*i*math.pi

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

screen.fill(WHITE)

for oscillator in oscillators:
oscillator.oscillate()
oscillator.show()

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

Exercise 3.9

class Oscillator:
def __init__(self):
# 取得顯示畫面的大小
self.screen = pygame.display.get_surface()
self.width, self.height = self.screen.get_size()

# 樞軸,拴住oscillator的地方
self.pivot = pygame.Vector2(self.width//2, self.height//2)

# 最高速限
self.top_speed = 0.1

self.angle = pygame.Vector2(0, 0)
self.angular_acceleration = 1.e-4*pygame.Vector2(random.uniform(-1, 1), random.uniform(-1, 1))
self.angular_velocity = pygame.Vector2(0, 0)
self.amplitude = pygame.Vector2(random.randint(0, self.width//2), random.randint(0, self.height//2))

self.surface = pygame.Surface((self.width, self.height), pygame.SRCALPHA)

def oscillate(self):
self.angular_velocity += self.angular_acceleration

# 限速
if self.angular_velocity.magnitude() > self.top_speed:
self.angular_velocity.scale_to_length(self.top_speed)

self.angle += self.angular_velocity

def show(self):
# 使用具透明度的白色把oscillator所在的surface清空
self.surface.fill((255, 255, 255, 0))

# oscillator的位置
x = self.amplitude.x*math.sin(self.angle.x)
y = self.amplitude.y*math.sin(self.angle.y)
position = pygame.Vector2(x, y) + self.pivot

# 畫出具有透明度的oscillator
color = (0, 0, 0, 100)
pygame.draw.circle(self.surface, color, position, 20)
pygame.draw.line(self.surface, color, position, self.pivot, 3)

# 把oscillator所在的surface貼到最後要顯示的畫面上
self.screen.blit(self.surface, (0, 0))


# python version 3.10.9
import math
import random
import sys

import pygame # version 2.3.0


pygame.init()

pygame.display.set_caption("Exercise 3.9")

WHITE = (255, 255, 255)

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

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

oscillators = [Oscillator() for i in range(10)]

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

screen.fill(WHITE)

for oscillator in oscillators:
oscillator.oscillate()
oscillator.show()

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


留言
avatar-img
留言分享你的想法!
avatar-img
ysf的沙龍
16會員
144內容數
寫點東西自娛娛人
ysf的沙龍的其他內容
2024/09/20
這一節要模擬的是擺(pendulum)這個裝置中,構造最簡單、具有理想化性質的單擺(simple pendulum)。
Thumbnail
2024/09/20
這一節要模擬的是擺(pendulum)這個裝置中,構造最簡單、具有理想化性質的單擺(simple pendulum)。
Thumbnail
2024/09/16
我們曾經利用sin函數來模擬彈簧吊錘(bob)的運動,雖然這樣子的做法程式很容易寫,但是卻沒辦法模擬彈簧吊錘受到如風力、重力等環境中其他作用力的影響下,在空間中的運動狀況。要克服這樣子的問題,就不能再倚靠sin函數,而必須改用能夠用來計算彈簧彈力的虎克定律(Hooke's law)。
Thumbnail
2024/09/16
我們曾經利用sin函數來模擬彈簧吊錘(bob)的運動,雖然這樣子的做法程式很容易寫,但是卻沒辦法模擬彈簧吊錘受到如風力、重力等環境中其他作用力的影響下,在空間中的運動狀況。要克服這樣子的問題,就不能再倚靠sin函數,而必須改用能夠用來計算彈簧彈力的虎克定律(Hooke's law)。
Thumbnail
2024/09/13
在x軸上依序取一些點,然後把這些點以及其對應的sin函數的值所構成的二維座標點畫出來時,就可以看到由這個sin函數所產生的像波一樣的圖案,也就是波型(wave pattern)。不同樣式的波型,可以用來設計生物的軀幹或肢體,也可以用來模擬像水這類柔軟的表面。
Thumbnail
2024/09/13
在x軸上依序取一些點,然後把這些點以及其對應的sin函數的值所構成的二維座標點畫出來時,就可以看到由這個sin函數所產生的像波一樣的圖案,也就是波型(wave pattern)。不同樣式的波型,可以用來設計生物的軀幹或肢體,也可以用來模擬像水這類柔軟的表面。
Thumbnail
看更多
你可能也想看
Thumbnail
TOMICA第一波推出吉伊卡哇聯名小車車的時候馬上就被搶購一空,一直很扼腕當時沒有趕緊入手。前陣子閒來無事逛蝦皮,突然發現幾家商場都又開始重新上架,價格也都回到正常水準,估計是官方又再補了一批貨,想都沒想就立刻下單! 同文也跟大家分享近期蝦皮購物紀錄、好用推薦、蝦皮分潤計畫的聯盟行銷!
Thumbnail
TOMICA第一波推出吉伊卡哇聯名小車車的時候馬上就被搶購一空,一直很扼腕當時沒有趕緊入手。前陣子閒來無事逛蝦皮,突然發現幾家商場都又開始重新上架,價格也都回到正常水準,估計是官方又再補了一批貨,想都沒想就立刻下單! 同文也跟大家分享近期蝦皮購物紀錄、好用推薦、蝦皮分潤計畫的聯盟行銷!
Thumbnail
每年4月、5月都是最多稅要繳的月份,當然大部份的人都是有機會繳到「綜合所得稅」,只是相當相當多人還不知道,原來繳給政府的稅!可以透過一些有活動的銀行信用卡或電子支付來繳,從繳費中賺一點點小確幸!就是賺個1%~2%大家也是很開心的,因為你們把沒回饋變成有回饋,就是用卡的最高境界 所得稅線上申報
Thumbnail
每年4月、5月都是最多稅要繳的月份,當然大部份的人都是有機會繳到「綜合所得稅」,只是相當相當多人還不知道,原來繳給政府的稅!可以透過一些有活動的銀行信用卡或電子支付來繳,從繳費中賺一點點小確幸!就是賺個1%~2%大家也是很開心的,因為你們把沒回饋變成有回饋,就是用卡的最高境界 所得稅線上申報
Thumbnail
模擬世界是我們寫程式造出來的,我們就是模擬世界的主宰,所以各種作用力要長什麼樣子、要怎麼個作用法,都由我們決定。不過,如果希望這些作用力看起來像真實世界的作用力一樣,那在寫程式的時候,套用這些作用力在真實世界中的物理公式,會是比較省時省力的做法。
Thumbnail
模擬世界是我們寫程式造出來的,我們就是模擬世界的主宰,所以各種作用力要長什麼樣子、要怎麼個作用法,都由我們決定。不過,如果希望這些作用力看起來像真實世界的作用力一樣,那在寫程式的時候,套用這些作用力在真實世界中的物理公式,會是比較省時省力的做法。
Thumbnail
在物理的領域裏 不變的物質有著恆常的定律 於是乎 月球繞著地球轉 地球繞著太陽轉 太陽繞著銀河系   在化學的領域裏 物質隨著原子們的排列組合 形成了 形色多變銀河系 各有千秋太陽系 繽紛美麗的地球   在數學的領域裏 數字的跳躍翻轉變化萬千中 綜言是 正負平方開根
Thumbnail
在物理的領域裏 不變的物質有著恆常的定律 於是乎 月球繞著地球轉 地球繞著太陽轉 太陽繞著銀河系   在化學的領域裏 物質隨著原子們的排列組合 形成了 形色多變銀河系 各有千秋太陽系 繽紛美麗的地球   在數學的領域裏 數字的跳躍翻轉變化萬千中 綜言是 正負平方開根
Thumbnail
這一節談的是向量的定義,以及如何運用向量來建立模擬物體運動時,關於位置和速度間的關係式。
Thumbnail
這一節談的是向量的定義,以及如何運用向量來建立模擬物體運動時,關於位置和速度間的關係式。
Thumbnail
1.0 從函數到函算語法 1.2 函數概念小史 1.2.1 中譯的來源 1.2.2 一個速度問題 1.2.3 幾何的方法 1.2.4 微積分的記法 1.2.5 弦的振動 三 1755年,歐拉改變了主意,在《微分學原理》(Institutiones calculi differen
Thumbnail
1.0 從函數到函算語法 1.2 函數概念小史 1.2.1 中譯的來源 1.2.2 一個速度問題 1.2.3 幾何的方法 1.2.4 微積分的記法 1.2.5 弦的振動 三 1755年,歐拉改變了主意,在《微分學原理》(Institutiones calculi differen
Thumbnail
直觀理解 導數:考慮的是單一變數的函數,描述的是函數在某點的斜率或變化率。 偏導數:考慮的是多變數函數,描述的是函數在某個變數變化時的變化率,其他變數保持不變。  (針對各維度的調整 或者稱變化 你要調多少) 應用 導數:在物理學中應用廣泛,例如描述速度和加速度。 偏導數:在多變量分析、優
Thumbnail
直觀理解 導數:考慮的是單一變數的函數,描述的是函數在某點的斜率或變化率。 偏導數:考慮的是多變數函數,描述的是函數在某個變數變化時的變化率,其他變數保持不變。  (針對各維度的調整 或者稱變化 你要調多少) 應用 導數:在物理學中應用廣泛,例如描述速度和加速度。 偏導數:在多變量分析、優
Thumbnail
這一系列關於數學符號歷史的紀錄片,共介紹了5種符號,以一集一種符號故事性、戲劇性地方式介紹,分別是圓周率π、無限∞、未知數x、零0、虛數i。一般人都能深入淺出的了解符號背後的由來及發現的意義。趁著這兩天陰雨天在家看完,真心覺得當初若國高中數學課也是如此項是在教一種思想史的教數學,必定會更加有
Thumbnail
這一系列關於數學符號歷史的紀錄片,共介紹了5種符號,以一集一種符號故事性、戲劇性地方式介紹,分別是圓周率π、無限∞、未知數x、零0、虛數i。一般人都能深入淺出的了解符號背後的由來及發現的意義。趁著這兩天陰雨天在家看完,真心覺得當初若國高中數學課也是如此項是在教一種思想史的教數學,必定會更加有
Thumbnail
冪次定律 呈現一條曲線,從左下方緩慢上升,然後迅速上升,強調了少數事件的極端值。這些極端值代表著相對較大的事件,其影響力遠遠超過了大多數事件。 馬太效應 由一個明顯的源頭開始,不斷分支出更多的線條,形成一個庞大的樹狀結構。這些分支中的一些可能變得更大,代表著成功的累積效應,符合馬太效應
Thumbnail
冪次定律 呈現一條曲線,從左下方緩慢上升,然後迅速上升,強調了少數事件的極端值。這些極端值代表著相對較大的事件,其影響力遠遠超過了大多數事件。 馬太效應 由一個明顯的源頭開始,不斷分支出更多的線條,形成一個庞大的樹狀結構。這些分支中的一些可能變得更大,代表著成功的累積效應,符合馬太效應
Thumbnail
這篇要來分享關於「頻率」這件事,談到頻率,不免就要順便談談「吸引力法則」,現在訪間已經有多書籍、影片都有詳細描述吸引力法則的運行方式。它並不是什麼怪力亂神也不是什麼偽科學,實則吸引力法則是個再科學不過的量子力學,同頻相吸的概念而已。
Thumbnail
這篇要來分享關於「頻率」這件事,談到頻率,不免就要順便談談「吸引力法則」,現在訪間已經有多書籍、影片都有詳細描述吸引力法則的運行方式。它並不是什麼怪力亂神也不是什麼偽科學,實則吸引力法則是個再科學不過的量子力學,同頻相吸的概念而已。
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News