RosettaCodeData/Task/Animate-a-pendulum/Ruby/animate-a-pendulum-3.rb

105 lines
2.0 KiB
Ruby

#!/bin/ruby
begin; require 'rubygems'; rescue; end
require 'gosu'
include Gosu
# Screen size
W = 640
H = 480
# Full-screen mode
FS = false
# Screen update rate (Hz)
FPS = 60
class Pendulum
attr_accessor :theta, :friction
def initialize( win, x, y, length, radius, bob = true, friction = false)
@win = win
@centerX = x
@centerY = y
@length = length
@radius = radius
@bob = bob
@friction = friction
@theta = 60.0
@omega = 0.0
@scale = 2.0 / FPS
end
def draw
@win.translate(@centerX, @centerY) {
@win.rotate(@theta) {
@win.draw_quad(-1, 0, 0x3F_FF_FF_FF, 1, 0, 0x3F_FF_FF_00, 1, @length, 0x3F_FF_FF_00, -1, @length, 0x3F_FF_FF_FF )
if @bob
@win.translate(0, @length) {
@win.draw_quad(0, -@radius, Color::RED, @radius, 0, Color::BLUE, 0, @radius, Color::WHITE, -@radius, 0, Color::BLUE )
}
end
}
}
end
def update
# Thanks to Hugo Elias for the formula (and explanation thereof)
@theta += @omega
@omega = @omega - (Math.sin(@theta * Math::PI / 180) / (@length * @scale))
@theta *= 0.999 if @friction
end
end # Pendulum class
class GfxWindow < Window
def initialize
# Initialize the base class
super W, H, FS, 1.0 / FPS * 1000
# self.caption = "You're getting sleeeeepy..."
self.caption = "Ruby/Gosu Pendulum Simulator (Space toggles friction)"
@n = 1 # Try changing this number!
@pendulums = []
(1..@n).each do |i|
@pendulums.push Pendulum.new( self, W / 2, H / 10, H * 0.75 * (i / @n.to_f), H / 60 )
end
end
def draw
@pendulums.each { |pen| pen.draw }
end
def update
@pendulums.each { |pen| pen.update }
end
def button_up(id)
if id == KbSpace
@pendulums.each { |pen|
pen.friction = !pen.friction
pen.theta = (pen.theta <=> 0) * 45.0 unless pen.friction
}
else
close
end
end
def needs_cursor?()
true
end
end # GfxWindow class
begin
GfxWindow.new.show
rescue Exception => e
puts e.message, e.backtrace
gets
end