Module: Chingu::Traits::CollisionDetection

Defined in:
lib/chingu/traits/collision_detection.rb

Overview

Research: 1) QuadTrees: lab.polygonal.de/2007/09/09/quadtree-demonstration/ 2) Sweep and Prune

SEE: www.shmup-dev.com/forum/index.php?board=65.0

Makes use of 2 attributes

bounding_box      - a Rect-instance, uses in bounding_box collisions
radius            - a number

Defined Under Namespace

Modules: ClassMethods

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#collidableObject

Returns the value of attribute collidable



36
37
38
# File 'lib/chingu/traits/collision_detection.rb', line 36

def collidable
  @collidable
end

Instance Method Details

#bounding_box_bounding_circle_collision?(object2) ⇒ Boolean

Returns:

  • (Boolean)


88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/chingu/traits/collision_detection.rb', line 88

def bounding_box_bounding_circle_collision?(object2)
  return false  unless self.collidable && object2.collidable
  
  rect = self.respond_to?(:bounding_box) ? self.bounding_box : object2.bounding_box
  circle = self.respond_to?(:radius) ? self : object2
  radius = circle.radius.to_i
  
  distance_x = (circle.x - rect.x - rect.width/2).abs
  distance_y = (circle.y - rect.y - rect.height/2).abs
  
  return false if distance_x > (rect.width/2 + circle.radius)
  return false if distance_y > (rect.height/2 + circle.radius)
  
  return true if distance_x <= (rect.width/2)
  return true if distance_y <= (rect.height/2)
    
  cornerDistance_sq = (distance_x - rect.width/2) ** 2 + (distance_y - rect.height/2) ** 2
  return (cornerDistance_sq <= (circle.radius ** 2))
end

#bounding_box_collision?(object2) ⇒ Boolean

Collide self with a given game object by checking both objects bounding_box'es Returns true if colliding.

Returns:

  • (Boolean)


69
70
71
72
# File 'lib/chingu/traits/collision_detection.rb', line 69

def bounding_box_collision?(object2)
  return false  unless self.collidable && object2.collidable
  self.bounding_box.collide_rect?(object2.bounding_box)
end

#bounding_circle_collision?(object2) ⇒ Boolean

Collide self using distance between 2 objects and their radius. Returns true if colliding.

Returns:

  • (Boolean)


78
79
80
81
# File 'lib/chingu/traits/collision_detection.rb', line 78

def bounding_circle_collision?(object2)
  return false  unless self.collidable && object2.collidable
  Gosu.distance(self.x, self.y, object2.x, object2.y) < self.radius + object2.radius
end

#collides?(object2) ⇒ Boolean Also known as: collision?

The standard method called when self needs to be checked for a collision with another object By default it calls bounding_box_collision? which will check for intersectons between the two objects “bounding_box” attributs (a Chingu::Rect instance)

Returns:

  • (Boolean)


54
55
56
57
58
59
60
61
62
# File 'lib/chingu/traits/collision_detection.rb', line 54

def collides?(object2)
  if self.respond_to?(:bounding_box) && object2.respond_to?(:bounding_box)
    bounding_box_collision?(object2)
  elsif self.respond_to?(:radius) && object2.respond_to?(:radius)
    bounding_circle_collision?(object2)
  else
    bounding_box_bounding_circle_collision?(object2)
  end
end

#each_bounding_box_collision(*klasses) ⇒ Object

Explicit bounding_box-collision Works like each_collision but with inline-code for speedups



147
148
149
150
151
152
153
154
155
# File 'lib/chingu/traits/collision_detection.rb', line 147

def each_bounding_box_collision(*klasses)
  Array(klasses).each do |klass|
    (klass.respond_to?(:all) ? klass.all : Array(klass)).each do |object|
      next if object == self
      next unless self.collidable && object.collidable
      yield(self, object) if self.bounding_box.collide_rect?(object.bounding_box)
    end
  end
end

#each_bounding_circle_collision(*klasses) ⇒ Object

Explicit radius-collision Works like each_collsion but with inline-code for speedups



133
134
135
136
137
138
139
140
141
# File 'lib/chingu/traits/collision_detection.rb', line 133

def each_bounding_circle_collision(*klasses)
  Array(klasses).each do |klass|
    (klass.respond_to?(:all) ? klass.all : Array(klass)).each do |object|
      next if object == self
      next unless self.collidable && object.collidable
      yield(self, object) if Gosu.distance(self.x, self.y, object.x, object.y) < self.radius + object.radius
    end
  end
end

#each_collision(*klasses) ⇒ Object

Collides self with all objects of given classes Yields self and the objects it collides with



112
113
114
115
116
117
118
# File 'lib/chingu/traits/collision_detection.rb', line 112

def each_collision(*klasses)
  Array(klasses).each do |klass|
    (klass.respond_to?(:all) ? klass.all : Array(klass)).each do |object|
      yield(self, object)   if collides?(object)
    end
  end
end

#first_collision(*klasses) ⇒ Object



120
121
122
123
124
125
126
127
# File 'lib/chingu/traits/collision_detection.rb', line 120

def first_collision(*klasses)
  Array(klasses).each do |klass|
    (klass.respond_to?(:all) ? klass.all : Array(klass)).each do |object|
      return object   if collides?(object)
    end
  end
  return nil
end

#setup_trait(options) ⇒ Object



44
45
46
47
# File 'lib/chingu/traits/collision_detection.rb', line 44

def setup_trait(options)
  @collidable = true
  super
end