require 'sdl'
class FPSTimerSample
FPS_COUNT = 10
attr_accessor :fps
attr_reader :real_fps, :total_skip
attr_reader :count_sleep
# +fps+ is the number of frames per second that you want to keep,
# +accurary+ is the accurary of sleep/SDL.delay in milisecond
def initialize(fps = 60, accurary = 10, skip_limit = 15)
@fps = fps
@accurary = accurary / 1000.0
@skip_limit = skip_limit
end
# reset timer, you should call just before starting loop
def reset
@old = get_ticks
@skip = 0
@real_fps = @fps
@frame_count = 0
@fps_old = @old
@count_sleep = 0
@total_skip = 0
end
# execute given block and wait
def wait_frame
now = get_ticks
nxt = @old + (1.0/@fps)
if nxt > now || @skip > @skip_limit
yield
@skip = 0
wait(nxt)
@old = nxt
else
@skip += 1
@total_skip += 1
@old = get_ticks
end
calc_real_fps
end
private
def wait(nxt)
while nxt > get_ticks + @accurary
sleep(@accurary - 0.005)
@count_sleep += 1
end
while nxt > get_ticks
# busy loop, do nothing
end
end
def get_ticks
SDL.getTicks / 1000.0
end
def calc_real_fps
@frame_count += 1
if @frame_count >= FPS_COUNT
@frame_count = 0
now = get_ticks
@real_fps = FPS_COUNT / (now - @fps_old)
@fps_old = now
end
end
end
class FPSTimerLight
N = 12
DT = 2
FPS_COUNT = 10
attr_reader :fps
attr_reader :real_fps
# +fps+ is the number of frames per second that you want to keep,
# +accurary+ is the accurary of sleep/SDL.delay in milisecond
def initialize(fps = 60, accurary = 10, skip_limit = 15)
@fps = fps
@accurary = accurary * N
@skip_limit = 15
@one_frame = 1000*N / fps
@delay = accurary - 2
end
# reset timer, you should call just before starting loop
def reset
@old = get_ticks
@skip = 0
# for calculate real fps
@frame_count = 0
@fps_old = @old
@real_fps = @fps
end
def wait_frame
now = get_ticks
nxt = @old + @one_frame
if nxt > now || @skip > @skip_limit
yield
@skip = 0
wait(nxt)
@old = nxt
else
@skip += 1
@total_skip += 1
@old = get_ticks
end
calc_real_fps
end
private
def get_ticks
SDL.getTicks * N
end
def wait(nxt)
while nxt > get_ticks + @accurary
SDL.delay(@delay)
end
while nxt > get_ticks
# busy loop, do nothing
end
end
def calc_real_fps
@frame_count += 1
if @frame_count >= FPS_COUNT
@frame_count = 0
now = get_ticks
@real_fps = (N*1000*FPS_COUNT)/(now - @fps_old)
@fps_old = now
end
end
end
if __FILE__ == $0
timer = FPSTimerSample.new
log = []
timer.reset
300.times do
sleep 0.005 if rand(5) == 0
timer.wait_frame do
log << timer.real_fps.to_s
end
end
puts log
printf "skip:%d\n", timer.total_skip
printf "sleep:%d\n", timer.count_sleep
puts
timer = FPSTimerLight.new
log = []
timer.reset
old = SDL.getTicks
300.times do
sleep 0.005 if rand(5) == 0
timer.wait_frame do
log << timer.real_fps
end
end
puts log
end
syntax highlighted by Code2HTML, v. 0.9.1