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