require 'tk'

$root = TkRoot.new( => )
$canvas = TkCanvas.new($root) do
  width 320
  height 200
  create TkcLine, 0,25,320,25,   'tags' => 'plate', 'width' => 2, 'fill' => 'grey50'
  create TkcOval, 155,20,165,30, 'tags' => 'pivot', 'outline' => , 'fill' => 'grey50'
  create TkcLine, 1,1,1,1, 'tags' => 'rod', 'width' => 3, 'fill' => 'black'
  create TkcOval, 1,1,2,2, 'tags' => 'bob', 'outline' => 'black', 'fill' => 'yellow'
end
$canvas.raise('pivot')
$canvas.pack('fill' => 'both', 'expand' => true)

$Theta = 45.0
$dTheta = 0.0
$length = 150
$homeX = 160
$homeY = 25

def show_pendulum
  angle = $Theta * Math::PI / 180
  x = $homeX + $length * Math.sin(angle)
  y = $homeY + $length * Math.cos(angle)
  $canvas.coords('rod', $homeX, $homeY, x, y)
  $canvas.coords('bob', x-15, y-15, x+15, y+15)
end

def recompute_angle
  scaling = 3000.0 / ($length ** 2)
  
  firstDDTheta = -Math.sin($Theta * Math::PI / 180) * scaling
  midDTheta = $dTheta + firstDDTheta
  midTheta = $Theta + ($dTheta + midDTheta)/2
  
  midDDTheta = -Math.sin(midTheta * Math::PI / 180) * scaling
  midDTheta = $dTheta + (firstDDTheta + midDDTheta)/2
  midTheta = $Theta + ($dTheta + midDTheta)/2
  
  midDDTheta = -Math.sin(midTheta * Math::PI / 180) * scaling
  lastDTheta = midDTheta + midDDTheta
  lastTheta = midTheta + (midDTheta + lastDTheta)/2
  
  lastDDTheta = -Math.sin(lastTheta * Math::PI/180) * scaling
  lastDTheta = midDTheta + (midDDTheta + lastDDTheta)/2
  lastTheta = midTheta + (midDTheta + lastDTheta)/2
  
  $dTheta  = lastDTheta
  $Theta = lastTheta
end

def animate
  recompute_angle
  show_pendulum
  $after_id = $root.after(15) {animate}
end

show_pendulum
$after_id = $root.after(500) {animate}

$canvas.bind('<Destroy>') {$root.after_cancel($after_id)}

Tk.mainloop