Module: Zif::Layers::Bitmaskable
- Included in:
- ActiveBitmaskedTiledLayer, BitmaskedTiledLayer
- Defined in:
- lib/zif/layers/bitmaskable.rb
Overview
A mixin to extend Tileable functionality. Sprites are chosen via bitmasked adjacency rules on the presence data layer - otherwise known as Autotiling. This is a bit opinionated! Here is how the bitmask is calculated:
+-----+----+-----+
| 128 | 1 | 16 |
+-----+----+-----+
| 8 | <> | 2 |
+-----+----+-----+
| 64 | 4 | 32 |
+-----+----+-----+
(Cardinal directions clockwise, then diagonal directions clockwise)
So if a tile has a neighbor to the north, east and northeast, it’ll try to load the sprite “mytiles_19” – 1+2+16 from the SpriteRegistry. See the SpriteRegistry for more info on filenames and aliasing.
Some background (note the author uses a different numbering scheme): gamedevelopment.tutsplus.com/tutorials/how-to-use-tile-bitmasking-to-auto-tile-your-level-layouts–cms-25673
Instance Attribute Summary collapse
-
#bitmask_data ⇒ Array<Array<Integer>>
readonly
A 2-dimensional array of bitmasked integers calculated from #presence_data This array is the size of your map’s logical height, containing arrays the size of the logical width.
-
#bitmasked_sprite_name_prefix ⇒ String
The prefix to use when referencing image paths.
-
#presence_data ⇒ Array<Array<Boolean>>
A 2-dimensional array of
true
andfalse
values This array is the size of your map’s logical height, containing arrays the size of the logical width.
1. Public Interface collapse
-
#add_at(x, y) ⇒ Object
Add presence at this logical position, then redraw.
-
#recalculate_bitmask(from_x: 0, from_y: 0, to_x: @map.logical_width - 1, to_y: @map.logical_height - 1) ⇒ Object
This will recalculte the #bitmask_data for a rectangle of logical positions, from #presence_data.
-
#redraw_at(x, y) ⇒ Object
Recalculates bitmask and sets sprites for the specified location and the 9 tiles surrounding it.
-
#reinitialize_sprites ⇒ Object
Overrides Tileable#reinitialize_sprites Clears @sprites and resets #presence_data and #bitmask_data.
-
#remove_at(x, y) ⇒ Object
Remove the tile / presence at this logical position, then redraw.
-
#set_sprites_from_bitmask(from_x: 0, from_y: 0, to_x: @map.logical_width - 1, to_y: @map.logical_height - 1) ⇒ Object
This will reset the tiles for a rectangle, based on the #bitmask_data.
2. Private-ish methods collapse
- #exclude_from_serialize ⇒ Object private
Instance Attribute Details
#bitmask_data ⇒ Array<Array<Integer>> (readonly)
Returns A 2-dimensional array of bitmasked integers calculated from #presence_data This array is the size of your map’s logical height, containing arrays the size of the logical width.
32 33 34 |
# File 'lib/zif/layers/bitmaskable.rb', line 32 def bitmask_data @bitmask_data end |
#bitmasked_sprite_name_prefix ⇒ String
Returns The prefix to use when referencing image paths.
35 36 37 |
# File 'lib/zif/layers/bitmaskable.rb', line 35 def bitmasked_sprite_name_prefix @bitmasked_sprite_name_prefix end |
#presence_data ⇒ Array<Array<Boolean>>
Returns A 2-dimensional array of true
and false
values This array is the size of your map’s logical height, containing arrays the size of the logical width.
28 29 30 |
# File 'lib/zif/layers/bitmaskable.rb', line 28 def presence_data @presence_data end |
Instance Method Details
#add_at(x, y) ⇒ Object
Add presence at this logical position, then redraw
60 61 62 63 |
# File 'lib/zif/layers/bitmaskable.rb', line 60 def add_at(x, y) @presence_data[y][x] = true redraw_at(x, y) end |
#exclude_from_serialize ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
154 155 156 |
# File 'lib/zif/layers/bitmaskable.rb', line 154 def exclude_from_serialize %w[presence_data bitmask_data sprites primitives] end |
#recalculate_bitmask(from_x: 0, from_y: 0, to_x: @map.logical_width - 1, to_y: @map.logical_height - 1) ⇒ Object
This will recalculte the #bitmask_data for a rectangle of logical positions, from #presence_data
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
# File 'lib/zif/layers/bitmaskable.rb', line 78 def recalculate_bitmask(from_x: 0, from_y: 0, to_x: @map.logical_width - 1, to_y: @map.logical_height - 1) from_x = [from_x, 0].max from_y = [from_y, 0].max to_x = [to_x, @map.logical_width - 1].min to_y = [to_y, @map.logical_height - 1].min (from_y..to_y).each do |i| (from_x..to_x).each do |j| @bitmask_data[i][j] = nil next unless @presence_data[i][j] map_north = (i + 1) <= @map.logical_height map_south = (i - 1).positive? map_east = (j + 1) <= @map.logical_width map_west = (j - 1).positive? bitmask = 0 # The presence of a bit in the bitmask indicates the presence of a tile relative to this one # Edges # Edges - North bitmask += 1 if map_north && @presence_data[i + 1][j] # Edges - East bitmask += 2 if map_east && @presence_data[i][j + 1] # Edges - South bitmask += 4 if map_south && @presence_data[i - 1][j] # Edges - West bitmask += 8 if map_west && @presence_data[i][j - 1] # Corners # Corners - NE bitmask += 16 if map_north && map_east && @presence_data[i + 1][j + 1] # Corners - SE bitmask += 32 if map_south && map_east && @presence_data[i - 1][j + 1] # Corners - SW bitmask += 64 if map_south && map_west && @presence_data[i - 1][j - 1] # Corners - NW bitmask += 128 if map_north && map_west && @presence_data[i + 1][j - 1] @bitmask_data[i][j] = bitmask end end end |
#redraw_at(x, y) ⇒ Object
Recalculates bitmask and sets sprites for the specified location and the 9 tiles surrounding it
68 69 70 71 |
# File 'lib/zif/layers/bitmaskable.rb', line 68 def redraw_at(x, y) recalculate_bitmask(from_x: x - 1, from_y: y - 1, to_x: x + 1, to_y: y + 1) set_sprites_from_bitmask(from_x: x - 1, from_y: y - 1, to_x: x + 1, to_y: y + 1) end |
#reinitialize_sprites ⇒ Object
Overrides Tileable#reinitialize_sprites Clears @sprites and resets #presence_data and #bitmask_data
42 43 44 45 46 |
# File 'lib/zif/layers/bitmaskable.rb', line 42 def reinitialize_sprites super() @presence_data = Array.new(@map.logical_height) { Array.new(@map.logical_width, false) } @bitmask_data = Array.new(@map.logical_height) { Array.new(@map.logical_width, nil) } end |
#remove_at(x, y) ⇒ Object
Remove the tile / presence at this logical position, then redraw
51 52 53 54 55 |
# File 'lib/zif/layers/bitmaskable.rb', line 51 def remove_at(x, y) @presence_data[y][x] = false remove_tile(x, y) redraw_at(x, y) end |
#set_sprites_from_bitmask(from_x: 0, from_y: 0, to_x: @map.logical_width - 1, to_y: @map.logical_height - 1) ⇒ Object
This will reset the tiles for a rectangle, based on the #bitmask_data
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 |
# File 'lib/zif/layers/bitmaskable.rb', line 128 def set_sprites_from_bitmask(from_x: 0, from_y: 0, to_x: @map.logical_width - 1, to_y: @map.logical_height - 1) raise 'BitmaskedTiledLayer: Please set @bitmasked_sprite_name_prefix' unless @bitmasked_sprite_name_prefix from_x = [from_x, 0].max from_y = [from_y, 0].max to_x = [to_x, @map.logical_width - 1].min to_y = [to_y, @map.logical_height - 1].min (from_y..to_y).each do |i| (from_x..to_x).each do |j| remove_tile(j, i) bitmask = @bitmask_data[i][j] next unless bitmask full_name = "#{@bitmasked_sprite_name_prefix}_#{bitmask}".to_sym sprite = $services[:sprite_registry].construct(full_name) add_positioned_sprite(sprite: sprite, logical_x: j, logical_y: i) end end end |