chingu 0.5.5.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. data.tar.gz.sig +0 -0
  2. data/History.txt +21 -0
  3. data/LICENSE +504 -0
  4. data/Manifest.txt +72 -0
  5. data/README.rdoc +588 -0
  6. data/Rakefile +19 -0
  7. data/benchmarks/README.txt +1 -0
  8. data/benchmarks/benchmark.rb +6 -0
  9. data/benchmarks/benchmark3.rb +23 -0
  10. data/benchmarks/benchmark4.rb +71 -0
  11. data/benchmarks/benchmark5.rb +91 -0
  12. data/benchmarks/benchmark6.rb +23 -0
  13. data/benchmarks/meta_benchmark.rb +67 -0
  14. data/benchmarks/meta_benchmark2.rb +39 -0
  15. data/chingu.gemspec +34 -0
  16. data/examples/example1.rb +37 -0
  17. data/examples/example10.rb +75 -0
  18. data/examples/example11.rb +51 -0
  19. data/examples/example12.rb +67 -0
  20. data/examples/example2.rb +115 -0
  21. data/examples/example3.rb +40 -0
  22. data/examples/example4.rb +175 -0
  23. data/examples/example5.rb +107 -0
  24. data/examples/example6.rb +57 -0
  25. data/examples/example7.rb +133 -0
  26. data/examples/example8.rb +109 -0
  27. data/examples/example9.rb +106 -0
  28. data/examples/media/Parallax-scroll-example-layer-0.png +0 -0
  29. data/examples/media/Parallax-scroll-example-layer-1.png +0 -0
  30. data/examples/media/Parallax-scroll-example-layer-2.png +0 -0
  31. data/examples/media/Parallax-scroll-example-layer-3.png +0 -0
  32. data/examples/media/background1.png +0 -0
  33. data/examples/media/fire_bullet.png +0 -0
  34. data/examples/media/fireball.png +0 -0
  35. data/examples/media/particle.png +0 -0
  36. data/examples/media/ruby.png +0 -0
  37. data/examples/media/spaceship.png +0 -0
  38. data/examples/media/stickfigure.bmp +0 -0
  39. data/examples/media/stickfigure.png +0 -0
  40. data/examples/media/video_games.png +0 -0
  41. data/lib/chingu.rb +32 -0
  42. data/lib/chingu/actor.rb +17 -0
  43. data/lib/chingu/animation.rb +142 -0
  44. data/lib/chingu/assets.rb +64 -0
  45. data/lib/chingu/basic_game_object.rb +132 -0
  46. data/lib/chingu/core_extensions.rb +53 -0
  47. data/lib/chingu/effects.rb +36 -0
  48. data/lib/chingu/fpscounter.rb +62 -0
  49. data/lib/chingu/game_object.rb +127 -0
  50. data/lib/chingu/game_object_list.rb +91 -0
  51. data/lib/chingu/game_state.rb +137 -0
  52. data/lib/chingu/game_state_manager.rb +284 -0
  53. data/lib/chingu/game_states/debug.rb +65 -0
  54. data/lib/chingu/game_states/fade_to.rb +91 -0
  55. data/lib/chingu/game_states/pause.rb +57 -0
  56. data/lib/chingu/gfx_helpers.rb +89 -0
  57. data/lib/chingu/helpers.rb +166 -0
  58. data/lib/chingu/inflector.rb +34 -0
  59. data/lib/chingu/input.rb +100 -0
  60. data/lib/chingu/named_resource.rb +254 -0
  61. data/lib/chingu/parallax.rb +83 -0
  62. data/lib/chingu/particle.rb +21 -0
  63. data/lib/chingu/rect.rb +612 -0
  64. data/lib/chingu/require_all.rb +133 -0
  65. data/lib/chingu/text.rb +56 -0
  66. data/lib/chingu/traits/collision_detection.rb +172 -0
  67. data/lib/chingu/traits/effect.rb +113 -0
  68. data/lib/chingu/traits/input.rb +38 -0
  69. data/lib/chingu/traits/retrofy.rb +53 -0
  70. data/lib/chingu/traits/rotation_center.rb +84 -0
  71. data/lib/chingu/traits/timer.rb +90 -0
  72. data/lib/chingu/traits/velocity.rb +67 -0
  73. data/lib/chingu/window.rb +170 -0
  74. metadata +162 -0
  75. metadata.gz.sig +1 -0
@@ -0,0 +1,83 @@
1
+ #
2
+ # Class for simple parallaxscrolling
3
+ # See: http://en.wikipedia.org/wiki/Parallax_scrolling
4
+ #
5
+ module Chingu
6
+ class Parallax < Chingu::GameObject
7
+ attr_reader :backgrounds
8
+
9
+ #
10
+ # Options (in hash-format):
11
+ #
12
+ # repeat: [true|false] When one background ends within the screen, repeat/loop it
13
+ #
14
+ def initialize(options)
15
+ super(options)
16
+ @repeat = options[:repeat] || true
17
+ @backgrounds = Array.new
18
+ end
19
+
20
+ #
21
+ # Add one background, either an ParallaxBackground-object or a Hash of options to create one
22
+ # You can also add new backgrounds with the shortcut "<<":
23
+ # @parallax << {:image => "landscape.png", :damping => 1}
24
+ #
25
+ def add_background(arg)
26
+ @backgrounds << (arg.is_a?(ParallaxBackground) ? arg : ParallaxBackground.new(arg))
27
+ end
28
+ alias << add_background
29
+
30
+ #
31
+ # TODO: make use of $window.milliseconds_since_last_update here!
32
+ #
33
+ def update
34
+ @backgrounds.each do |background|
35
+ background.x = -@x / background.damping
36
+ background.y = @y / background.damping
37
+
38
+ # This is the magic that repeats the background to the left and right
39
+ background.x -= background.image.width while background.x > 0
40
+ end
41
+ end
42
+
43
+ #
44
+ # Draw
45
+ #
46
+ def draw
47
+ @backgrounds.each do |background|
48
+ background.draw
49
+
50
+ save_x = background.x
51
+
52
+ ## If background lands inside our screen, repeat it
53
+ while (background.x + background.image.width) < $window.width
54
+ background.x += background.image.width
55
+ background.draw
56
+ end
57
+
58
+ background.x = save_x
59
+ end
60
+ self
61
+ end
62
+ end
63
+
64
+ #
65
+ # One background item
66
+ #
67
+ class ParallaxBackground < Chingu::GameObject
68
+ @@zorder_counter = 0
69
+ attr_reader :damping
70
+
71
+ def initialize(options)
72
+ ## No auto update/draw, the parentclass Parallax takes care of that!
73
+ options.merge!(:draw => false, :update => false)
74
+
75
+ # If no zorder is given, use a global incrementing counter. First added, furthest behind when drawn.
76
+ options.merge!(:zorder => (@@zorder_counter+=1)) if options[:zorder].nil?
77
+
78
+ super(options)
79
+
80
+ @damping = options[:damping] || 10
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,21 @@
1
+ #
2
+ # Our basic particle class, basicly just a GameObject with trait "effect"
3
+ #
4
+ # TODO: expand on this further, as it is now it doesn't add much.
5
+ #
6
+ module Chingu
7
+ class Particle < Chingu::GameObject
8
+ has_trait :effect
9
+
10
+ def initialize(options)
11
+ super({:mode => :additive}.merge(options))
12
+ @animation = options[:animation] || nil
13
+ end
14
+
15
+ def update
16
+ super
17
+ self.image = @animation.next! if @animation
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,612 @@
1
+ #--
2
+ # Rubygame -- Ruby code and bindings to SDL to facilitate game creation
3
+ # Copyright (C) 2004-2007 John Croisant
4
+ #
5
+ # This library is free software; you can redistribute it and/or
6
+ # modify it under the terms of the GNU Lesser General Public
7
+ # License as published by the Free Software Foundation; either
8
+ # version 2.1 of the License, or (at your option) any later version.
9
+ #
10
+ # This library is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
+ # Lesser General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU Lesser General Public
16
+ # License along with this library; if not, write to the Free Software
17
+ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
+ #++
19
+
20
+ #--
21
+ # Table of Contents:
22
+ #
23
+ # class Rect
24
+ # GENERAL:
25
+ # initialize
26
+ # new_from_object
27
+ # to_s
28
+ # to_a, to_ary
29
+ # []
30
+ # ATTRIBUTES:
31
+ # x, y, w, h [<- accessors]
32
+ # width, height, size
33
+ # left, top, right, bottom
34
+ # center, centerx, centery
35
+ # topleft, topright
36
+ # bottomleft, bottomright
37
+ # midleft, midtop, midright, midbottom
38
+ # UTILITY METHODS:
39
+ # clamp, clamp!
40
+ # clip, clip!
41
+ # collide_hash, collide_hash_all
42
+ # collide_array, collide_array_all
43
+ # collide_point?
44
+ # collide_rect?
45
+ # contain?
46
+ # inflate, inflate!
47
+ # move, move!
48
+ # normalize, normalize!
49
+ # union, union!
50
+ # union_all, union_all!
51
+ #
52
+ # class Surface
53
+ # make_rect
54
+ #
55
+ #++
56
+
57
+ module Chingu
58
+
59
+ # A Rect is a representation of a rectangle, with four core attributes
60
+ # (x offset, y offset, width, and height) and a variety of functions
61
+ # for manipulating and accessing these attributes.
62
+ #
63
+ # Like all coordinates in Rubygame (and its base library, SDL), x and y
64
+ # offsets are measured from the top-left corner of the screen, with greater
65
+ # y offsets being lower. Thus, specifying the x and y offsets of the Rect
66
+ # is equivalent to setting the location of its top-left corner.
67
+ #
68
+ # In Rubygame, Rects are used for collision detection and describing
69
+ # the area of a Surface to operate on.
70
+ class Rect < Array
71
+
72
+ #--
73
+ # GENERAL
74
+ #++
75
+
76
+ # Create a new Rect, attempting to extract its own information from
77
+ # the given arguments. The arguments must fall into one of these cases:
78
+ #
79
+ # - 4 integers +(x, y, w, h)+.
80
+ # - 1 Rect or Array containing 4 integers +([x, y, w, h])+.
81
+ # - 2 Arrays containing 2 integers each +([x,y], [w,h])+.
82
+ # - 1 object with a +rect+ attribute which is a valid Rect object.
83
+ #
84
+ # All rect core attributes (x,y,w,h) must be integers.
85
+ #
86
+ def initialize(*argv)
87
+ case argv.length
88
+ when 1
89
+ if argv[0].kind_of? Array; super(argv[0])
90
+ elsif argv[0].respond_to? :rect; super(argv[0])
91
+ end
92
+ when 2
93
+ super(argv[0].concat(argv[1]))
94
+ when 4
95
+ super(argv)
96
+ end
97
+ return self
98
+ end
99
+
100
+ # Extract or generate a Rect from the given object, if possible, using the
101
+ # following process:
102
+ #
103
+ # 1. If it's a Rect already, return a duplicate Rect.
104
+ # 2. Elsif it's an Array with at least 4 values, make a Rect from it.
105
+ # 3. Elsif it has a +rect+ attribute., perform (1) and (2) on that.
106
+ # 4. Otherwise, raise TypeError.
107
+ #
108
+ # See also Surface#make_rect()
109
+ def Rect.new_from_object(object)
110
+ case(object)
111
+ when Rect
112
+ return object.dup
113
+ when Array
114
+ if object.length >= 4
115
+ return Rect.new(object)
116
+ else
117
+ raise(ArgumentError,"Array does not have enough indices to be made into a Rect (%d for 4)."%object.length )
118
+ end
119
+ else
120
+ begin
121
+ case(object.rect)
122
+ when Rect
123
+ return object.rect.dup
124
+ when Array
125
+ if object.rect.length >= 4
126
+ return Rect.new(object.rect)
127
+ else
128
+ raise(ArgumentError,"Array does not have enough indices to be made into a Rect (%d for 4)."%object.rect.length )
129
+ end
130
+ end # case object.rect
131
+ rescue NoMethodError # if no rect.rect
132
+ raise(TypeError,"Object must be a Rect or Array [x,y,w,h], or have an attribute called 'rect'. (Got %s instance.)"%object.class)
133
+ end
134
+ end # case object
135
+ end
136
+
137
+
138
+ # Print the Rect in the form "+#<Rect [x,y,w,h]>+"
139
+ def to_s; "#<Rect [%s,%s,%s,%s]>"%self; end
140
+
141
+ # Print the Rect in the form "+#<Rect:id [x,y,w,h]>+"
142
+ def inspect; "#<Rect:#{self.object_id} [%s,%s,%s,%s]>"%self; end
143
+
144
+ #--
145
+ # ATTRIBUTES
146
+ #++
147
+
148
+ # Returns self.at(0)
149
+ def x; return self.at(0); end
150
+ # Sets self[0] to +val+
151
+ def x=(val); self[0] = val; end
152
+
153
+ alias left x
154
+ alias left= x=;
155
+ alias l x
156
+ alias l= x=;
157
+
158
+ # Returns self.at(1)
159
+ def y; return self.at(1); end
160
+ # Sets self[1] to +val+
161
+ def y=(val); self[1] = val; end
162
+
163
+ alias top y
164
+ alias top= y=;
165
+ alias t y
166
+ alias t= y=;
167
+
168
+ # Returns self.at(2)
169
+ def w; return self.at(2); end
170
+ # Sets self[2] to +val+
171
+ def w=(val); self[2] = val; end
172
+
173
+ alias width w
174
+ alias width= w=;
175
+
176
+ # Returns self.at(3)
177
+ def h; return self.at(3); end
178
+ # Sets self[3] to +val+
179
+ def h=(val); self[3] = val; end
180
+
181
+ alias height h
182
+ alias height= h=;
183
+
184
+ # Return the width and height of the Rect.
185
+ def size; return self[2,2]; end
186
+
187
+ # Set the width and height of the Rect.
188
+ def size=(size)
189
+ raise ArgumentError, "Rect#size= takes an Array of form [width, height]." if size.size != 2
190
+ self[2,2] = size
191
+ size
192
+ end
193
+
194
+ # Return the x coordinate of the right side of the Rect.
195
+ def right; return self.at(0)+self.at(2); end
196
+
197
+ # Set the x coordinate of the right side of the Rect by translating the
198
+ # Rect (adjusting the x offset).
199
+ def right=(r); self[0] = r - self.at(2); return r; end
200
+
201
+ alias r right
202
+ alias r= right=;
203
+
204
+ # Return the y coordinate of the bottom side of the Rect.
205
+ def bottom; return self.at(1)+self.at(3); end
206
+
207
+ # Set the y coordinate of the bottom side of the Rect by translating the
208
+ # Rect (adjusting the y offset).
209
+ def bottom=(b); self[1] = b - self.at(3); return b; end
210
+
211
+ alias b bottom
212
+ alias b= bottom=;
213
+
214
+ # Return the x and y coordinates of the center of the Rect.
215
+ def center; return self.centerx, self.centery; end
216
+
217
+ # Set the x and y coordinates of the center of the Rect by translating the
218
+ # Rect (adjusting the x and y offsets).
219
+ def center=(center)
220
+ raise ArgumentError, "Rect#center= takes an Array of the form [x,y]." if center.size != 2
221
+ self.centerx, self.centery = center
222
+ center
223
+ end
224
+ alias c center
225
+ alias c= center=;
226
+
227
+ # Return the x coordinate of the center of the Rect
228
+ def centerx; return self.at(0)+(self.at(2).div(2)); end
229
+
230
+ # Set the x coordinate of the center of the Rect by translating the
231
+ # Rect (adjusting the x offset).
232
+ def centerx=(x); self[0] = x - (self.at(2).div(2)); return x; end
233
+
234
+ alias cx centerx
235
+ alias cx= centerx=;
236
+
237
+ # Return the y coordinate of the center of the Rect
238
+ def centery; return self.at(1)+(self.at(3).div(2)); end
239
+
240
+ # Set the y coordinate of the center of the Rect by translating the
241
+ # Rect (adjusting the y offset).
242
+ def centery=(y); self[1] = y- (self.at(3).div(2)); return y; end
243
+
244
+ alias cy centery
245
+ alias cy= centery=;
246
+
247
+ # Return the x and y coordinates of the top-left corner of the Rect
248
+ def topleft; return self[0,2].to_a; end
249
+
250
+ # Set the x and y coordinates of the top-left corner of the Rect by
251
+ # translating the Rect (adjusting the x and y offsets).
252
+ def topleft=(topleft)
253
+ raise ArgumentError, "Rect#topright= takes an Array of form [x, y]." if topleft.size != 2
254
+ self[0,2] = topleft
255
+ return topleft
256
+ end
257
+
258
+ alias tl topleft
259
+ alias tl= topleft=;
260
+
261
+ # Return the x and y coordinates of the top-right corner of the Rect
262
+ def topright; return self.right, self.at(1); end
263
+
264
+ # Set the x and y coordinates of the top-right corner of the Rect by
265
+ # translating the Rect (adjusting the x and y offsets).
266
+ def topright=(topright)
267
+ raise ArgumentError, "Rect#topright= takes an Array of form [x, y]." if topright.size != 2
268
+ self.right, self[1] = topright
269
+ return topright
270
+ end
271
+
272
+ alias tr topright
273
+ alias tr= topright=;
274
+
275
+ # Return the x and y coordinates of the bottom-left corner of the Rect
276
+ def bottomleft; return self.at(0), self.bottom; end
277
+
278
+ # Set the x and y coordinates of the bottom-left corner of the Rect by
279
+ # translating the Rect (adjusting the x and y offsets).
280
+ def bottomleft=(bottomleft)
281
+ raise ArgumentError, "Rect#bottomleft= takes an Array of form [x, y]." if bottomleft.size != 2
282
+ self[0], self.bottom = bottomleft
283
+ return bottomleft
284
+ end
285
+
286
+ alias bl bottomleft
287
+ alias bl= bottomleft=;
288
+
289
+ # Return the x and y coordinates of the bottom-right corner of the Rect
290
+ def bottomright; return self.right, self.bottom; end
291
+
292
+ # Set the x and y coordinates of the bottom-right corner of the Rect by
293
+ # translating the Rect (adjusting the x and y offsets).
294
+ def bottomright=(bottomright)
295
+ raise ArgumentError, "Rect#bottomright= takes an Array of form [x, y]." if bottomright.size != 2
296
+ self.right, self.bottom = bottomright
297
+ return bottomright
298
+ end
299
+
300
+ alias br bottomright
301
+ alias br= bottomright=;
302
+
303
+ # Return the x and y coordinates of the midpoint on the left side of the
304
+ # Rect.
305
+ def midleft; return self.at(0), self.centery; end
306
+
307
+ # Set the x and y coordinates of the midpoint on the left side of the Rect
308
+ # by translating the Rect (adjusting the x and y offsets).
309
+ def midleft=(midleft)
310
+ raise ArgumentError, "Rect#midleft= takes an Array of form [x, y]." if midleft.size != 2
311
+ self[0], self.centery = midleft
312
+ return midleft
313
+ end
314
+
315
+ alias ml midleft
316
+ alias ml= midleft=;
317
+
318
+ # Return the x and y coordinates of the midpoint on the left side of the
319
+ # Rect.
320
+ def midtop; return self.centerx, self.at(1); end
321
+
322
+ # Set the x and y coordinates of the midpoint on the top side of the Rect
323
+ # by translating the Rect (adjusting the x and y offsets).
324
+ def midtop=(midtop)
325
+ raise ArgumentError, "Rect#midtop= takes an Array of form [x, y]." if midtop.size != 2
326
+ self.centerx, self[1] = midtop
327
+ return midtop
328
+ end
329
+
330
+ alias mt midtop
331
+ alias mt= midtop=;
332
+
333
+ # Return the x and y coordinates of the midpoint on the left side of the
334
+ # Rect.
335
+ def midright; return self.right, self.centery; end
336
+
337
+ # Set the x and y coordinates of the midpoint on the right side of the Rect
338
+ # by translating the Rect (adjusting the x and y offsets).
339
+ def midright=(midright)
340
+ raise ArgumentError, "Rect#midright= takes an Array of form [x, y]." if midright.size != 2
341
+ self.right, self.centery = midright
342
+ return midright
343
+ end
344
+
345
+ alias mr midright
346
+ alias mr= midright=;
347
+
348
+ # Return the x and y coordinates of the midpoint on the left side of the
349
+ # Rect.
350
+ def midbottom; return self.centerx, self.bottom; end
351
+
352
+ # Set the x and y coordinates of the midpoint on the bottom side of the
353
+ # Rect by translating the Rect (adjusting the x and y offsets).
354
+ def midbottom=(midbottom)
355
+ raise ArgumentError, "Rect#midbottom= takes an Array of form [x, y]." if midbottom.size != 2
356
+ self.centerx, self.bottom = midbottom
357
+ return midbottom
358
+ end
359
+
360
+ alias mb midbottom
361
+ alias mb= midbottom=;
362
+
363
+ #--
364
+ # UTILITY METHODS
365
+ #++
366
+
367
+
368
+ # As #clamp!, but the original caller is not changed.
369
+ def clamp(rect)
370
+ self.dup.clamp!(rect)
371
+ end
372
+
373
+ # Translate the calling Rect to be entirely inside the given Rect. If
374
+ # the caller is too large along either axis to fit in the given rect,
375
+ # it is centered with respect to the given rect, along that axis.
376
+ def clamp!(rect)
377
+ nself = self.normalize
378
+ rect = Rect.new_from_object(rect)
379
+ #If self is inside given, there is no need to move self
380
+ unless rect.contain?(nself)
381
+
382
+ #If self is too wide:
383
+ if nself.at(2) >= rect.at(2)
384
+ self[0] = rect.centerx - nself.at(2).div(2)
385
+ #Else self is not too wide
386
+ else
387
+ #If self is to the left of arg
388
+ if nself.at(0) < rect.at(0)
389
+ self[0] = rect.at(0)
390
+ #If self is to the right of arg
391
+ elsif nself.right > rect.right
392
+ self[0] = rect.right - nself.at(2)
393
+ #Otherwise, leave x alone
394
+ end
395
+ end
396
+
397
+ #If self is too tall:
398
+ if nself.at(3) >= rect.at(3)
399
+ self[1] = rect.centery - nself.at(3).div(2)
400
+ #Else self is not too tall
401
+ else
402
+ #If self is above arg
403
+ if nself.at(1) < rect.at(1)
404
+ self[1] = rect.at(1)
405
+ #If self below arg
406
+ elsif nself.bottom > rect.bottom
407
+ self[1] = rect.bottom - nself.at(3)
408
+ #Otherwise, leave y alone
409
+ end
410
+ end
411
+ end
412
+ return self
413
+ end
414
+
415
+ # As #clip!, but the original caller is not changed.
416
+ def clip(rect)
417
+ self.dup.clip!(rect)
418
+ end
419
+
420
+ # Crop the calling Rect to be entirely inside the given Rect. If the
421
+ # caller does not intersect the given Rect at all, its width and height
422
+ # are set to zero, but its x and y offsets are not changed.
423
+ #
424
+ # As a side effect, the Rect is normalized.
425
+ def clip!(rect)
426
+ nself = self.normalize
427
+ other = Rect.new_from_object(rect).normalize!
428
+ if self.collide_rect?(other)
429
+ self[0] = [nself.at(0), other.at(0)].max
430
+ self[1] = [nself.at(1), other.at(1)].max
431
+ self[2] = [nself.right, other.right].min - self.at(0)
432
+ self[3] = [nself.bottom, other.bottom].min - self.at(1)
433
+ else #if they do not intersect at all:
434
+ self[0], self[1] = nself.topleft
435
+ self[2], self[3] = 0, 0
436
+ end
437
+ return self
438
+ end
439
+
440
+ # Iterate through all key/value pairs in the given hash table, and
441
+ # return the first pair whose value is a Rect that collides with the
442
+ # caller.
443
+ #
444
+ # Because a hash table is unordered, you should not expect any
445
+ # particular Rect to be returned first.
446
+ def collide_hash(hash_rects)
447
+ hash_rects.each { |key,value|
448
+ if value.collide_rect?+(self); return [key,value]; end
449
+ }
450
+ return nil
451
+ end
452
+
453
+ # Iterate through all key/value pairs in the given hash table, and
454
+ # return an Array of every pair whose value is a Rect that collides
455
+ # the caller.
456
+ #
457
+ # Because a hash table is unordered, you should not expect the returned
458
+ # pairs to be in any particular order.
459
+ def collide_hash_all(hash_rects)
460
+ hash_rects.select { |key,value|
461
+ value.collide_rect?+(self)
462
+ }
463
+ end
464
+
465
+ # Iterate through all elements in the given Array, and return
466
+ # the *index* of the first element which is a Rect that collides with
467
+ # the caller.
468
+ def collide_array(array_rects)
469
+ for i in (0...(array_rects.length))
470
+ if array_rects[i].collide_rect?(self)
471
+ return i
472
+ end
473
+ end
474
+ return nil
475
+ end
476
+
477
+ # Iterate through all elements in the given Array, and return
478
+ # an Array containing the *indices* of every element that is a Rect
479
+ # that collides with the caller.
480
+ def collide_array_all(array_rects)
481
+ indexes = []
482
+ for i in (0...(array_rects.length))
483
+ if array_rects[i].collide_rect?(self)
484
+ indexes += [i]
485
+ end
486
+ end
487
+ return indexes
488
+ end
489
+
490
+ # True if the point is inside (including on the border) of the caller.
491
+ # If you have Array of coordinates, you can use collide_point?(*coords).
492
+ def collide_point?(x,y)
493
+ nself = normalize()
494
+ x.between?(nself.left,nself.right) && y.between?(nself.top,nself.bottom)
495
+ end
496
+
497
+ # True if the caller and the given Rect overlap (or touch) at all.
498
+ def collide_rect?(rect)
499
+ nself = self.normalize
500
+ rect = Rect.new_from_object(rect).normalize!
501
+ return ((nself.l >= rect.l && nself.l <= rect.r) or (rect.l >= nself.l && rect.l <= nself.r)) &&
502
+ ((nself.t >= rect.t && nself.t <= rect.b) or (rect.t >= nself.t && rect.t <= nself.b))
503
+ end
504
+
505
+ # True if the given Rect is totally within the caller. Borders may
506
+ # overlap.
507
+ def contain?(rect)
508
+ nself = self.normalize
509
+ rect = Rect.new_from_object(rect).normalize!
510
+ return (nself.left <= rect.left and rect.right <= nself.right and
511
+ nself.top <= rect.top and rect.bottom <= nself.bottom)
512
+ end
513
+
514
+ # As #inflate!, but the original caller is not changed.
515
+ def inflate(x,y)
516
+ return self.class.new(self.at(0) - x.div(2),
517
+ self.at(1) - y.div(2),
518
+ self.at(2) + x,
519
+ self.at(3) + y)
520
+ end
521
+
522
+ # Increase the Rect's size is the x and y directions, while keeping the
523
+ # same center point. For best results, expand by an even number.
524
+ # X and y inflation can be given as an Array or as separate values.
525
+ def inflate!(x,y)
526
+ self[0] -= x.div(2)
527
+ self[1] -= y.div(2)
528
+ self[2] += x
529
+ self[3] += y
530
+ return self
531
+ end
532
+
533
+ # As #move!, but the original caller is not changed.
534
+ def move(x,y)
535
+ self.dup.move!(x,y)
536
+ end
537
+
538
+ # Translate the Rect by the given amounts in the x and y directions.
539
+ # Positive values are rightward for x and downward for y.
540
+ # X and y movement can be given as an Array or as separate values.
541
+ def move!(x,y)
542
+ self[0]+=x; self[1]+=y
543
+ return self
544
+ end
545
+
546
+ # As #normalize!, but the original caller is not changed.
547
+ def normalize
548
+ self.dup.normalize!()
549
+ end
550
+
551
+ # Fix Rects that have negative width or height, without changing the
552
+ # area it represents. Has no effect on Rects with non-negative width
553
+ # and height. Some Rect methods will automatically normalize the Rect.
554
+ def normalize!
555
+ if self.at(2) < 0
556
+ self[0], self[2] = self.at(0)+self.at(2), -self.at(2)
557
+ end
558
+ if self.at(3) < 0
559
+ self[1], self[3] = self.at(1)+self.at(3), -self.at(3)
560
+ end
561
+ self
562
+ end
563
+
564
+ # As #union!, but the original caller is not changed.
565
+ def union(rect)
566
+ self.dup.union!(rect)
567
+ end
568
+
569
+ # Expand the caller to also cover the given Rect. The Rect is still a
570
+ # rectangle, so it may also cover areas that neither of the original
571
+ # Rects did, for example areas between the two Rects.
572
+ def union!(rect)
573
+ self.normalize!
574
+ rleft, rtop = self.topleft
575
+ rright, rbottom = self.bottomright
576
+ r2 = Rect.new_from_object(rect).normalize!
577
+
578
+ rleft = [rleft, r2.left].min
579
+ rtop = [rtop, r2.top].min
580
+ rright = [rright, r2.right].max
581
+ rbottom = [rbottom, r2.bottom].max
582
+
583
+ self[0,4] = rleft, rtop, rright - rleft, rbottom - rtop
584
+ return self
585
+ end
586
+
587
+ # As #union_all!, but the original caller is not changed.
588
+ def union_all(array_rects)
589
+ self.dup.union_all!(array_rects)
590
+ end
591
+
592
+ # Expand the caller to cover all of the given Rects. See also #union!
593
+ def union_all!(array_rects)
594
+ array_rects.each do |r|
595
+ self.union!(r)
596
+ end
597
+ return self
598
+ end
599
+
600
+
601
+ end # class Rect
602
+
603
+
604
+ class Surface
605
+ # Return a Rect with the same width and height as the Surface, positioned
606
+ # at (0,0).
607
+ def make_rect()
608
+ return Rect.new(0,0,self.width,self.height)
609
+ end
610
+ end
611
+
612
+ end # module Rubygame