An experiment with using pygame to simulate a physical system, inspired by Peter Collingridges's tutorial posts. In this case, I'm modelling resonances on a string fixed at one end, with the other end driven at a variable frequency. Full description in blog post here.
Created
January 20, 2015 10:06
-
-
Save keerlu/180f422112b48d2c1f20 to your computer and use it in GitHub Desktop.
Waves on a string
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
## Standing wave demonstration with pygame | |
import pygame | |
import time | |
import math | |
# Window size | |
canvas_width = 640 | |
canvas_height = 480 | |
# Define colours | |
line_colour = pygame.Color(55, 115, 212, 0) | |
background_colour = pygame.Color(255, 255, 255, 0) | |
slider_colour = pygame.Color(0, 0, 0, 0) | |
# Make screen | |
screen = pygame.display.set_mode((canvas_width, canvas_height)) | |
screen.fill(background_colour) | |
# Make drawing surface | |
surface = pygame.Surface((canvas_width, canvas_height)).convert() | |
surface.fill(background_colour) | |
# Define standing wave function | |
amplitude = 3 # in px | |
speed = 1 | |
def k(n): | |
return n*math.pi/canvas_width | |
def ysummand(x, n, frequency): | |
return ((float(frequency)/speed)**2/n)*(1/(k(n)**2-(float(frequency)/speed)**2))*math.sin(k(n)*(float(x))) | |
def ysum(x, Nmax, frequency): | |
sumList = [0]*Nmax | |
for i in range(1, Nmax): | |
sumList[i] = ysummand(x, i, frequency) | |
return sum(sumList) | |
def y(x, frequency): | |
return (2/math.pi)*amplitude*ysum(x, 10, frequency) | |
def psi(x, frequency): | |
return y(x, frequency) + amplitude*(1 - (float(x)/float(canvas_width))) | |
pygame.init() | |
# Main loop | |
running = True | |
freq = 0.01 # set initial frequency | |
while running: | |
for event in pygame.event.get(): | |
if event.type == pygame.QUIT: | |
running = False | |
# Redraw background | |
surface.fill(background_colour) | |
for xrange in range(0, canvas_width): | |
yrange = int((canvas_height/2) + psi(xrange, freq)*math.cos(1000*speed*freq*time.time())) | |
for i in range(0, 4): | |
surface.set_at((xrange, yrange + i), line_colour) | |
# Display some text | |
font = pygame.font.Font(None, 36) | |
text = font.render("Frequency is "+str(abs(freq)), 1, (10, 10, 10)) | |
textpos = text.get_rect() | |
textpos.centerx = surface.get_rect().centerx | |
surface.blit(text, textpos) | |
move_ticker = 0 | |
keys=pygame.key.get_pressed() | |
if keys[pygame.K_LEFT]: | |
if move_ticker == 0: | |
move_ticker = 20 | |
freq -= 0.0001 | |
if keys[pygame.K_RIGHT]: | |
if move_ticker == 0: | |
move_ticker = 20 | |
freq += 0.0001 | |
# Add surface to screen | |
screen.blit(surface, (0, 0)) | |
# Display | |
pygame.display.flip() | |
pygame.quit() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment