Skip to content

Instantly share code, notes, and snippets.

@keerlu
Created January 20, 2015 10:06
Show Gist options
  • Save keerlu/180f422112b48d2c1f20 to your computer and use it in GitHub Desktop.
Save keerlu/180f422112b48d2c1f20 to your computer and use it in GitHub Desktop.
Waves on a string

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.

## 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