1 # Copyright (c) 2009 Paolo Capriotti <p.capriotti@gmail.com>
3 # This program is free software; you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation; either version 2 of the License, or
6 # (at your option) any later version.
8 require 'observer_utils'
12 # A clock keeps track of game time and sends regular updates to a graphical
13 # clock component whenever the displayed time needs to change.
15 # The clock is based on the idea of _displayed_ time, which is the value in
16 # milliseconds that is displayed to the user on a clock with a specified
17 # _resolution_. For example, if the remaining time is 13561 milliseconds, and
18 # the resolution is 1 second, the displayed time is 14000.
20 # In general, the displayed time is the smallest multiple of the resolution
21 # which is greater or equal to the actual time.
23 # The other important concept is the _step_. This is currently set to the
24 # constant 100, and represents the frequency with which the internal timer is
27 # The resolution can be set while the clock is running, but only to a multiple
34 attr_reader :resolution
38 # Create a clock object. Times are expressed in milliseconds.
39 # The timer_class argument can be used to provide a different factory for
40 # the internal timer (the default is Qt::Timer).
42 def initialize(main, increment, timer_class = Qt::Timer)
47 @increment = increment
49 @timer = timer_class.new
50 @timer.single_shot = true
51 @timer.on(:timeout) { tick }
60 # The clock keeps track of the portion of step elapsed since the last tick,
61 # and will compensate when resuming.
69 @displayed += @increment
77 # Start or resume the timer.
90 # The current displayed time.
97 # The main internal method, called every STEP milliseconds to update the
98 # internal state and keep track of elapsed time.
100 # Fire timer signal when the displayed time is a multiple of resolution.
103 return unless @running
108 if @displayed % @resolution == 0
116 # Forcibly set a time for this clock.
118 # As a side effect, this method causes the timer to stop.
124 # always stop the timer when forcing a time
132 # Whether the clock is running
139 # Set resolution in milliseconds.
141 # The value must be a multiple of STEP.
143 def resolution=(value)
144 if value <= 0 || (value % STEP != 0)
145 raise "Invalid resolution"
153 @rem = @rem_last - @time.elapsed
157 @displayed = @rem + STEP - 1 - (@rem - 1) % STEP
161 [0, STEP - @displayed + @rem].max