commit 888c55d92561f9557546552ca067f07b3a478d4e Author: mewrrythekibby Date: Sat Nov 29 19:19:38 2025 -0600 Should have started this repo sooner... diff --git a/main.rb b/main.rb new file mode 100644 index 0000000..9c3dc81 --- /dev/null +++ b/main.rb @@ -0,0 +1,345 @@ +require 'gosu' + +puts "Hexagonal Terminal Emulator" +puts "---------------------------" +puts "Gosu Version: #{Gosu::VERSION}" +puts "Ruby Version: #{RUBY_VERSION}" + +$fg_color = Gosu::Color.new(0, 255, 0) +$bg_color = Gosu::Color.new(0, 0, 0) +$hex_color = Gosu::Color.new(255, 255, 255) +$pallette16 = [ + Gosu::Color.new( 0, 0, 0), # Black 000000 + Gosu::Color.new(255, 0, 0), # Red FF0000 + Gosu::Color.new( 0, 255, 0), # Green 00FF00 + Gosu::Color.new(255, 255, 0), # Yellow FFFF00 + Gosu::Color.new( 0, 0, 255), # Blue 0000FF + Gosu::Color.new(255, 0, 255), # Magenta FF00FF + Gosu::Color.new( 0, 255, 255), # Cyan 00FFFF + Gosu::Color.new(128, 128, 128), # White 808080 + Gosu::Color.new( 64, 64, 64), # Bright Black 404040 + Gosu::Color.new(255, 128, 128), # Bright Red 008080 + Gosu::Color.new(128, 255, 128), # Bright Green 800080 + Gosu::Color.new(255, 255, 128), # Bright Yellow 000080 + Gosu::Color.new(128, 128, 255), # Bright Blue 808000 + Gosu::Color.new(255, 128, 255), # Bright Magenta 008000 + Gosu::Color.new(128, 255, 255), # Bright Cyan 800000 + Gosu::Color.new(255, 255, 255), # Bright White FFFFFF +] +#WHITE = Gosu::Color.new(255, 255, 255) # For image drawing purposes + +$hex_width = 20 +$hex_mid = 40 +$hex_tip = 5 + +HEX_DEBUG_WIDTH = 15 +def recalculate_hexagons + # 0 + # / \ + # 5 1 + # | | + # 4 2 + # \ / + # 3 + $hex_points = [ + # A six pointed hexagon + [$hex_width/2, 0 ], # Top center + [$hex_width , $hex_tip ], # Upper right + [$hex_width , $hex_tip+$hex_mid ], # Lower right + [$hex_width/2, ($hex_tip*2)+$hex_mid], # Bottom center + [0 , $hex_tip+$hex_mid ], # Lower left + [0 , $hex_tip ], # Upper left + # Iterate in a clockwise order + ] + puts "Recalculated hexagons:" + puts "(#{$hex_points[0][0]},#{$hex_points[0][1]})".center(HEX_DEBUG_WIDTH) + puts "(#{$hex_points[5][0]},#{$hex_points[5][1]})".ljust(HEX_DEBUG_WIDTH/2) \ + + "(#{$hex_points[1][0]},#{$hex_points[1][1]})".rjust(HEX_DEBUG_WIDTH/2) + puts "(#{$hex_points[4][0]},#{$hex_points[4][1]})".ljust(HEX_DEBUG_WIDTH/2) \ + + "(#{$hex_points[2][0]},#{$hex_points[2][1]})".rjust(HEX_DEBUG_WIDTH/2) + puts "(#{$hex_points[3][0]},#{$hex_points[3][1]})".center(HEX_DEBUG_WIDTH) + $hex_x_offset = $hex_width/2 + $hex_y_offset = $hex_tip + $hex_mid + $hex_bgs.clear +end + +class HexEditXref_BgGrphStore + def initialize + @hex_ids = Hash.new #hexid => color + @hex_refs = Hash.new #color => [num_refs, hexids] + @hex_bgs = Hash.new #color => bg + end + def register(hexid,color) + argb=color.argb + unregister hexid + @hex_ids[hexid] = argb + if @hex_refs.has_key? argb + @hex_refs[argb][0] += 1 + unless @hex_refs[argb][1].include? hexid + @hex_refs[argb][1].append hexid + end + end + render argb + end + def unregister(hexid) + if @hex_ids.has_key? hexid + argb = @hex_ids[hexid] + @hex_ids.delete hexid + end + if @hex_refs.has_key? argb + if @hex_refs[argb][1].include? hexid + @hex_refs[argb][1].delete hexid + @hex_refs[argb][0] -= 1 + end + if @hex_refs[argb][0] < 1 + @hex_refs.delete argb + end + end + if (@hex_bgs.has_key?(argb) && + !@hex_refs.has_key?(argb)) + @hex_bgs.delete argb + end + end + def [](color) + argb = color.argb + raise RuntimeError.new( + "Color #{argb} was requested from "+ + "a HEX_BGs class, but was not "+ + "registered beforehand." + ) unless @hex_bgs.has_key? argb + return @hex_bgs[argb] + end + def render(argb) + color = Gosu::Color.new(argb) + @hex_bgs[argb] = [Gosu::record($hex_width, $hex_mid+($hex_tip*2)) { + # Double Quad Method (0145, 1234): + Gosu::draw_quad( # 0145 + $hex_points[0][0], $hex_points[0][1], color, #0 + $hex_points[1][0], $hex_points[1][1], color, #1 + $hex_points[4][0], $hex_points[4][1], color, #4 + $hex_points[5][0], $hex_points[5][1], color, #5 + 0 + ) + Gosu.draw_quad( # 1234 + $hex_points[1][0], $hex_points[1][1], color, #1 + $hex_points[2][0], $hex_points[2][1], color, #2 + $hex_points[3][0], $hex_points[3][1], color, #3 + $hex_points[4][0], $hex_points[4][1], color, #4 + 0 + ) + },Time.now + ] + end +end + +class TextProps + attr_accessor \ + :font, :bg_color, :fg_color, + :hex_border_color, + :bold, :italic, :underline, :overline, :strikethrough + def initialize(font, text_props=nil) + if text_props != nil + @font = font + @fg_color = text_props.fg_color + @bg_color = text_props.bg_color + @hex_border_color = text_props.hex_border_color + @bold = text_props.bold + @italic = text_props.italic + @underline = text_props.underline + @overline = text_props.overline + @strikethrough = text_props.strikethrough + return + end + @font = font + @fg_color = $fg_color + @bg_color = $bg_color + @hex_border_color = $hex_color + @bold = false + @italic = false + @underline = false + @overline = false + @strikethrough = false + return + end +end + +class Hex + attr_accessor :x, :y, :char, :text_props + def initialize(x, y, char, text_props) + @x = x + @y = y + @char = char + @text_props = text_props + end + + def draw + + $hex_bgs[@text_props.bg_color].draw( + @x, @y, 0, 1, 1, Gosu::Color::WHITE + ) + @text_props.font.draw_text(@char, @x, @y+$hex_tip, 2, 1.0, 1.0, @text_props.fg_color) + end +end + + +class HexagonTerminalWindow < Gosu::Window + def initialize(width, height, fullscreen) + # Window + super + self.caption = "Hexagon Terminal" + @width = width + @height = height + + # Fonts (load default monospaced font) + @font = Gosu::Font.new(self, "Monaspace Krypton", 30) + $hex_width = @font.text_width("_").round() + $hex_mid = @font.height.round() + recalculate_hexagons + + # State + @cursor_pos = [0, 1] # row-1, col-1 + @input_buffer = "" + @output_buffer = "." + @active_styling = TextProps.new(@font) + @do_redraw = true + self.text_input = Gosu::TextInput.new + @old_text = [0,'',0] + + # Hexes + @xexes = ((width-$hex_x_offset) / $hex_width).floor # xexes = 'x's of hexes + @yexes = ((height-$hex_tip) / $hex_y_offset ).floor # yexes = 'y's of hexes + @next_row_is_shifted = false + @hexes = [] + for row in 0..@yexes-1 + @hexes << [] + for col in 0..@xexes-1 + x = (col*$hex_width) + ((row % 2 == 1) ? $hex_x_offset : 0) + y = row*$hex_y_offset + @active_styling.bg_color = Gosu::Color.new(rand(255), rand(255), rand(255)) + @hexes[-1] << Hex.new(x, y, "W", TextProps.new(@font, @active_styling)) + @next_row_is_shifted = row % 2 == 0 + end + end + + # Clear the screen + @hexes.each do |rex| + rex.each do |hex| + hex.char = ' ' + end + end + end + + def needs_redraw? + # Quads are expensive; Avoid redrawing. + return @do_redraw + end + + def update + $hex_bgs.clean + if @output_buffer.length > 0 + render_output + @do_redraw = true + end + new_text = [ + self.text_input.selection_start, + self.text_input.text, + self.text_input.caret_pos + ] + if @old_text != new_text + @old_text = [ + new_text[0], + new_text[1], + new_text[2] + ] + out = ''+new_text[1] + if new_text[0]= @hexes[0].length + @cursor_pos[0] += 1 + @cursor_pos[1] = 0 + end + if @cursor_pos[0] >= @hexes.length + @cursor_pos[0] = @hexes.length - 1 + scroll_with_new_line + end + end + @do_redraw = true + # @output_buffer = "" + end + + def scroll_with_new_line + @active_styling.hex_border_color =\ + Gosu::Color.new(rand(255), rand(255), rand(255)) + @hexes.each do |rex| + rex.each do |hex| + hex.y -= $hex_y_offset + end + end + @hexes = @hexes[1..-1] + @hexes << [] + for i in 0..@xexes-1 + @active_styling.bg_color = Gosu::Color.new(rand(255), rand(255), rand(255)) + @hexes[-1] << Hex.new( + (i*$hex_width) + (@next_row_is_shifted? $hex_x_offset : 0), + (@yexes-1)*$hex_y_offset, + " ", TextProps.new(@font, @active_styling)) + end + @next_row_is_shifted = !@next_row_is_shifted + end + + def handle_escape_char(char) + @escape_buffer += @output_buffer[0] + @output_buffer = @output_buffer[1..-1] + end +end + +$hex_bgs = HexBgCache.new +recalculate_hexagons +window = HexagonTerminalWindow.new(800, 600, false) +window.show \ No newline at end of file