NaaLaa

Full Version: Bridge (simple physics)
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
BRIDGE
A demo of simple physics

[attachment=434][attachment=435]
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
Lovely demo - I look forward to seeing future updates.....
SO cool... Well done!
Very nice indeed!