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