module Chalk module Compiler class Sprite def initialize @pixels = Hash(UInt8, UInt8).new(default_value: 0_u8) end def height return (@pixels.keys.max || 0_u8) + 1 end def initialize(string, blank_char = ' ') @pixels = Hash(UInt8, UInt8).new(default_value: 0_u8) string.split("\n").each_with_index do |s, i| break if i > 15 index = 0 byte = 0_u8 s.each_char do |char| break if index > 7 bit = (char == blank_char) ? 0_u8 : 1_u8 byte |= (bit << (7 - index)) index += 1 end @pixels[i.to_u8] = byte end end def initialize(tokens) raise "Invalid sprite" if tokens.size > 15 @pixels = Hash(UInt8, UInt8).new(default_value: 0_u8) tokens.each_with_index do |token, i| byte = 0_u8 substring = token[1..token.size - 2] raise "Invalid sprite" if substring.size > 8 bit = 0b10000000 substring.each_char do |char| byte |= bit if char == 'x' bit >>= 1 end @pixels[i.to_u8] = byte end end def set_pixel(x, y) raise "Invalid x-coordinate" if x > 7 raise "Invalid y-coordinate" if y > 15 x = x.to_u8 y = y.to_u8 char = @pixels.fetch y, 0_u8 char |= (1 << (7 - x)) @pixels[y] = char end def unset_pixel(x, y) raise "Invalid x-coordinate" if x > 7 raise "Invalid y-coordinate" if y > 15 x = x.to_u8 y = y.to_u8 char = @pixels.fetch y, 0_u8 char &= ~(1 << (7 - x)) @pixels[y] = char end def toggle_pixel(x, y) raise "Invalid x-coordinate" if x > 7 raise "Invalid y-coordinate" if y > 15 x = x.to_u8 y = y.to_u8 char = @pixels.fetch y, 0_u8 char ^= (1 << (7 - x)) @pixels[y] = char end def draw(io = STDOUT, blank_char = ' ', ink_char = 'x') until_y = @pixels.keys.max? return unless until_y (0..until_y).each do |y| row = @pixels.fetch y, 0_u8 pointer = 0b10000000 while pointer != 0 draw_pixel = (row & pointer) != 0 io << (draw_pixel ? ink_char : blank_char) pointer = pointer >> 1 end io << '\n' end end def encode if until_y = @pixels.keys.max? return (0..until_y).map { |it| @pixels.fetch it, 0_u8 } end return [0_u8] end end end end