03-16-2025, 09:51 AM
(This post was last modified: 03-16-2025, 10:00 AM by 1micha.elok.)
BRIDGE
A demo of simple physics
click the images to zoom in
How It Works
1. The circle falls due to gravity and collides with the bridge.
2. Upon collision, the circle applies a downward force to the bridge segment it lands on, proportional to its mass.
3. Springs pull the displaced segments back toward their rest positions, creating a bending effect
4. When the ball stops moving, increased damping stabilizes the bridge, preventing further vibrations
A demo of simple physics
click the images to zoom in
How It Works
1. The circle falls due to gravity and collides with the bridge.
2. Upon collision, the circle applies a downward force to the bridge segment it lands on, proportional to its mass.
3. Springs pull the displaced segments back toward their rest positions, creating a bending effect
4. When the ball stops moving, increased damping stabilizes the bridge, preventing further vibrations
Code:
'=================================
'
' BRIDGE
' A demo of simple physics
'
'=================================
#win32
set window "bridge",800, 600,false
set redraw off
' Gravity value
visible gravity = 0.5
' Parameters for the bridge
visible bridge = []
bridge.segments = 15 ' number of segments in the bridge
bridge.swidth = 40 ' width of each segment
bridge.sheight = 10 ' height of each segment
bridge.gap = 5 ' gap between segments
bridge.y = height()/2 ' vertical position of the bridge
' Calculate total width of the bridge
bridge.total = bridge.segments * bridge.swidth + (bridge.segments - 1) * bridge.gap
' Calculate starting x-coordinate to center the bridge horizontally
bridge.start = (width() - bridge.total) / 2
' Bridge segment position
bridge.xs = []
bridge.ys = []
bridge.vy = []
bridge.rest = [] ' Rest position of each segment
bridge.spring = [] ' Spring elasticity
' Initialize bridge segments
for i = 0 to bridge.segments - 1
bridge.xs[i] = bridge.start + i * (bridge.swidth + bridge.gap)
bridge.ys[i] = bridge.y
bridge.rest[i] = bridge.y
bridge.vy[i] = 0
bridge.spring[i]= 0.1
next
' Parameters for the falling circle
visible circle = []
circle.radius = 15 ' Radius of the circle
circle.x = width()/2 ' Initial x position of the circle
circle.y = bridge.y-circle.radius ' Initial y position of the circle
circle.vx = 0 ' Horizontal velocity
circle.vy = 0 ' Vertical velocity
circle.mass = 0
circle.bounce = 0.7 ' Energy loss on collision
circle.velocity = 0.1
' Function to update the circle's position
function update_circle()
' Apply gravity to the vertical velocity
circle.vy = circle.vy + gravity
' Update the circle's position based on velocity
circle.x = circle.x + circle.vx
circle.y = circle.y + circle.vy
endfunc
' Function to handle collisions between the circle and the bridge
function handle_collisions()
for i = 0 to bridge.segments - 1
' Check if the circle overlaps with the current bridge segment
if circle.x + circle.radius > bridge.xs[i] and
circle.x - circle.radius < bridge.xs[i] + bridge.swidth and
circle.y + circle.radius > bridge.ys[i] and
circle.y - circle.radius < bridge.ys[i] + bridge.sheight then
' Collision detected: Reposition the circle and apply force to the bridge segment
overlap = (circle.y + circle.radius) - bridge.ys[i]
circle.y = bridge.ys[i] - circle.radius ' Reposition the circle above the bridge
' Reverse and dampen vertical velocity
circle.vy = circle.vy * -circle.bounce
' Stop bouncing if velocity is below the threshold
if abs(circle.vy) < circle.velocity then
circle.vy = 0
endif
' Apply downward force to the bridge segment based on the circle's mass
bridge.vy[i] = bridge.vy[i] + overlap * circle.mass * 0.01
endif
next
endfunc
' Simulate spring forces between bridge segments
function simulate_springs()
for i = 1 to bridge.segments - 1
' Calculate displacement from rest position
dy = bridge.ys[i] - bridge.rest[i]
' Apply spring force to pull the segment back to its rest position
bridge.vy[i] = bridge.vy[i] - dy * bridge.spring[i]
next
' Apply spring forces between adjacent segments
for i = 1 to bridge.segments - 1
' Calculate displacement between adjacent segments
dy = bridge.ys[i] - bridge.ys[i - 1]
force = dy * bridge.spring[i]
' Apply spring force
bridge.vy[i] = bridge.vy[i] - force
bridge.vy[i - 1] = bridge.vy[i - 1] + force
next
endfunc
' Update bridge positions
function update_bridge()
for i = 0 to bridge.segments - 1
' If the ball has stopped moving, increase damping to stabilize the bridge
if abs(circle.vy) < circle.velocity then
bridge.vy[i] = 0 ' Stronger damping when the ball stops
else
bridge.vy[i] = bridge.vy[i] * 0.99 ' Normal damping during movement
endif
bridge.ys[i] = bridge.ys[i] + bridge.vy[i]
' Prevent the bridge from bending too far downward
if bridge.ys[i] > bridge.rest[i] + 50 then
bridge.ys[i] = bridge.rest[i] + 50
bridge.vy[i] = 0
endif
' Ensure the bridge doesn't go above its rest position
if bridge.ys[i] < bridge.rest[i] then
bridge.ys[i] = bridge.rest[i]
bridge.vy[i] = 0
endif
next
endfunc
' Render the bridge and the circle
function render_scene()
'clear screen
set color 0,0,0;cls
'white
set color 255,255,255
' Draw the bridge
for i = 0 to bridge.segments - 1
draw rect bridge.xs[i], bridge.ys[i], bridge.swidth, bridge.sheight
next
' Draw the circle
draw ellipse circle.x, circle.y, circle.radius, circle.radius
endfunc
'--------------
' Main Loop
'--------------
while not keydown(KEY_ESCAPE,true)
update_circle() ' Update the circle's position
handle_collisions() ' Handle collisions with the bridge
simulate_springs()
update_bridge()
render_scene() ' Render the scene
'control keys
if keydown(KEY_1,true) then
circle.mass = 10
circle.y = -50
endif
if keydown(KEY_2,true) then
circle.mass = 150
circle.y = -50
endif
set caret 10, bridge.y+100
set color 255,255,255
wln "Simple Physics"
wln "================================================"
wln
wln "Please watch how the bridge reacts to the circle"
wln
wln "Press Key 1 : weight = 10 (light)"
wln "Press Key 2 : weight = 150 (heavy)"
wln
wln "Circle Mass = "+circle.mass
wln
fwait 10
redraw
wend