Class: MagicCloud::CollisionBoard
- Defined in:
- lib/magic_cloud/collision_board.rb
Overview
Pixel-by-pixel collision board
Providen by width and height of the board, allows to check if given shape (array of zero and non-zero pixels) “collides” with any of previosly placed shapes
Instance Attribute Summary collapse
-
#intersections_cache ⇒ Object
readonly
Returns the value of attribute intersections_cache.
-
#rects ⇒ Object
readonly
Returns the value of attribute rects.
Attributes inherited from BitMatrix
Instance Method Summary collapse
- #add(shape) ⇒ Object
- #collides?(shape) ⇒ Boolean
- #collides_previous?(shape, intersections) ⇒ Boolean
- #criss_cross_collision?(rect) ⇒ Boolean
-
#initialize(width, height) ⇒ CollisionBoard
constructor
A new instance of CollisionBoard.
- #pixels_collision?(shape, rect) ⇒ Boolean
- #pixels_collision_multi?(shape, intersections) ⇒ Boolean
Methods inherited from BitMatrix
Constructor Details
#initialize(width, height) ⇒ CollisionBoard
Returns a new instance of CollisionBoard.
11 12 13 14 15 |
# File 'lib/magic_cloud/collision_board.rb', line 11 def initialize(width, height) super @rects = [] @intersections_cache = {} end |
Instance Attribute Details
#intersections_cache ⇒ Object (readonly)
Returns the value of attribute intersections_cache.
17 18 19 |
# File 'lib/magic_cloud/collision_board.rb', line 17 def intersections_cache @intersections_cache end |
#rects ⇒ Object (readonly)
Returns the value of attribute rects.
17 18 19 |
# File 'lib/magic_cloud/collision_board.rb', line 17 def rects @rects end |
Instance Method Details
#add(shape) ⇒ Object
99 100 101 102 103 104 105 106 107 108 |
# File 'lib/magic_cloud/collision_board.rb', line 99 def add(shape) l, t = shape.left, shape.top shape.height.times do |dy| shape.width.times do |dx| put(l + dx, t + dy) if shape.sprite.at(dx, dy) end end rects << shape.rect end |
#collides?(shape) ⇒ Boolean
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/magic_cloud/collision_board.rb', line 56 def collides?(shape) Debug.stats[:collide_total] += 1 # nothing on board - so, no collisions return false if rects.empty? # no point to try drawing criss-crossed words # even if they will not collide pixel-per-pixel return true if criss_cross_collision?(shape.rect) # then find which of placed sprites rectangles tag intersects intersections = rects.map{|r| r.intersect(shape.rect)} # no need to further check: this tag is not inside any others' rectangle if intersections.compact.empty? Debug.stats[:rect_no] += 1 return false end # most probable that we are still collide with this word return true if collides_previous?(shape, intersections) # only then check points inside intersected rectangles return true if pixels_collision_multi?(shape, intersections) Debug.stats[:px_no] += 1 false end |
#collides_previous?(shape, intersections) ⇒ Boolean
28 29 30 31 32 33 34 35 36 37 38 39 |
# File 'lib/magic_cloud/collision_board.rb', line 28 def collides_previous?(shape, intersections) prev_idx = intersections_cache[shape.object_id] if prev_idx && (prev = intersections[prev_idx]) && pixels_collision?(shape, prev) Debug.stats[:px_prev_yes] += 1 true else false end end |
#criss_cross_collision?(rect) ⇒ Boolean
19 20 21 22 23 24 25 26 |
# File 'lib/magic_cloud/collision_board.rb', line 19 def criss_cross_collision?(rect) if rects.any?{|r| r.criss_cross?(rect)} Debug.stats[:criss_cross] += 1 true else false end end |
#pixels_collision?(shape, rect) ⇒ Boolean
86 87 88 89 90 91 92 93 94 95 96 97 |
# File 'lib/magic_cloud/collision_board.rb', line 86 def pixels_collision?(shape, rect) l, t = shape.left, shape.top (rect.x0...rect.x1).each do |x| (rect.y0...rect.y1).each do |y| dx = x - l dy = y - t return true if shape.sprite.at(dx, dy) && at(x, y) end end false end |
#pixels_collision_multi?(shape, intersections) ⇒ Boolean
41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/magic_cloud/collision_board.rb', line 41 def pixels_collision_multi?(shape, intersections) intersections.each_with_index do |intersection, idx| next unless intersection next if idx == intersections_cache[shape.object_id] # already checked it next unless pixels_collision?(shape, intersection) Debug.stats[:px_yes] += 1 intersections_cache[shape.object_id] = idx return true end false end |