我一直在修补使用 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