Alex F. wrote:
doesn’t work at all if thread.join is called, but runs
pretty smoothly (about 8s total) otherwise. At some level
you’ll also be caught by the granularity of Ruby’s thread
time slices (10ms IIRC), and garbage collection, which is
taking up to 9ms tracking wxRuby objects alone in your
example.
OK, so avoid excessive object creation… Oh, yes, and I forgot
(again) to mention I’m on Windows, as are my main target users.
Interesting that the thread handling seems to be so much better on
OSX.
I see a couple of further potential optimisations in your
code which improve smoothness for me:
- Take the calls to surface.pen= and surface.pen.cap= out
of the 30.times loop.- See whether the drawing could be more efficiently done
with a single draw_polygon (which acccepts an Array of
Wx::Points)
It only happens to look like a polygon - my actual game needs to draw
individual lines (in varying colors and line widths). But that’s OK,
because your below suggestion allowed me to draw everything at decent
speed…
Another untested possibility to improve perceived
smoothness might be to drive the animation from a
Wx::Timer. Have it run at regular intervals, calling
window.refresh to invalidate the window, then copy from the
bitmap inside an evt_paint handler.
This was the key. It’s drawing 300 lines in under 33 milliseconds
now, even on my laptop. The close button and window dragging respond
immediately.
require ‘rubygems’
require ‘wx’
class MyApp < Wx::App
def on_init
#Containing frame.
frame = Wx::Frame.new(nil, :size => [300, 300])
frame.show
#Offscreen drawing buffer.
buffer = Wx::Bitmap.new(300, 300)
#Displays drawing.
window = Wx::Window.new(frame, :size => [300, 300])
window.evt_paint do |event|
update_window(window, buffer)
end
#Initialize drawing loop counter.
@i = 0
#Animate periodically.
timer_id = Wx::ID_HIGHEST + 1
t = Wx::Timer.new(self, timer_id)
evt_timer(timer_id) {animate(window, buffer)}
t.start(33)
end
def animate(window, buffer)
green_pen = Wx::Pen.new(Wx::Colour.new(128, 255, 128), 3)
black_pen = Wx::Pen.new(Wx::Colour.new(0, 0, 0), 0)
buffer.draw do |surface|
#Clear screen.
surface.pen = black_pen
surface.brush = Wx::BLACK_BRUSH
surface.draw_rectangle(0, 0, 300, 300)
#Draw lines.
surface.pen = green_pen
surface.pen.cap = Wx::CAP_ROUND
300.times do |j|
x = @i + j
surface.draw_line(x, 0, x+100, 100)
end
end
#Update screen.
update_window(window, buffer)
@i += 1
@i = 0 if @i > 300
end
def update_window(window, buffer)
window.paint do |dc|
#Copy the buffer to the viewable window.
dc.draw_bitmap(buffer, 0, 0, false)
end
end
end
app = MyApp.new
app.main_loop
Now to see if I can get similar results from the game itself. Thanks
to everyone for the assistance!
-Jay McGavren
http://jay.mcgavren.com/zyps