Skip to content

Instantly share code, notes, and snippets.

@Impulsleistung
Created February 1, 2025 20:14
Show Gist options
  • Save Impulsleistung/9d1bd7aebf2df699f27cd57ce5e61435 to your computer and use it in GitHub Desktop.
Save Impulsleistung/9d1bd7aebf2df699f27cd57ce5e61435 to your computer and use it in GitHub Desktop.
animation of spring-mass-damper system with realistic physics
import pygame
import pymunk
import pymunk.pygame_util
import numpy as np
from scipy.signal import sawtooth
# Initialisierung
pygame.init()
WIDTH, HEIGHT = 800, 600
window = pygame.display.set_mode((WIDTH, HEIGHT))
clock = pygame.time.Clock()
# Physik-Space konfigurieren
space = pymunk.Space()
space.gravity = (0, 900) # Schwerkraft
draw_options = pymunk.pygame_util.DrawOptions(window)
# Boden erstellen
ground = pymunk.Segment(space.static_body, (0, 550), (WIDTH, 550), 5)
ground.friction = 1.0
space.add(ground)
# Anregungsparameter
PERIODE = 3.0 # 3 Sekunden Periodendauer
AMPLITUDE = 100 # Vertikale Amplitude in Pixel
# Feder-Ankerpunkt (kinematischer Körper für Bewegung)
anchor = pymunk.Body(body_type=pymunk.Body.KINEMATIC)
anchor.position = (400, 300)
space.add(anchor)
# Masse erstellen
mass = pymunk.Body()
mass.position = (400, 400)
shape = pymunk.Poly.create_box(mass, (30, 30))
shape.mass = 8.0
shape.friction = 0.5
space.add(mass, shape)
# Feder-Dämpfer-System
spring = pymunk.DampedSpring(
anchor,
mass,
(0, 0),
(0, 0),
rest_length=100,
stiffness=120, # Federkonstante
damping=15, # Dämpfungskoeffizient
)
space.add(spring)
# Dreieckfunktion für vertikale Anregung
def triangle_wave(t):
phase = sawtooth(2 * np.pi * t / PERIODE, width=0.5)
return AMPLITUDE * phase
# Hauptsimulationsschleife
running = True
start_time = pygame.time.get_ticks()
while running:
# Zeitberechnung
current_time = (pygame.time.get_ticks() - start_time) / 1000.0
# Ankerposition aktualisieren
anchor.position = (400, 300 + triangle_wave(current_time))
# Events verarbeiten
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# Physik-Update
space.step(1 / 60)
# Zeichnen
window.fill((30, 30, 30))
space.debug_draw(draw_options)
pygame.draw.line(window, (255, 255, 255), anchor.position, mass.position, 3)
pygame.display.flip()
clock.tick(60)
pygame.quit()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment