Class: Chingu::Rect

Inherits:
Array
  • Object
show all
Defined in:
lib/chingu/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 inherited from Array

#each_bounding_box_collision, #each_bounding_circle_collision, #each_collision

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.



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

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()



109
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
# File 'lib/chingu/rect.rb', line 109

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

#bottomObject Also known as: b

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



205
# File 'lib/chingu/rect.rb', line 205

def bottom; return self.at(1)+self.at(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).



209
# File 'lib/chingu/rect.rb', line 209

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

#bottomleftObject Also known as: bl

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



276
# File 'lib/chingu/rect.rb', line 276

def bottomleft; return self.at(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)


280
281
282
283
284
# File 'lib/chingu/rect.rb', line 280

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



290
# File 'lib/chingu/rect.rb', line 290

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)


294
295
296
297
298
# File 'lib/chingu/rect.rb', line 294

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.



215
# File 'lib/chingu/rect.rb', line 215

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)


219
220
221
222
223
# File 'lib/chingu/rect.rb', line 219

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



228
# File 'lib/chingu/rect.rb', line 228

def centerx; return self.at(0)+(self.at(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).



232
# File 'lib/chingu/rect.rb', line 232

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

#centeryObject Also known as: cy

Return the y coordinate of the center of the Rect



238
# File 'lib/chingu/rect.rb', line 238

def centery; return self.at(1)+(self.at(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).



242
# File 'lib/chingu/rect.rb', line 242

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

#clamp(rect) ⇒ Object

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



369
370
371
# File 'lib/chingu/rect.rb', line 369

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.



376
377
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
# File 'lib/chingu/rect.rb', line 376

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

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

#clip(rect) ⇒ Object

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



416
417
418
# File 'lib/chingu/rect.rb', line 416

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.



425
426
427
428
429
430
431
432
433
434
435
436
437
438
# File 'lib/chingu/rect.rb', line 425

def clip!(rect)
	nself = self.normalize
	other = Rect.new_from_object(rect).normalize!
	if self.collide_rect?(other)
		self[0] = [nself.at(0), other.at(0)].max
		self[1] = [nself.at(1), other.at(1)].max
		self[2] = [nself.right, other.right].min - self.at(0)
		self[3] = [nself.bottom, other.bottom].min - self.at(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.



468
469
470
471
472
473
474
475
# File 'lib/chingu/rect.rb', line 468

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.



480
481
482
483
484
485
486
487
488
# File 'lib/chingu/rect.rb', line 480

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.



446
447
448
449
450
451
# File 'lib/chingu/rect.rb', line 446

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.



459
460
461
462
463
# File 'lib/chingu/rect.rb', line 459

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)


492
493
494
495
# File 'lib/chingu/rect.rb', line 492

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)


498
499
500
501
502
503
# File 'lib/chingu/rect.rb', line 498

def collide_rect?(rect)
	nself = self.normalize
	rect  = Rect.new_from_object(rect).normalize!
	return ((nself.l >= rect.l && nself.l <= rect.r) or (rect.l >= nself.l && rect.l <= nself.r)) &&
	       ((nself.t >= rect.t && nself.t <= rect.b) or (rect.t >= nself.t && rect.t <= nself.b))
end

#contain?(rect) ⇒ Boolean

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

Returns:

  • (Boolean)


507
508
509
510
511
512
# File 'lib/chingu/rect.rb', line 507

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

#hObject Also known as: height

Returns self.at(3)



177
# File 'lib/chingu/rect.rb', line 177

def h; return self.at(3); end

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

Sets self to val



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

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

#inflate(x, y) ⇒ Object

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



515
516
517
518
519
520
# File 'lib/chingu/rect.rb', line 515

def inflate(x,y)
	return self.class.new(self.at(0) - x.div(2),
												self.at(1) - y.div(2),
												self.at(2) + x,
												self.at(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.



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

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]>+”



142
# File 'lib/chingu/rect.rb', line 142

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.



350
# File 'lib/chingu/rect.rb', line 350

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)


354
355
356
357
358
# File 'lib/chingu/rect.rb', line 354

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.



305
# File 'lib/chingu/rect.rb', line 305

def midleft; return self.at(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)


309
310
311
312
313
# File 'lib/chingu/rect.rb', line 309

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.



335
# File 'lib/chingu/rect.rb', line 335

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)


339
340
341
342
343
# File 'lib/chingu/rect.rb', line 339

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.



320
# File 'lib/chingu/rect.rb', line 320

def midtop; return self.centerx, self.at(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)


324
325
326
327
328
# File 'lib/chingu/rect.rb', line 324

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.



534
535
536
# File 'lib/chingu/rect.rb', line 534

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.



541
542
543
544
# File 'lib/chingu/rect.rb', line 541

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

#normalizeObject

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



547
548
549
# File 'lib/chingu/rect.rb', line 547

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.



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

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

#rightObject Also known as: r

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



195
# File 'lib/chingu/rect.rb', line 195

def right; return self.at(0)+self.at(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).



199
# File 'lib/chingu/rect.rb', line 199

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

#sizeObject

Return the width and height of the Rect.



185
# File 'lib/chingu/rect.rb', line 185

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

#size=(size) ⇒ Object

Set the width and height of the Rect.

Raises:

  • (ArgumentError)


188
189
190
191
192
# File 'lib/chingu/rect.rb', line 188

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]>+”



139
# File 'lib/chingu/rect.rb', line 139

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



248
# File 'lib/chingu/rect.rb', line 248

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)


252
253
254
255
256
# File 'lib/chingu/rect.rb', line 252

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



262
# File 'lib/chingu/rect.rb', line 262

def topright; return self.right, self.at(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)


266
267
268
269
270
# File 'lib/chingu/rect.rb', line 266

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.



565
566
567
# File 'lib/chingu/rect.rb', line 565

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.



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

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.



588
589
590
# File 'lib/chingu/rect.rb', line 588

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!



593
594
595
596
597
598
# File 'lib/chingu/rect.rb', line 593

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

#wObject Also known as: width

Returns self.at(2)



169
# File 'lib/chingu/rect.rb', line 169

def w; return self.at(2); end

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

Sets self to val



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

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

#xObject Also known as: left, l

Returns self.at(0)



149
# File 'lib/chingu/rect.rb', line 149

def x; return self.at(0); end

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

Sets self to val



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

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

#yObject Also known as: top, t

Returns self.at(1)



159
# File 'lib/chingu/rect.rb', line 159

def y; return self.at(1); end

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

Sets self to val



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

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