2

Ruby を使用して Gosu で描画アプリケーションを作成しようとしていますが、CPU 使用率が高くなります。考えられる原因の 1 つを知っています。

まず、ユーザーがマウス ボタンをクリックするたびに (またはマウス ボタンを押したままにしておくと、画面が更新されるたびに、1 秒あたり約 60 回発生すると思われます)、プリミティブをハッシュに追加するだけです。画面が再描画されるたびに、プログラムにハッシュをループさせ、すべてのプリミティブを再描画させます。誰かがマウス ボタンを押したままにすると、プリミティブが重なり合ったままになり、他の状況ではプリミティブが単にレイヤー化されます。それが最終的にハッシュ内の大量のメモリを消費することがわかります。

最良の解決策は、画面上のピクセルを単純に色付けし、それらをハッシュに保存する必要のない、ある種の低レベル関数を使用することだと思います。Gosu がそれをサポートしているかどうかはわかりません。誰かがGosuでこれを手伝ってくれるか、別の方法や別のプログラムを使用することを提案できますか? ありがとうございました!

(以下は私のプログラムの完全なコードです。)

require 'Gosu'
require 'socket'

class GameWindow < 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 > @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 << 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
4

2 に答える 2

1

Ashton gem を使用してテクスチャに直接レンダリングすることをお勧めします - TexPlay や​​他のソフトウェア レンダリングとは異なり、これはハードウェア アクセラレーションであるため、非常に高速です。Ashton::Texture#render を使用すると、描画操作を画面に描画するのと同じ速さでテクスチャにキャッシュできます。

def initialize(...)
  # WindowBuffer is just an Ashton::Texture that is the same size as the window
  @draw_buffer = Ashton::WindowBuffer.new 
  ...
end

def update()
  @draw_buffer.render do
    # Perform new gosu drawing actions (e.g. draw_quad)
    # here to draw directly into the texture.
    # Both the local ones and the ones pulled from the network.
  end
end

def draw()
  # Since you are drawing things in the order they should appear,
  # you don't need to worry about Z values.
  @background_image.draw 0, 0, 0
  @earth_image.draw 295, 215, 0
  @draw_buffer.draw 0, 0, 0
  @cursor_image.draw @cx, @cy, 0
end

また、テキストの印刷は実際には非常に遅いため、すべての更新/描画で実行すると FPS に影響することに注意してください。

于 2013-09-04T11:28:24.383 に答える