Class: Rect

Inherits:
Array show all
Includes:
MinMaxHelpers
Defined in:
lib/gamebox/lib/rect.rb

Overview

A Rect is a representation of a rectangle, with four core attributes (x offset, y offset, width, and height) and a variety of functions for manipulating and accessing these attributes.

Like all coordinates in Rubygame (and its base library, SDL), x and y offsets are measured from the top-left corner of the screen, with greater y offsets being lower. Thus, specifying the x and y offsets of the Rect is equivalent to setting the location of its top-left corner.

In Rubygame, Rects are used for collision detection and describing the area of a Surface to operate on.

Class Method Summary collapse

Instance Method Summary collapse

Methods included from MinMaxHelpers

#max, #min

Methods inherited from Array

wrap

Constructor Details

#initialize(*argv) ⇒ Rect

Create a new Rect, attempting to extract its own information from the given arguments. The arguments must fall into one of these cases:

- 4 integers +(x, y, w, h)+.
- 1 Rect or Array containing 4 integers +([x, y, w, h])+.
- 2 Arrays containing 2 integers each +([x,y], [w,h])+.
- 1 object with a +rect+ attribute which is a valid Rect object.

All rect core attributes (x,y,w,h) must be integers.



87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/gamebox/lib/rect.rb', line 87

def initialize(*argv)
  case argv.length
  when 1
    if argv[0].kind_of? Array; super(argv[0])
    elsif argv[0].respond_to? :rect; super(argv[0])
    end
  when 2
    super(argv[0].concat(argv[1]))
  when 4
    super(argv)
  end
  return self
end

Class Method Details

.new_from_object(object) ⇒ Object

Extract or generate a Rect from the given object, if possible, using the following process:

1. If it's a Rect already, return a duplicate Rect.
2. Elsif it's an Array with at least 4 values, make a Rect from it.
3. Elsif it has a +rect+ attribute., perform (1) and (2) on that.
4. Otherwise, raise TypeError.

See also Surface#make_rect()



110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# File 'lib/gamebox/lib/rect.rb', line 110

def Rect.new_from_object(object)
  case(object)
  when Rect
    return object.dup
  when Array 
    if object.length >= 4
      return Rect.new(object)
    else
      raise(ArgumentError,"Array does not have enough indices to be made into a Rect (%d for 4)."%object.length )
    end
  else
    begin
      case(object.rect)
      when Rect
        return object.rect.dup
      when Array
        if object.rect.length >= 4
          return Rect.new(object.rect)
        else
          raise(ArgumentError,"Array does not have enough indices to be made into a Rect (%d for 4)."%object.rect.length )
        end
      end        # case object.rect
    rescue NoMethodError # if no rect.rect
      raise(TypeError,"Object must be a Rect or Array [x,y,w,h], or have an attribute called 'rect'. (Got %s instance.)"%object.class)
    end
  end # case object
end

Instance Method Details

#areaObject

calculate the area of the Rect



602
603
604
# File 'lib/gamebox/lib/rect.rb', line 602

def area
  w * h
end

#bottomObject Also known as: b

Return the y coordinate of the bottom side of the Rect.



207
# File 'lib/gamebox/lib/rect.rb', line 207

def bottom; return self[1]+self[3]; end

#bottom=(b) ⇒ Object Also known as: b=

Set the y coordinate of the bottom side of the Rect by translating the Rect (adjusting the y offset).



211
# File 'lib/gamebox/lib/rect.rb', line 211

def bottom=(b); self[1] = b - self[3]; return b; end

#bottomleftObject Also known as: bl

Return the x and y coordinates of the bottom-left corner of the Rect



278
# File 'lib/gamebox/lib/rect.rb', line 278

def bottomleft; return self[0], self.bottom; end

#bottomleft=(bottomleft) ⇒ Object Also known as: bl=

Set the x and y coordinates of the bottom-left corner of the Rect by translating the Rect (adjusting the x and y offsets).

Raises:

  • (ArgumentError)


282
283
284
285
286
# File 'lib/gamebox/lib/rect.rb', line 282

def bottomleft=(bottomleft)
  raise ArgumentError, "Rect#bottomleft= takes an Array of form [x, y]." if bottomleft.size != 2
  self[0], self.bottom = bottomleft
  return bottomleft
end

#bottomrightObject Also known as: br

Return the x and y coordinates of the bottom-right corner of the Rect



292
# File 'lib/gamebox/lib/rect.rb', line 292

def bottomright; return self.right, self.bottom; end

#bottomright=(bottomright) ⇒ Object Also known as: br=

Set the x and y coordinates of the bottom-right corner of the Rect by translating the Rect (adjusting the x and y offsets).

Raises:

  • (ArgumentError)


296
297
298
299
300
# File 'lib/gamebox/lib/rect.rb', line 296

def bottomright=(bottomright)
  raise ArgumentError, "Rect#bottomright= takes an Array of form [x, y]." if bottomright.size != 2
  self.right, self.bottom = bottomright
  return bottomright
end

#centerObject Also known as: c

Return the x and y coordinates of the center of the Rect.



217
# File 'lib/gamebox/lib/rect.rb', line 217

def center; return self.centerx, self.centery; end

#center=(center) ⇒ Object Also known as: c=

Set the x and y coordinates of the center of the Rect by translating the Rect (adjusting the x and y offsets).

Raises:

  • (ArgumentError)


221
222
223
224
225
# File 'lib/gamebox/lib/rect.rb', line 221

def center=(center)
    raise ArgumentError, "Rect#center= takes an Array of the form [x,y]." if center.size != 2
  self.centerx, self.centery = center
  center
end

#centerxObject Also known as: cx

Return the x coordinate of the center of the Rect



230
# File 'lib/gamebox/lib/rect.rb', line 230

def centerx; return self[0]+(self[2].div(2)); end

#centerx=(x) ⇒ Object Also known as: cx=

Set the x coordinate of the center of the Rect by translating the Rect (adjusting the x offset).



234
# File 'lib/gamebox/lib/rect.rb', line 234

def centerx=(x); self[0] = x - (self[2].div(2)); return x; end

#centeryObject Also known as: cy

Return the y coordinate of the center of the Rect



240
# File 'lib/gamebox/lib/rect.rb', line 240

def centery; return self[1]+(self[3].div(2)); end

#centery=(y) ⇒ Object Also known as: cy=

Set the y coordinate of the center of the Rect by translating the Rect (adjusting the y offset).



244
# File 'lib/gamebox/lib/rect.rb', line 244

def centery=(y); self[1] = y- (self[3].div(2)); return y; end

#clamp(rect) ⇒ Object

As #clamp!, but the original caller is not changed.



371
372
373
# File 'lib/gamebox/lib/rect.rb', line 371

def clamp(rect)
  self.dup.clamp!(rect)
end

#clamp!(rect) ⇒ Object

Translate the calling Rect to be entirely inside the given Rect. If the caller is too large along either axis to fit in the given rect, it is centered with respect to the given rect, along that axis.



378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
# File 'lib/gamebox/lib/rect.rb', line 378

def clamp!(rect)
  nself = self.normalize
  rect = Rect.new_from_object(rect)
  #If self is inside given, there is no need to move self
  unless rect.contain?(nself)

    #If self is too wide:
    if nself[2] >= rect[2]
      self[0] = rect.centerx - nself[2].div(2)
      #Else self is not too wide
    else
      #If self is to the left of arg
      if nself[0] < rect[0]
        self[0] = rect[0]
      #If self is to the right of arg
      elsif nself.right > rect.right
        self[0] = rect.right - nself[2]
      #Otherwise, leave x alone
      end
    end

    #If self is too tall:
    if nself[3] >= rect[3]
      self[1] = rect.centery - nself[3].div(2)
      #Else self is not too tall
    else
      #If self is above arg
      if nself[1] < rect[1]
        self[1] = rect[1]
      #If self below arg
      elsif nself.bottom > rect.bottom
        self[1] = rect.bottom - nself[3]
      #Otherwise, leave y alone
      end
    end
  end
  return self
end

#clip(rect) ⇒ Object

As #clip!, but the original caller is not changed.



418
419
420
# File 'lib/gamebox/lib/rect.rb', line 418

def clip(rect)
  self.dup.clip!(rect)
end

#clip!(rect) ⇒ Object

Crop the calling Rect to be entirely inside the given Rect. If the caller does not intersect the given Rect at all, its width and height are set to zero, but its x and y offsets are not changed.

As a side effect, the Rect is normalized.



427
428
429
430
431
432
433
434
435
436
437
438
439
440
# File 'lib/gamebox/lib/rect.rb', line 427

def clip!(rect)
  nself = self.normalize
  other = Rect.new_from_object(rect).normalize!
  if self.collide_rect?(other)
    self[0] = [nself[0], other[0]].max
    self[1] = [nself[1], other[1]].max
    self[2] = [nself.right, other.right].min - self[0]
    self[3] = [nself.bottom, other.bottom].min - self[1]
  else #if they do not intersect at all:
    self[0], self[1] = nself.topleft
    self[2], self[3] = 0, 0
  end
  return self
end

#collide_array(array_rects) ⇒ Object

Iterate through all elements in the given Array, and return the index of the first element which is a Rect that collides with the caller.



470
471
472
473
474
475
476
477
# File 'lib/gamebox/lib/rect.rb', line 470

def collide_array(array_rects)
  for i in (0...(array_rects.length))
    if array_rects[i].collide_rect?(self)
      return i
    end
  end
  return nil
end

#collide_array_all(array_rects) ⇒ Object

Iterate through all elements in the given Array, and return an Array containing the indices of every element that is a Rect that collides with the caller.



482
483
484
485
486
487
488
489
490
# File 'lib/gamebox/lib/rect.rb', line 482

def collide_array_all(array_rects)
  indexes = []
  for i in (0...(array_rects.length))
    if array_rects[i].collide_rect?(self)
      indexes += [i]
    end
  end
  return indexes
end

#collide_hash(hash_rects) ⇒ Object

Iterate through all key/value pairs in the given hash table, and return the first pair whose value is a Rect that collides with the caller.

Because a hash table is unordered, you should not expect any particular Rect to be returned first.



448
449
450
451
452
453
# File 'lib/gamebox/lib/rect.rb', line 448

def collide_hash(hash_rects)
  hash_rects.each { |key,value|
    if value.collide_rect?+(self); return [key,value]; end
  }
  return nil
end

#collide_hash_all(hash_rects) ⇒ Object

Iterate through all key/value pairs in the given hash table, and return an Array of every pair whose value is a Rect that collides the caller.

Because a hash table is unordered, you should not expect the returned pairs to be in any particular order.



461
462
463
464
465
# File 'lib/gamebox/lib/rect.rb', line 461

def collide_hash_all(hash_rects)
  hash_rects.select { |key,value|
    value.collide_rect?+(self)
  }
end

#collide_point?(x, y) ⇒ Boolean

True if the point is inside (including on the border) of the caller. If you have Array of coordinates, you can use collide_point?(*coords).

Returns:

  • (Boolean)


494
495
496
497
# File 'lib/gamebox/lib/rect.rb', line 494

def collide_point?(x,y)
  nself = normalize()
  x.between?(nself.left,nself.right) && y.between?(nself.top,nself.bottom)
end

#collide_rect?(rect) ⇒ Boolean

True if the caller and the given Rect overlap (or touch) at all.

Returns:

  • (Boolean)


500
501
502
503
504
# File 'lib/gamebox/lib/rect.rb', line 500

def collide_rect?(rect)
  rect = Rect.new_from_object(rect)
  ((l >= rect.l && l <= rect.r) or (rect.l >= l && rect.l <= r)) &&
  ((t >= rect.t && t <= rect.b) or (rect.t >= t && rect.t <= b))
end

#contain?(rect) ⇒ Boolean

True if the given Rect is totally within the caller. Borders may overlap.

Returns:

  • (Boolean)


508
509
510
511
512
513
# File 'lib/gamebox/lib/rect.rb', line 508

def contain?(rect)
  nself = self#.normalize
  rect = Rect.new_from_object(rect)#.normalize!
  return (nself.left <= rect.left and rect.right <= nself.right and
        nself.top <= rect.top and rect.bottom <= nself.bottom)
end

#expand_to_include!(rect) ⇒ Object



643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
# File 'lib/gamebox/lib/rect.rb', line 643

def expand_to_include!(rect)
  rleft = self.left
  rtop = self.top
  rright = self.right
  rbottom = self.bottom
  r2 = Rect.new_from_object(rect)

  rleft = min(rleft, r2.left)
  rtop = min(rtop, r2.top)
  rright = max(rright, r2.right)
  rbottom = max(rbottom, r2.bottom)

  self.x = rleft
  self.y = rtop
  self.w = rright - rleft
  self.h = rbottom - rtop
end

#hObject Also known as: height

Returns self



179
# File 'lib/gamebox/lib/rect.rb', line 179

def h; return self[3]; end

#h=(val) ⇒ Object Also known as: height=

Sets self to val



181
# File 'lib/gamebox/lib/rect.rb', line 181

def h=(val); self[3] = val; end

#inflate(x, y) ⇒ Object

As #inflate!, but the original caller is not changed.



516
517
518
519
520
521
# File 'lib/gamebox/lib/rect.rb', line 516

def inflate(x,y)
  return self.class.new(self[0] - x.div(2),
                        self[1] - y.div(2),
                        self[2] + x,
                        self[3] + y)
end

#inflate!(x, y) ⇒ Object

Increase the Rect’s size is the x and y directions, while keeping the same center point. For best results, expand by an even number. X and y inflation can be given as an Array or as separate values.



526
527
528
529
530
531
532
# File 'lib/gamebox/lib/rect.rb', line 526

def inflate!(x,y)
  self[0] -= x.div(2)
  self[1] -= y.div(2)
  self[2] += x
  self[3] += y
  return self
end

#inspectObject

Print the Rect in the form “+#<Rect:id [x,y,w,h]>+”



143
# File 'lib/gamebox/lib/rect.rb', line 143

def inspect; "#<Rect:#{self.object_id} [%s,%s,%s,%s]>"%self; end

#midbottomObject Also known as: mb

Return the x and y coordinates of the midpoint on the left side of the Rect.



352
# File 'lib/gamebox/lib/rect.rb', line 352

def midbottom; return self.centerx, self.bottom; end

#midbottom=(midbottom) ⇒ Object Also known as: mb=

Set the x and y coordinates of the midpoint on the bottom side of the Rect by translating the Rect (adjusting the x and y offsets).

Raises:

  • (ArgumentError)


356
357
358
359
360
# File 'lib/gamebox/lib/rect.rb', line 356

def midbottom=(midbottom)
    raise ArgumentError, "Rect#midbottom= takes an Array of form [x, y]." if midbottom.size != 2
  self.centerx, self.bottom = midbottom
  return midbottom
end

#midleftObject Also known as: ml

Return the x and y coordinates of the midpoint on the left side of the Rect.



307
# File 'lib/gamebox/lib/rect.rb', line 307

def midleft; return self[0], self.centery; end

#midleft=(midleft) ⇒ Object Also known as: ml=

Set the x and y coordinates of the midpoint on the left side of the Rect by translating the Rect (adjusting the x and y offsets).

Raises:

  • (ArgumentError)


311
312
313
314
315
# File 'lib/gamebox/lib/rect.rb', line 311

def midleft=(midleft)
    raise ArgumentError, "Rect#midleft= takes an Array of form [x, y]." if midleft.size != 2
  self[0], self.centery = midleft
  return midleft
end

#midrightObject Also known as: mr

Return the x and y coordinates of the midpoint on the left side of the Rect.



337
# File 'lib/gamebox/lib/rect.rb', line 337

def midright; return self.right, self.centery; end

#midright=(midright) ⇒ Object Also known as: mr=

Set the x and y coordinates of the midpoint on the right side of the Rect by translating the Rect (adjusting the x and y offsets).

Raises:

  • (ArgumentError)


341
342
343
344
345
# File 'lib/gamebox/lib/rect.rb', line 341

def midright=(midright)
    raise ArgumentError, "Rect#midright= takes an Array of form [x, y]." if midright.size != 2
  self.right, self.centery = midright
  return midright
end

#midtopObject Also known as: mt

Return the x and y coordinates of the midpoint on the left side of the Rect.



322
# File 'lib/gamebox/lib/rect.rb', line 322

def midtop; return self.centerx, self[1]; end

#midtop=(midtop) ⇒ Object Also known as: mt=

Set the x and y coordinates of the midpoint on the top side of the Rect by translating the Rect (adjusting the x and y offsets).

Raises:

  • (ArgumentError)


326
327
328
329
330
# File 'lib/gamebox/lib/rect.rb', line 326

def midtop=(midtop)
    raise ArgumentError, "Rect#midtop= takes an Array of form [x, y]." if midtop.size != 2
  self.centerx, self[1] = midtop
  return midtop
end

#move(x, y) ⇒ Object

As #move!, but the original caller is not changed.



535
536
537
# File 'lib/gamebox/lib/rect.rb', line 535

def move(x,y)
  self.dup.move!(x,y)
end

#move!(x, y) ⇒ Object

Translate the Rect by the given amounts in the x and y directions. Positive values are rightward for x and downward for y. X and y movement can be given as an Array or as separate values.



542
543
544
545
# File 'lib/gamebox/lib/rect.rb', line 542

def move!(x,y)
  self[0]+=x; self[1]+=y
  return self
end

#normalizeObject

As #normalize!, but the original caller is not changed.



548
549
550
# File 'lib/gamebox/lib/rect.rb', line 548

def normalize
  self.dup.normalize!()
end

#normalize!Object

Fix Rects that have negative width or height, without changing the area it represents. Has no effect on Rects with non-negative width and height. Some Rect methods will automatically normalize the Rect.



555
556
557
558
559
560
561
562
563
# File 'lib/gamebox/lib/rect.rb', line 555

def normalize!
  if self[2] < 0
    self[0], self[2] = self[0]+self[2], -self[2]
  end
  if self[3] < 0
    self[1], self[3] = self[1]+self[3], -self[3]
  end
  self
end

#refit_for!(rect_a, rect_b) ⇒ Object



661
662
663
664
665
# File 'lib/gamebox/lib/rect.rb', line 661

def refit_for!(rect_a, rect_b)
  self.zero_out!
  self.expand_to_include! rect_a
  self.expand_to_include! rect_b
end

#rightObject Also known as: r

Return the x coordinate of the right side of the Rect.



197
# File 'lib/gamebox/lib/rect.rb', line 197

def right; return self[0]+self[2]; end

#right=(r) ⇒ Object Also known as: r=

Set the x coordinate of the right side of the Rect by translating the Rect (adjusting the x offset).



201
# File 'lib/gamebox/lib/rect.rb', line 201

def right=(r); self[0] = r - self[2]; return r; end

#sizeObject

Return the width and height of the Rect.



187
# File 'lib/gamebox/lib/rect.rb', line 187

def size; return self[2,2]; end

#size=(size) ⇒ Object

Set the width and height of the Rect.

Raises:

  • (ArgumentError)


190
191
192
193
194
# File 'lib/gamebox/lib/rect.rb', line 190

def size=(size)
 raise ArgumentError, "Rect#size= takes an Array of form [width, height]." if size.size != 2
 self[2,2] = size
 size
end

#to_sObject

Print the Rect in the form “+#<Rect [x,y,w,h]>+”



140
# File 'lib/gamebox/lib/rect.rb', line 140

def to_s; "#<Rect [%s,%s,%s,%s]>"%self; end

#topleftObject Also known as: tl

Return the x and y coordinates of the top-left corner of the Rect



250
# File 'lib/gamebox/lib/rect.rb', line 250

def topleft; return self[0,2].to_a; end

#topleft=(topleft) ⇒ Object Also known as: tl=

Set the x and y coordinates of the top-left corner of the Rect by translating the Rect (adjusting the x and y offsets).

Raises:

  • (ArgumentError)


254
255
256
257
258
# File 'lib/gamebox/lib/rect.rb', line 254

def topleft=(topleft)
    raise ArgumentError, "Rect#topright= takes an Array of form [x, y]." if topleft.size != 2
  self[0,2] = topleft
  return topleft
end

#toprightObject Also known as: tr

Return the x and y coordinates of the top-right corner of the Rect



264
# File 'lib/gamebox/lib/rect.rb', line 264

def topright; return self.right, self[1]; end

#topright=(topright) ⇒ Object Also known as: tr=

Set the x and y coordinates of the top-right corner of the Rect by translating the Rect (adjusting the x and y offsets).

Raises:

  • (ArgumentError)


268
269
270
271
272
# File 'lib/gamebox/lib/rect.rb', line 268

def topright=(topright)
    raise ArgumentError, "Rect#topright= takes an Array of form [x, y]." if topright.size != 2
  self.right, self[1] = topright
  return topright
end

#union(rect) ⇒ Object

As #union!, but the original caller is not changed.



566
567
568
# File 'lib/gamebox/lib/rect.rb', line 566

def union(rect)
  self.dup.union!(rect)
end

#union!(rect) ⇒ Object

Expand the caller to also cover the given Rect. The Rect is still a rectangle, so it may also cover areas that neither of the original Rects did, for example areas between the two Rects.



573
574
575
576
577
578
579
580
581
582
583
584
585
586
# File 'lib/gamebox/lib/rect.rb', line 573

def union!(rect)
  self.normalize!
  rleft, rtop = self.topleft
  rright, rbottom = self.bottomright
  r2 = Rect.new_from_object(rect).normalize!

  rleft = [rleft, r2.left].min
  rtop = [rtop, r2.top].min
  rright = [rright, r2.right].max
  rbottom = [rbottom, r2.bottom].max

  self[0,4] = rleft, rtop, rright - rleft, rbottom - rtop
  return self
end

#union_all(array_rects) ⇒ Object

As #union_all!, but the original caller is not changed.



589
590
591
# File 'lib/gamebox/lib/rect.rb', line 589

def union_all(array_rects)
  self.dup.union_all!(array_rects)
end

#union_all!(array_rects) ⇒ Object

Expand the caller to cover all of the given Rects. See also #union!



594
595
596
597
598
599
# File 'lib/gamebox/lib/rect.rb', line 594

def union_all!(array_rects)
  array_rects.each do |r|
    self.union!(r)
  end
  return self
end

#union_area(rect) ⇒ Object



613
614
615
616
617
618
619
620
621
622
623
624
625
626
# File 'lib/gamebox/lib/rect.rb', line 613

def union_area(rect)
  rleft = self.left
  rtop = self.top
  rright = self.right
  rbottom = self.bottom
  r2 = Rect.new_from_object(rect)

  rleft = min(rleft, r2.left)
  rtop = min(rtop, r2.top)
  rright = max(rright, r2.right)
  rbottom = max(rbottom, r2.bottom)

  (rright - rleft) * (rbottom - rtop)
end

#union_fast(rect) ⇒ Object



628
629
630
631
632
633
634
635
636
637
638
639
640
641
# File 'lib/gamebox/lib/rect.rb', line 628

def union_fast(rect)
  rleft = self.left
  rtop = self.top
  rright = self.right
  rbottom = self.bottom
  r2 = Rect.new_from_object(rect)

  rleft = min(rleft, r2.left)
  rtop = min(rtop, r2.top)
  rright = max(rright, r2.right)
  rbottom = max(rbottom, r2.bottom)

  Rect.new(rleft, rtop, rright - rleft, rbottom - rtop)
end

#wObject Also known as: width

Returns self



171
# File 'lib/gamebox/lib/rect.rb', line 171

def w; return self[2]; end

#w=(val) ⇒ Object Also known as: width=

Sets self to val



173
# File 'lib/gamebox/lib/rect.rb', line 173

def w=(val); self[2] = val; end

#xObject Also known as: left, l

Returns self



151
# File 'lib/gamebox/lib/rect.rb', line 151

def x; return self[0]; end

#x=(val) ⇒ Object Also known as: left=, l=

Sets self to val



153
# File 'lib/gamebox/lib/rect.rb', line 153

def x=(val); self[0] = val; end

#yObject Also known as: top, t

Returns self



161
# File 'lib/gamebox/lib/rect.rb', line 161

def y; return self[1]; end

#y=(val) ⇒ Object Also known as: top=, t=

Sets self to val



163
# File 'lib/gamebox/lib/rect.rb', line 163

def y=(val); self[1] = val; end

#zero_out!Object



606
607
608
609
610
611
# File 'lib/gamebox/lib/rect.rb', line 606

def zero_out!
  self[0] = 0
  self[1] = 0
  self[2] = 0
  self[3] = 0
end