Gosu Forums
Topic Gosu / Extending Gosu / Extending Ruby/Gosu with Inline C
By jlnr (dev) Date 2011-03-08 13:04
(Warning: getting this to work on Windows is probably a pain? :))

I have posted this in a different context before, I think, but I want to point out this technique again (public code snippet by zenspider):

http://p.zenspider.com/gosu-extensions.rb.html

If you have any performance critical, isolated(!) thing that Gosu is missing, you may use this to get an instant performance boost. And when your serious game is ready to be shipped, you can precompile it for Windows (or discuss integrating your feature into Gosu :)).
By erisdiscord Date 2011-03-08 16:05
Since the posted example is mostly about drawing a circle efficiently, I figured I'd share this: An Efficient Way to Draw Approximate Circles in OpenGL. I adapted this algorithm for Chingu and it works great. You only have to calculate sin and cos at the beginning and the rest is essentially matrix multiplication, so it's much faster.

The way I implemented it uses blocks to avoid duplicated code so it may have additional overhead, but I'm not sure how well Ruby optimises those block calls. :)
By Basic Date 2011-03-08 16:15
Since we are talking about circles ;)

Efficient ways to draw a circle?
hmmm, trig functions and floating points?

While I have not benchmarked it on a modern machine (so therefor I could be entirely wrong), an efficient way to draw a circle would be using ints and no trig what soever.

Bresenham's circle algorithm
http://en.wikipedia.org/wiki/Midpoint_circle_algorithm

I've used this on the GBA and this is fast as hell. (GBA has no floating point unit).
By erisdiscord Date 2011-03-08 17:30
Most modern systems (apart from video game consoles and mobiles, I guess) have an FPU for fast floating point math, and they're used behind the scenes with OpenGL anyway. Integer math might give you a bigger performance boost in Ruby since integers are immediate values while floats are objects, but I feel like there's a good balance here between mental cycles and CPU cycles.

I have encountered Bresenham's circle algorithm but somehow it totally slipped my mind because it doesn't initially seem appropriate for OpenGL. Reading about it again, I realise that it could easily be thought of as connecting points on a grid, so it's totally applicable. I'll give it consideration, but I think I'm content for now to use trigonometric functions sparingly.

I think Julian's solution is really clever, and probably has us both beat if you know you're gonna be reusing the same circle. I have a little piece of code that uses TexPlay to generate raster images on demand and caches the results for future use and I think it would work pretty famously as an alternate implementation.

Drawing a circular target might look something like this, for instance:

`class Target  include Drawing    ...    def draw    left, top, size = @x - @radius, @y - @radius, @radius * 2    # Draw the :target layer; the painting operations only get called when the    # layer needs to be repainted.    paint_layer(:target, left, top, size, size, :z => 0) do |canvas|      cx = cy = @radius # for clarity below      canvas.circle cx, cy, @radius,       :color => :red,   :fill => true      canvas.circle cx, cy, @radius * 0.8, :color => :white, :fill => true      canvas.circle cx, cy, @radius * 0.6, :color => :red,   :fill => true      canvas.circle cx, cy, @radius * 0.4, :color => :white, :fill => true      canvas.circle cx, cy, @radius * 0.2, :color => :red,   :fill => true    end  end    def radius= new_radius    @radius = Float(new_radius)        # The :target layer must be redrawn when the radius changes.    invalidate_layer_cache! :target  end  end`

I've tested this system in a small widget library I probably won't finish and it makes drawing pretty fast.
By banister Date 2011-03-09 06:36
TexPlay uses bresenham circle and line routines too :)
By RunnerPack Date 2011-03-09 09:04 Edited 2011-03-09 09:37
By jlnr (dev) Date 2011-03-08 16:17
FWIW my take on the circle example is here :)
By erisdiscord Date 2011-03-08 17:39
My adaptation of the algorithm was meant to provide a faster, backwards-compatible implementation of Chingu's `draw_circle`; if I were going to be writing code that required arbitrary primitives, I'd probably use the "layer caching" thing with TexPlay that I mentioned above. I thought it was pretty clever. I like your solution too, though. :D
By kaBOOM Date 2011-03-09 01:26
Hi. :0  Just in case anyone knows... I want to make a "draw arc" method similar to the draw_line one. Anybody knows the formula?
By jlnr (dev) Date 2011-03-09 04:18
An arc is a partially drawn circle, right? Then you just need to adjust the start and end the for() loop in the posted code.
Topic Gosu / Extending Gosu / Extending Ruby/Gosu with Inline C