title: High CPU Usage in Gosu Drawing Program with Ruby
body: <p>I have been tinkering with making a drawing application in Gosu using Ruby, but am running into some high CPU usage. I know one possible cause. </p>
  
  <p>First, I am simply adding a primitive to an hash every time the user clicks the mouse button (or if they hold down the mouse button, every time the screen refreshes, which I think happen around 60 times per second). Each time the screen redraws I have the program loop through the hash and redraw all the primitives. If someone holds down their mouse button it will just keep overlapping primitives on top of each other and in other situations the primitives just layer. I can see how that would eventually eat up a bunch of memory in the hash.</p>
  
  <p>I feel that the best solution would be to use some sort of lower level function that simply colors pixels on the screen and doesn't have to store them in an hash. I'm not sure if Gosu supports that. Could someone either help me with this in Gosu or suggest a different method and/or another program to use? Thank you!</p>
  
  <p>(Below is the complete code for my program.)</p>
  
  <pre><code>require 'Gosu'
  require 'socket'
  
  class GameWindow &lt; Gosu::Window
    def initialize
  
      super 1280, 960, false
      self.caption = "Drawz Server"
  
      @background_image = Gosu::Image.new(self, "media/Space.png", true)
  
  
      @player = Player.new(self)
      # Platform is the blank image for the epicycle to be drawn on.
      @earth_image = Gosu::Image.new(self, "media/earth.bmp", true)
      @cursor_image = Gosu::Image.new(self, "media/cursor.bmp", true)
  
      puts "Please enter port..."
      port = gets.strip!
      puts "Server is running."
  
      # Initialized Instance variables for all methods.
      @square_drawing_number = 0
      @client_coordinates_array = []
      @client_coordinates_array_array = []
      @client_quad_hash = {}
      server = TCPServer.open("10.64.8.2", port)
      @client = server.accept
  
      manage_client_data = Thread.new do
              x = 0
              loop do
                  @client_coordinates_array[x] = @client.gets
                  x += 1
              end
          end
  
      @x = 0
      @quad_hash = {}
      # Start up value of things in draw method, because draw is called before update. Hence I put the start up values here so that when draw is called it has location of things in
      # its arguments.
      @cx = 0 
      @cy = 0
    end
  
  
  
  class QuadCoords
      attr_reader :x1, :y1, :x2, :y2, :x3, :y3, :x4, :y4
  
      def initialize(x1, y1, x2, y2, x3, y3, x4, y4)
          @x1 = x1
          @y1 = y1
          @x2 = x2
          @y2 = y2
          @x3 = x3
          @y3 = y3
          @x4 = x4
          @y4 = y4
      end
  end
  
      # Mean't to change location (x and y) and such of things in draw method.
  
      def update
          @cx = mouse_x
          @cy = mouse_y
          @x += 1
          # Adds square locations to hash which is then accessed by draw function to retrieve and draw squares.
          if button_down? Gosu::MsLeft
              @x += 1
              quad_coords_obj = QuadCoords.new(@cx - 5, @cy - 5, @cx, @cy - 5, @cx - 5, @cy, @cx, @cy)
              @quad_hash["quad#{@x}"] = quad_coords_obj
              # Sends location of squares to client for it to draw.
              @client.puts "#{quad_coords_obj.x1}---#{quad_coords_obj.y1}---#{quad_coords_obj.x2}---#{quad_coords_obj.y2}---#{quad_coords_obj.x3}---#{quad_coords_obj.y3}---#{quad_coords_obj.x4}---#{quad_coords_obj.y4}"
          end
  
          if @client_coordinates_array.length &gt; @square_drawing_number
              new_squares_to_add = @client_coordinates_array.length - @square_drawing_number
              @client_coordinates_array[-1 * new_squares_to_add..-1].each do |value|
                  @client_coordinates_array_array &lt;&lt; value.split(/\---/)
              end
              x = 1
              new_squares_to_add.times do
                  @x += 1
                  @client_quad_coords_obj = QuadCoords.new(@client_coordinates_array_array[-1 * x][0].to_i,
                  @client_coordinates_array_array[-1 * x][1].to_i,
                  @client_coordinates_array_array[-1 * x][2].to_i,
                  @client_coordinates_array_array[-1 * x][3].to_i,
                  @client_coordinates_array_array[-1 * x][4].to_i,
                  @client_coordinates_array_array[-1 * x][5].to_i, 
                  @client_coordinates_array_array[-1 * x][6].to_i, 
                  @client_coordinates_array_array[-1 * x][7].to_i)
                  @client_quad_hash["quad#{@x}"] = @client_quad_coords_obj
                  x += 1
                  @square_drawing_number += 1
              end
          end
  
  
      end
  
  
    # Draw is called before update.
    def draw
  
      @background_image.draw(0,0,0)
      @earth_image.draw(295,215,1)
      # x1,y1 = Upper Left Hand Corner; x2,y2 = Lower Left Hand Corner; x3,y3 = Upper Right Hand Corner; x4,y4 = Lower Right Hand Corner
      @quad_hash.each_value do |value|
          draw_quad(value.x1, value.y1, 0xff00ffff, value.x2, value.y2, 0xff00ffff, value.x3, value.y3, 0xff00ffff, value.x4, value.y4, 0xff00ffff, z = 0, mode = :default)
      end
  
      @client_quad_hash.each_value do |value|
          draw_quad(value.x1, value.y1, 0xff00ff00, value.x2, value.y2, 0xff00ff00, value.x3, value.y3, 0xff00ff00, value.x4, value.y4, 0xff00ff00, z = 0, mode = :default)
      end
  
      @cursor_image.draw(@cx, @cy, 1)
  
    end
  
    def button_down(id)
      if id == Gosu::KbEscape
        close
      end
    end
  end
  
  
  
  class Player
      attr_accessor :x, :y, :update_called
    def initialize(window)
      @image = Gosu::Image.new(window, "media/Sun.bmp", false)
    end
  end
  
  
  
  window = GameWindow.new
  window.show
  </code></pre>