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
rubocop:enable Lint/HashCompareByIdentity.
-
#collides_previous?(shape, intersections) ⇒ Boolean
rubocop:disable Lint/HashCompareByIdentity – probably should be followed, but don’t have time to test it now.
- #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.
12 13 14 15 16 |
# File 'lib/magic_cloud/collision_board.rb', line 12 def initialize(width, height) super @rects = [] @intersections_cache = {} end |
Instance Attribute Details
#intersections_cache ⇒ Object (readonly)
Returns the value of attribute intersections_cache.
18 19 20 |
# File 'lib/magic_cloud/collision_board.rb', line 18 def intersections_cache @intersections_cache end |
#rects ⇒ Object (readonly)
Returns the value of attribute rects.
18 19 20 |
# File 'lib/magic_cloud/collision_board.rb', line 18 def rects @rects end |
Instance Method Details
#add(shape) ⇒ Object
102 103 104 105 106 107 108 109 110 111 |
# File 'lib/magic_cloud/collision_board.rb', line 102 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
rubocop:enable Lint/HashCompareByIdentity
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 85 86 87 |
# File 'lib/magic_cloud/collision_board.rb', line 59 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
rubocop:disable Lint/HashCompareByIdentity – probably should be followed, but don’t have time to test it now
30 31 32 33 34 35 36 37 38 39 40 41 |
# File 'lib/magic_cloud/collision_board.rb', line 30 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
20 21 22 23 24 25 26 27 |
# File 'lib/magic_cloud/collision_board.rb', line 20 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
89 90 91 92 93 94 95 96 97 98 99 100 |
# File 'lib/magic_cloud/collision_board.rb', line 89 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
43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/magic_cloud/collision_board.rb', line 43 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 |