rubygame 2.4.1 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * Rubygame -- Ruby code and bindings to SDL to facilitate game creation
3
- * Copyright (C) 2004-2007 John Croisant
3
+ * Copyright (C) 2004-2009 John Croisant
4
4
  *
5
5
  * This library is free software; you can redistribute it and/or
6
6
  * modify it under the terms of the GNU Lesser General Public
@@ -18,15 +18,15 @@
18
18
  *
19
19
  */
20
20
 
21
- #ifndef _RUBYGAME_TIME_H
22
- #define _RUBYGAME_TIME_H
21
+ #ifndef _RUBYGAME_CLOCK_H
22
+ #define _RUBYGAME_CLOCK_H
23
23
 
24
- extern void Rubygame_Init_Time();
24
+ extern void Rubygame_Init_Clock();
25
25
 
26
26
  extern VALUE cClock;
27
27
 
28
- extern VALUE rbgm_time_wait(VALUE, VALUE);
29
- extern VALUE rbgm_time_delay(int, VALUE*, VALUE);
30
- extern VALUE rbgm_time_getticks(VALUE);
28
+ extern VALUE rbgm_clock_wait(int, VALUE*, VALUE);
29
+ extern VALUE rbgm_clock_delay(int, VALUE*, VALUE);
30
+ extern VALUE rbgm_clock_runtime(VALUE);
31
31
 
32
32
  #endif
@@ -27,7 +27,7 @@
27
27
  #include "rubygame_joystick.h"
28
28
  #include "rubygame_screen.h"
29
29
  #include "rubygame_surface.h"
30
- #include "rubygame_time.h"
30
+ #include "rubygame_clock.h"
31
31
 
32
32
  VALUE rbgm_init(VALUE);
33
33
  VALUE rbgm_quit(VALUE);
@@ -127,7 +127,7 @@ void Init_rubygame_core()
127
127
  INT2NUM(SDL_MINOR_VERSION),
128
128
  INT2NUM(SDL_PATCHLEVEL)));
129
129
 
130
- Rubygame_Init_Time();
130
+ Rubygame_Init_Clock();
131
131
  Rubygame_Init_Surface();
132
132
  Rubygame_Init_Screen();
133
133
  Rubygame_Init_Event();
@@ -32,6 +32,8 @@ VALUE cScreen;
32
32
  VALUE rbgm_screen_setmode(int, VALUE*, VALUE);
33
33
  VALUE rbgm_screen_getsurface(VALUE);
34
34
 
35
+ VALUE rbgm_screen_getresolution(VALUE);
36
+
35
37
  VALUE rbgm_screen_getcaption(VALUE);
36
38
  VALUE rbgm_screen_setcaption(VALUE, VALUE);
37
39
 
@@ -46,8 +48,8 @@ VALUE rbgm_screen_setshowcursor(VALUE, VALUE);
46
48
 
47
49
 
48
50
  /* call-seq:
49
- * new(size, depth=0, flags=[SWSURFACE]) -> Screen
50
- * (aliases: set_mode, instance)
51
+ * Screen.new( size, depth=0, flags=[SWSURFACE] ) -> Screen
52
+ * (alias: open)
51
53
  *
52
54
  * Create a new Rubygame window if there is none, or modify the existing one.
53
55
  * You cannot create more than one Screen; the existing one will be replaced.
@@ -94,13 +96,13 @@ VALUE rbgm_screen_setshowcursor(VALUE, VALUE);
94
96
  * OpenGL functions.
95
97
  * RESIZABLE:: Create a resizable window. When the window is
96
98
  * resized by the user, a ResizeEvent is
97
- * generated and #set_mode can be called again
99
+ * generated and this method can be called again
98
100
  * with the new size.
99
101
  * NOFRAME:: If possible, create a window with no title bar or
100
102
  * frame decoration.
101
103
  * Fullscreen modes automatically have this flag set.
102
104
  */
103
- VALUE rbgm_screen_setmode(int argc, VALUE *argv, VALUE module)
105
+ VALUE rbgm_screen_new(int argc, VALUE *argv, VALUE module)
104
106
  {
105
107
  SDL_Surface *screen;
106
108
  int w, h, depth;
@@ -133,8 +135,73 @@ VALUE rbgm_screen_setmode(int argc, VALUE *argv, VALUE module)
133
135
  return Data_Wrap_Struct( cScreen,0,0,screen );
134
136
  }
135
137
 
138
+
139
+ /* call-seq:
140
+ * Screen.set_mode( size, depth=0, flags=[SWSURFACE] ) -> Screen
141
+ *
142
+ * Deprecated alias for Screen.new. This method will be REMOVED
143
+ * in Rubygame 3.0. You should use Screen.new (or its alias, Screen.open)
144
+ * instead.
145
+ */
146
+ VALUE rbgm_screen_setmode(int argc, VALUE *argv, VALUE module)
147
+ {
148
+ rg_deprecated("Rubygame::Screen.set_mode", "3.0");
149
+ return rbgm_screen_new(argc, argv, module);
150
+ }
151
+
152
+ /* call-seq:
153
+ * Screen.instance( size, depth=0, flags=[SWSURFACE] ) -> Screen
154
+ *
155
+ * Deprecated alias for Screen.new. This method will be REMOVED
156
+ * in Rubygame 3.0. You should use Screen.new (or its alias, Screen.open)
157
+ * instead.
158
+ */
159
+ VALUE rbgm_screen_instance(int argc, VALUE *argv, VALUE module)
160
+ {
161
+ rg_deprecated("Rubygame::Screen.instance", "3.0");
162
+ return rbgm_screen_new(argc, argv, module);
163
+ }
164
+
165
+
166
+ /*
167
+ * call-seq:
168
+ * Screen.close
169
+ *
170
+ * Close the Screen, making the Rubygame window disappear.
171
+ * This method also exits from fullscreen mode, if needed.
172
+ *
173
+ * After calling this method, you should discard any references
174
+ * to the old Screen surface, as it is no longer valid, even
175
+ * if you call Screen.new again.
176
+ *
177
+ * (Note: You do not need to close the Screen to change its size
178
+ * or flags, you can simply call Screen.new while already open.)
179
+ *
180
+ */
181
+ VALUE rbgm_screen_close(VALUE module)
182
+ {
183
+ SDL_QuitSubSystem(SDL_INIT_VIDEO);
184
+ return Qnil;
185
+ }
186
+
187
+
188
+ /*
189
+ * call-seq:
190
+ * Screen.open?
191
+ *
192
+ * True if there is an open Rubygame window.
193
+ * See Screen.new and Screen.close.
194
+ *
195
+ */
196
+ VALUE rbgm_screen_openp(VALUE module)
197
+ {
198
+ return (SDL_GetVideoSurface() == NULL) ? Qfalse : Qtrue;
199
+ }
200
+
201
+
202
+
136
203
  /* call-seq:
137
- * get_surface
204
+ * Screen.get_surface
138
205
  *
139
206
  * Returns the current display window, or raises SDLError if it
140
207
  * fails to get it (for example, if it doesn't exist yet).
@@ -150,7 +217,55 @@ VALUE rbgm_screen_getsurface(VALUE module)
150
217
  return Data_Wrap_Struct( cScreen,0,0,surface );
151
218
  }
152
219
 
153
- /* Screen methods: */
220
+
221
+ /* call-seq:
222
+ * Screen.get_resolution -> [width, height]
223
+ *
224
+ * Returns the pixel dimensions of the user's display (i.e. monitor).
225
+ * (That is not the same as Screen#size, which only measures the
226
+ * Rubygame window.) You can use this information to detect
227
+ * how large of a Screen can fit on the user's display.
228
+ *
229
+ * This method can _only_ be used when there is no open Screen instance.
230
+ * This method raises SDLError if there is a Screen instance (i.e.
231
+ * you have done Screen.new before). This is a limitation of the SDL
232
+ * function SDL_GetVideoInfo, which behaves differently when a Screen
233
+ * is open than when it is closed.
234
+ *
235
+ * This method will also raise SDLError if it cannot get the display
236
+ * size for some other reason.
237
+ *
238
+ */
239
+ VALUE rbgm_screen_getresolution(VALUE module)
240
+ {
241
+ VALUE array;
242
+ const SDL_VideoInfo* hw;
243
+ init_video_system();
244
+
245
+ /* Test for existing Screen */
246
+ SDL_Surface *surface;
247
+ surface = SDL_GetVideoSurface();
248
+ if(surface != NULL)
249
+ {
250
+ rb_raise(eSDLError, "You cannot get resolution when there is " \
251
+ "an open Screen. See the docs for the reason.");
252
+ }
253
+
254
+ hw = SDL_GetVideoInfo();
255
+ if(hw==NULL)
256
+ {
257
+ rb_raise(eSDLError,"Couldn't get video info: %s",SDL_GetError());
258
+ }
259
+
260
+ array = rb_ary_new();
261
+ rb_ary_push(array, INT2NUM(hw->current_w));
262
+ rb_ary_push(array, INT2NUM(hw->current_h));
263
+ return array;
264
+ }
265
+
266
+
267
+ /* Screen instance methods: */
268
+
154
269
 
155
270
  /* call-seq:
156
271
  * title -> String
@@ -224,7 +339,7 @@ VALUE rbgm_screen_seticon(VALUE self, VALUE data)
224
339
  *
225
340
  * Updates (refreshes) all or part of the Rubygame window, revealing to the
226
341
  * user any changes that have been made since the last update. If you're using
227
- * a double-buffered display (see Display.set_mode), you should use
342
+ * a double-buffered display (see Screen.new), you should use
228
343
  * Screen#flip instead.
229
344
  *
230
345
  * This method takes these arguments:
@@ -347,7 +462,7 @@ VALUE rbgm_screen_updaterects(VALUE self, VALUE array_rects)
347
462
  /* call-seq:
348
463
  * flip()
349
464
  *
350
- * If the Rubygame display is double-buffered (see #set_mode), flips
465
+ * If the Rubygame display is double-buffered (see Screen.new), flips
351
466
  * the buffers and updates the whole screen. Otherwise, just updates the
352
467
  * whole screen.
353
468
  */
@@ -402,8 +517,8 @@ VALUE rbgm_screen_setshowcursor(VALUE self, VALUE val)
402
517
  * Surface#set_colorkey and Surface#set_alpha are not inherited.
403
518
  *
404
519
  * Please note that only *one* Screen can exist, per application, at a time;
405
- * this is a limitation of SDL. You *must* use Screen.set_mode to create the
406
- * Screen or modify its properties.
520
+ * this is a limitation of SDL. You *must* use Screen.new (or its alias,
521
+ * Screen.open) to create or modify the Screen.
407
522
  *
408
523
  * Also note that no changes to the Screen will be seen until it is refreshed.
409
524
  * See #update, #update_rects, and #flip for ways to refresh all or part of
@@ -419,10 +534,19 @@ void Rubygame_Init_Screen()
419
534
 
420
535
  /* Screen class */
421
536
  cScreen = rb_define_class_under(mRubygame,"Screen",cSurface);
422
- rb_define_singleton_method(cScreen,"new",rbgm_screen_setmode, -1);
423
- rb_define_alias(rb_singleton_class(cScreen),"set_mode","new");
424
- rb_define_alias(rb_singleton_class(cScreen),"instance","new");
537
+ rb_define_singleton_method(cScreen,"new",rbgm_screen_new, -1);
538
+ rb_define_alias(rb_singleton_class(cScreen),"open","new");
539
+
540
+ rb_define_singleton_method(cScreen,"close", rbgm_screen_close, 0);
541
+ rb_define_singleton_method(cScreen,"open?", rbgm_screen_openp, 0);
425
542
  rb_define_singleton_method(cScreen,"get_surface",rbgm_screen_getsurface, 0);
543
+ rb_define_singleton_method(cScreen,"get_resolution",rbgm_screen_getresolution, 0);
544
+
545
+ /* Deprecated: */
546
+ rb_define_singleton_method(cScreen,"set_mode", rbgm_screen_setmode, -1);
547
+ rb_define_singleton_method(cScreen,"instance", rbgm_screen_instance, -1);
548
+
549
+
426
550
 
427
551
  /* These are inherited from Surface, but should not be called on Screen */
428
552
  rb_undef_method(cScreen,"set_alpha");
@@ -28,6 +28,8 @@ extern VALUE cScreen;
28
28
  extern VALUE rbgm_screen_setmode(int, VALUE*, VALUE);
29
29
  extern VALUE rbgm_screen_getsurface(VALUE);
30
30
 
31
+ extern VALUE rbgm_screen_getresolution(VALUE);
32
+
31
33
  extern VALUE rbgm_screen_getcaption(VALUE);
32
34
  extern VALUE rbgm_screen_setcaption(VALUE, VALUE);
33
35
 
data/lib/rubygame.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  #--
2
+ #
2
3
  # Rubygame -- Ruby code and bindings to SDL to facilitate game creation
3
- # Copyright (C) 2004-2007, 2008 John Croisant
4
+ # Copyright (C) 2004-2009 John Croisant
4
5
  #
5
6
  # This library is free software; you can redistribute it and/or
6
7
  # modify it under the terms of the GNU Lesser General Public
@@ -15,6 +16,7 @@
15
16
  # You should have received a copy of the GNU Lesser General Public
16
17
  # License along with this library; if not, write to the Free Software
17
18
  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
+ #
18
20
  #++
19
21
 
20
22
  # This file is loaded when you "require 'rubygame'".
@@ -39,6 +41,8 @@ require "rubygame_core"
39
41
  end
40
42
  end
41
43
 
44
+ require "rubygame/shared"
45
+
42
46
  require "rubygame/color"
43
47
  require "rubygame/constants"
44
48
 
@@ -1,6 +1,7 @@
1
1
  #--
2
+ #
2
3
  # Rubygame -- Ruby code and bindings to SDL to facilitate game creation
3
- # Copyright (C) 2004-2007 John Croisant
4
+ # Copyright (C) 2004-2009 John Croisant
4
5
  #
5
6
  # This library is free software; you can redistribute it and/or
6
7
  # modify it under the terms of the GNU Lesser General Public
@@ -15,114 +16,295 @@
15
16
  # You should have received a copy of the GNU Lesser General Public
16
17
  # License along with this library; if not, write to the Free Software
17
18
  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
+ #
18
20
  #++
19
21
 
22
+
23
+ require "rubygame/events/clock_events"
24
+
25
+
20
26
  module Rubygame
21
- # Clock provides class methods for tracking running time and delaying
22
- # execution of the program for specified time periods. This is used to
23
- # provide a consistent framerate, prevent the program from using
24
- # all the processor time, etc.
25
- #
26
- # Clock also provides instance methods to make it convenient to
27
- # monitor and limit application framerate. See #tick.
28
- class Clock
29
- # The runtime when the Clock was initialized.
30
- attr_reader :start
31
- # The number of times #tick has been called.
32
- attr_reader :ticks
33
-
34
- # Create a new Clock instance.
35
- def initialize()
36
- @start = Clock.runtime()
37
- @last_tick = @start
38
- @ticks = 0
39
- @target_frametime = nil
40
- yield self if block_given?
41
- end
42
-
43
- # The target frametime (milliseconds/frame). See #tick
44
- attr_accessor :target_frametime
45
-
46
- # Returns the current target framerate (frames/second).
47
- # This is an alternate way to access @target_frametime.
48
- # Same as: 1000.0 / #target_frametime
49
- def target_framerate
50
- if @target_frametime
51
- 1000.0 / @target_frametime
52
- else
53
- nil
54
- end
55
- rescue ZeroDivisionError
56
- return nil
57
- end
58
-
59
- # Sets the target number of frames per second to +framerate+.
60
- # This is an alternate way to access @target_frametime.
61
- # Same as: #target_frametime = 1000.0 / framerate
62
- def target_framerate=( framerate )
63
- if framerate
64
- @target_frametime = 1000.0 / framerate
65
- else
66
- @target_frametime = nil
67
- end
68
- rescue ZeroDivisionError
69
- @target_frametime = nil
70
- end
71
-
72
- # call-seq: lifetime() -> Numeric
73
- #
74
- # Returns time in milliseconds since this Clock instance was created.
75
- def lifetime
76
- Clock.runtime() - @start
77
- end
78
-
79
- # call-seq: framerate() -> Numeric
80
- #
81
- # Return the actual framerate (frames per second) recorded by the Clock.
82
- # See #tick.
83
- #
84
- # TODO: sample only a few seconds in the past, instead of the
85
- # entire lifetime of the Clock.
86
- def framerate
87
- # below is same as: return @ticks / (lifetime / 1000.0)
88
- return 1000.0 * @ticks / lifetime()
89
- rescue ZeroDivisionError
90
- return 0
91
- end
92
-
93
- # Returns the number of milliseconds since you last called this method.
94
- #
95
- # You must call this method once per frame (i.e. per iteration of
96
- # your main loop) if you want to use the framerate monitoring and/or
97
- # framerate limiting features.
98
- #
99
- # Framerate monitoring allows you to check the framerate (frames per
100
- # second) with the #framerate method.
101
- #
102
- # Framerate limiting allows you to prevent the application from running
103
- # too fast (and using 100% of processor time) by pausing the program
104
- # very briefly each frame. The pause duration is calculated each frame
105
- # to maintain a constant framerate.
106
- #
107
- # Framerate limiting is only enabled if you have set the
108
- # #target_framerate= or #target_frametime=.
109
- # If you have done that, this method will automatically perform the
110
- # delay each time you call it.
111
- #
112
- # (Please note that no effort is made to correct a framerate
113
- # which is *slower* than the target framerate. Clock can't
114
- # make your code run faster, only slow it down if it is
115
- # running too fast.)
116
- def tick()
117
- passed = Clock.runtime() - @last_tick # how long since the last tick?
118
- if @target_frametime
119
- return Clock.delay(@target_frametime - passed) + passed
120
- end
121
- return passed
122
- ensure
123
- @last_tick = Clock.runtime()
124
- @ticks += 1
125
- end
126
-
127
- end # class Clock
128
- end #module Rubygame
27
+
28
+
29
+ # Clock provides class methods for tracking running time and delaying
30
+ # execution of the program for specified time periods. This is used to
31
+ # provide a consistent framerate, prevent the program from using
32
+ # all the processor time, etc.
33
+ #
34
+ # Clock also provides instance methods to make it convenient to
35
+ # monitor and limit application framerate. See #tick.
36
+ #
37
+ # An in-depth tutorial on using Clock is available. See
38
+ # doc/managing_framerate.rdoc[link:files/doc/managing_framerate_rdoc.html]
39
+ # in the Rubygame source distribution or in the online
40
+ # documentation.
41
+ #
42
+ class Clock
43
+
44
+ # The runtime when the Clock was initialized.
45
+ attr_reader :start
46
+
47
+ # The number of times #tick has been called.
48
+ attr_reader :ticks
49
+
50
+
51
+ # Granularity used for framerate limiting delays in #tick.
52
+ # You can calibrate this easily with #calibrate.
53
+ # See also #tick and Clock.delay.
54
+ # (Non-negative integer. Default: 12.)
55
+ attr_accessor :granularity
56
+
57
+ # Whether to try to let other ruby threads run during framerate
58
+ # limiting delays in #tick. See #tick and Clock.delay.
59
+ # (true or false. Default: false.)
60
+ attr_accessor :nice
61
+
62
+
63
+ # Create a new Clock instance.
64
+ def initialize()
65
+ @start = self.class.runtime()
66
+ @last_tick = nil
67
+ @ticks = 0
68
+
69
+ @target_frametime = nil
70
+
71
+ # Frametime samples for framerate calculation
72
+ @samples = []
73
+ @max_samples = 20
74
+
75
+ @granularity = 12
76
+ @nice = false
77
+
78
+ # Should #tick return a ClockTicked event?
79
+ @tick_events = false
80
+
81
+ # Cache for past tick events with specific ms values
82
+ @tick_cache = {}
83
+
84
+ yield self if block_given?
85
+ end
86
+
87
+
88
+ # Calibrate some Clock settings to match the current computer.
89
+ # This improves efficiency and minimizes CPU usage without
90
+ # reducing accuracy.
91
+ #
92
+ # As of Rubygame 2.5, this method calibrates @granularity. See
93
+ # #tick and Clock.delay for more information about the effect of
94
+ # setting granularity. In future versions of Rubygame, this
95
+ # method may also calibrate additional Clock attributes.
96
+ #
97
+ # By default, the calibration takes a maximum of 0.5 seconds to
98
+ # complete. You can specify a different maximum length by passing
99
+ # a different value for +max_time+. In future versions of
100
+ # Rubygame, calibration may take less than max_time, but will
101
+ # not take more. Also, the default max_time may be lowered in
102
+ # future versions, but will not be raised.
103
+ #
104
+ # You usually only need to call this once, after you create the
105
+ # Clock instance at the start of your application. You should not
106
+ # run any other ruby threads at the same time, as doing so will
107
+ # skew the calibration.
108
+ #
109
+ #--
110
+ #
111
+ # I'm not 100% sure that this is a valid way to measure
112
+ # granularity, or that the granularity of ruby sleep is
113
+ # always the same as that of SDL_Delay. But it can be
114
+ # improved later if needed...
115
+ #
116
+ #++
117
+ def calibrate( max_time = 0.5 )
118
+ samples = []
119
+
120
+ end_time = Time.now + max_time
121
+
122
+ while( Time.now < end_time )
123
+ t = Time.now
124
+ sleep 0.01
125
+ samples << (Time.now - t - 0.01)
126
+ end
127
+
128
+ average = samples.inject{|sum,n| sum + n} / samples.length
129
+
130
+ # convert to ms, add some padding
131
+ gran = (average * 1000).to_i + 1
132
+
133
+ @granularity = gran
134
+
135
+ return nil
136
+ end
137
+
138
+
139
+ # Enable tick events, so that #tick will return a ClockTicked
140
+ # instance instead of a number of milliseconds.
141
+ #
142
+ # This option is available starting in Rubygame 2.5, and will
143
+ # become the default in Rubygame 3.0.
144
+ #
145
+ def enable_tick_events
146
+ @tick_events = true
147
+ end
148
+
149
+
150
+ # Returns the current target frametime (milliseconds/frame),
151
+ # or nil if there is no target.
152
+ #
153
+ # This is another way to access #target_framerate.
154
+ # Same as: 1000.0 / #target_framerate
155
+ #
156
+ def target_frametime
157
+ @target_frametime
158
+ end
159
+
160
+
161
+ # Sets the target milliseconds per frame to +frametime+.
162
+ # If +frametime+ is nil, the target is unset, and #tick
163
+ # will no longer apply any delay.
164
+ #
165
+ # This is another way to access #target_framerate.
166
+ # Same as: #target_framerate = 1000.0 / frametime
167
+ #
168
+ def target_frametime=( frametime )
169
+ @target_frametime = frametime
170
+ end
171
+
172
+
173
+ # Returns the current target framerate (frames/second),
174
+ # or nil if there is no target.
175
+ #
176
+ # This is another to access #target_frametime.
177
+ # Same as: 1000.0 / #target_frametime
178
+ #
179
+ def target_framerate
180
+ if @target_frametime
181
+ 1000.0 / @target_frametime
182
+ else
183
+ nil
184
+ end
185
+ rescue ZeroDivisionError
186
+ return nil
187
+ end
188
+
189
+
190
+ # Sets the target number of frames per second to +framerate+.
191
+ # If +framerate+ is nil, the target is unset, and #tick
192
+ # will no longer apply any delay.
193
+ #
194
+ # This is another way to access #target_frametime.
195
+ # Same as: #target_frametime = 1000.0 / framerate
196
+ #
197
+ def target_framerate=( framerate )
198
+ if framerate
199
+ @target_frametime = 1000.0 / framerate
200
+ else
201
+ @target_frametime = nil
202
+ end
203
+ rescue ZeroDivisionError
204
+ @target_frametime = nil
205
+ end
206
+
207
+
208
+ # call-seq:
209
+ # lifetime -> Integer
210
+ #
211
+ # Returns time in milliseconds since this Clock instance was created.
212
+ #
213
+ def lifetime
214
+ self.class.runtime() - @start
215
+ end
216
+
217
+
218
+ # call-seq:
219
+ # framerate -> Float
220
+ #
221
+ # Return the actual framerate (frames per second) recorded by the
222
+ # Clock. See #tick.
223
+ #
224
+ def framerate
225
+ 1000.0 * @samples.length / @samples.inject(0){|sum, n| sum + n}
226
+ rescue ZeroDivisionError
227
+ 0.0
228
+ end
229
+
230
+
231
+ # call-seq:
232
+ # frametime -> Float
233
+ #
234
+ # Return the actual frametime (milliseconds per frame) recorded by
235
+ # the Clock. See #tick.
236
+ #
237
+ def frametime
238
+ @samples.inject(0){|sum, n| sum + n} / (@samples.length)
239
+ rescue ZeroDivisionError
240
+ 0.0
241
+ end
242
+
243
+
244
+ # Returns the number of milliseconds since you last called this
245
+ # method. Or, if you have called #enable_tick_events, this returns
246
+ # a ClockTicked event representing the time since you last called
247
+ # this method. (ClockTicked was added in Rubygame 2.5, and will
248
+ # become the default and only option in Rubygame 3.0.)
249
+ #
250
+ # You must call this method once per frame (i.e. per iteration
251
+ # of your main loop) if you want to use the framerate monitoring
252
+ # and/or framerate limiting features.
253
+ #
254
+ # Framerate monitoring allows you to check the #framerate (frames
255
+ # per second) or #frametime (milliseconds per frame) of your game.
256
+ #
257
+ # Framerate limiting allows you to prevent the application from
258
+ # running too fast (and using 100% of processor time) by pausing
259
+ # the program very briefly each frame. The pause duration is
260
+ # calculated each frame to maintain a stable framerate.
261
+ #
262
+ # Framerate limiting is only enabled if you have set the
263
+ # #target_framerate= or #target_frametime=. If you have done that,
264
+ # this method will automatically perform the delay each time you
265
+ # call it.
266
+ #
267
+ # There are two other attributes which affect framerate limiting,
268
+ # #granularity and #nice. These are passed as parameters to
269
+ # Clock.delay for the brief pause each frame. See Clock.delay for
270
+ # the effects of those parameters on CPU usage and threading.
271
+ #
272
+ # (Please note that no effort is made to correct a framerate which
273
+ # is *slower* than the target framerate. Clock can't make your
274
+ # code run faster, only slow it down if it is running too fast.)
275
+ #
276
+ def tick()
277
+
278
+ # how long since the last tick?
279
+ passed = 0
280
+ if @last_tick
281
+ passed += self.class.runtime() - @last_tick
282
+ end
283
+
284
+ if @target_frametime
285
+ extra = @target_frametime - passed
286
+ if( extra > 0 )
287
+ passed += self.class.delay( extra, @granularity, @nice )
288
+ end
289
+ end
290
+
291
+ if @tick_events
292
+ return (@tick_cache[passed] or
293
+ (@tick_cache[passed] =
294
+ Rubygame::Events::ClockTicked.new( passed ) ))
295
+ else
296
+ return passed
297
+ end
298
+
299
+ ensure
300
+ @last_tick = self.class.runtime()
301
+ @ticks += 1
302
+
303
+ # Save the frametime for framerate calculation
304
+ @samples.push(passed)
305
+ @samples.shift if @samples.length > @max_samples
306
+ end
307
+
308
+ end
309
+
310
+ end