我一直在修改使用Ruby在Gosu中制作绘图应用程序,但是我遇到了一些高CPU使用率。我知道一个可能的原因。
首先,我只是在每次用户单击鼠标按钮时向一个哈希添加一个原语(或者如果他们按住鼠标按钮,每次屏幕刷新时,我认为每秒大约发生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
答案 0 :(得分:1)
您可以使用TexPlay绘制Gosu :: Image,然后渲染此图像。 http://banisterfiend.wordpress.com/2008/08/23/texplay-an-image-manipulation-tool-for-ruby-and-gosu/ 例如:
image1.paint {
circle 20,20,10, :color => :red
rect 40,40,50,50, :color => :green
pixel 60,60, :color => :blue
}
还有其他选择:RMagick(功能更强大,但安装\分发要复杂得多)和Ashton(它有渲染OpenGL纹理的方法,所以它更快,但需要对OpenGL有所了解)。
答案 1 :(得分: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。