I've seen some code to draw filled circles, but not for empty or hollow circles. So I ended up writing a little script to do it for me. The script can create a circle of any size or color and of different thicknesses. The script can also make arcs or partial circles. The circles, unfortunately, are not perfect, although they are pretty close. Sometimes a small pixel-sized gap can form (which you can actually see in the first screen shot). There's also some code in the script that can be used to create gradients within the circle. That code is based on previous work by Ryex. I've made a minor update to the script, it now uses set_pixel instead of fill_rect, as recommended by Modern Algebra.
#==============================================================================
# Extends the Bitmap class with circle drawing functions
# v 1.1 (May 23, 2010) by scanime@gmail.com
#==============================================================================
class Bitmap
#--------------------------------------------------------------------------
# * Draws a hollow circle (or pretty close to it)
# x = x of center coordinate
# y = y of center coordinate
# r = radius of the circle (distance from center)
# c = color of the circle -- ie, Color.new(255, 0, 0)
# thickness = the thickness of the line for the circle
# Defaults to 5.
# percent = to create partial circles, set the size as a percent
# 0.5 makes a half circle, etc.
# Defaults to 1 (a full circle)
# start = the angle of the start of the circle, measured in radians. Useful
# to rotate partial circles.
# Defaults to pi (starts at the top)
#--------------------------------------------------------------------------
def draw_circle(x, y, r, c, thickness = 5, percent = 1, start = Math::PI)
size = Math::PI * 2 * percent
for i in 0...thickness
radians = 0
while radians >= -size
set_pixel(x + r * Math.sin(radians + start), y + r * Math.cos(radians + start), c)
radians = radians - 0.017453293
end
r = r - 1
end
end
#--------------------------------------------------------------------------
# * Draws circular gradients for HP, SP, or whatever
# Based on Ryex's code for gradient bars
#--------------------------------------------------------------------------
def draw_circle_gradient(x, y, radius, c, thickness = 5, percent = 1)
gray = Color.new(100, 100, 100)
white = Color.new(255, 255, 255)
draw_circle(x, y, radius, Color.new(0, 0, 0), thickness)
for i in 0...(thickness - 1)
gr = gray.red * i / (thickness - 1)
gg = gray.green * i / (thickness - 1)
gb = gray.blue * i / (thickness - 1)
draw_circle(x, y, radius - i - 1, Color.new(gr-255, gg-255, gb-255), 1)
end
for i in 0...(thickness / 2)
r = c.red + (white.red - c.red) * i / (thickness / 2 - 1)
g = c.green + (white.green - c.green) * i / (thickness / 2 - 1)
b = c.blue + (white.blue - c.blue) * i / (thickness / 2 - 1)
draw_circle(x, y, radius - thickness / 2 + i, Color.new(r, g, b), 1, percent)
end
for i in 0...(thickness / 2 - 1)
r = c.red * i / (thickness / 2)
g = c.green * i / (thickness / 2)
b = c.blue * i / (thickness / 2)
draw_circle(x, y, radius - thickness / 2 - (thickness / 2 - 1 - i), Color.new(r, g, b), 1, percent)
end
end
end
And I've also written an add-on for the KGC 2D Drawing functions that creates gradient-filled circles. The circles made this way are definitely cleaner looking and don't have the missing pixels that show up sometimes in the circles my script above draws. You can find the KGC 2D Drawing script at http://ytomy.sakura.ne.jp/tkool/rpgtech/tech_xp/draw_function/2d_drawing_xp.html (http://ytomy.sakura.ne.jp/tkool/rpgtech/tech_xp/draw_function/2d_drawing_xp.html). It adds a large collection of tools for drawing 2D shapes. Big props to Mr Wiggles for pointing this collection of functions out to me.
I also added a variant to draw_arc that draws arcs clockwise rather than counter-clockwise.
#==============================================================================
# The following extends the Bitmap class modifications made by
# KGC, available at:
# http://ytomy.sakura.ne.jp/tkool/rpgtech/tech_xp/draw_function/2d_drawing_xp.html.
#
# The functions offer a variety of drawing tools, but this script
# adds gradient filled arcs and circles. To use, place this script below
# the script available in the link above.
#
# v 1.0 (May 23, 2010) by scanime@gmail.com
#==============================================================================
class Bitmap
# Modified version of draw_arc that draws arcs clockwise rather than
# counter-clockwise
def draw_arc_clockwise(*args)
# ????
cx, cy, r, st_ang, end_ang, color, size = _arc_args(args)
return unless cx
# ???????
x = r * Math.cos(Math::PI * st_ang / 180.0)
y = r * -Math.sin(Math::PI * st_ang / 180.0)
dfx = dfy = 0
pr = Integer([100, r].max ** 1.6)
a = 6.3 / pr
pr = pr * (end_ang - st_ang) / 360
# ?????
pr.times { |i|
x, y = x - dfx, y + dfy
dx, dy = x + cx, y + cy
if size == 1
self.set_pixel(dx, dy, color)
else
self.fill_rect(dx, dy, size, size, color)
end
dfx, dfy = a * y, a * x
}
end
#--------------------------------------------------------------------------
# * Draws circular gradients for HP, SP, or whatever
# Based on Ryex's code for gradient bars
# x = x of center coordinate
# y = y of center coordinate
# r = radius of the circle (distance from center)
# c = color of the circle -- ie, Color.new(255, 0, 0)
# thickness = the thickness of the line for the circle
# Defaults to 5.
# percent = to create partial circles, set the size as a percent
# 0.5 makes a half circle, etc.
# Defaults to 1 (a full circle)
# start = the angle of the start of the circle, measured in radians. Useful
# to rotate partial circles.
# Defaults to pi / 2 (starts at the top)
#--------------------------------------------------------------------------
def draw_circle_gradient(x, y, radius, c, t = 5, p = 1, start = Math::PI / 2)
# convert angle from radians to degrees
start_angle = (start * 180 / Math::PI).to_i
end_angle = (360 * p + start_angle).to_i
gray = Color.new(100, 100, 100)
white = Color.new(255, 255, 255)
for i in 0...(t - 1)
gr = gray.red * (t - i) / (t - 1)
gg = gray.green * (t - i) / (t - 1)
gb = gray.blue * (t - i) / (t - 1)
draw_circle(x, y, radius - i - 1, Color.new(gr-255, gg-255, gb-255))
end
for i in 0...(t / 2)
r = c.red + (white.red - c.red) * i / (t / 2 - 1)
g = c.green + (white.green - c.green) * i / (t / 2 - 1)
b = c.blue + (white.blue - c.blue) * i / (t / 2 - 1)
draw_arc_clockwise(x, y, radius - t / 2 + i, start_angle, end_angle, Color.new(r, g, b))
end
for i in 0...(t / 2 - 1)
r = c.red * i / (t / 2)
g = c.green * i / (t / 2)
b = c.blue * i / (t / 2)
draw_arc_clockwise(x, y, radius - t / 2 - (t / 2 - 1 - i), start_angle, end_angle, Color.new(r, g, b))
end
end
end
A basic example of the script:
And something a little more practical looking:
It's attached, cool update.
[edit]
I'm getting an error when i use the "draw_circle_gradient", wrong number of arguments 4 of 6.
i have the command set up like so:
min = 5
max = 10
percent = min / max.to_f if max != 0
# draw_circle_gradient(x, y, radius, c, t = 5, p = 1, start = Math::PI / 2)
self.contents.draw_circle_gradient(300, 300, 80, Color.new(255, 0, 0), 10, percent)
i have the max and min set to fixnum cause i was testing it.
I'm getting an error when i use the "draw_circle_gradient", wrong number of arguments 4 of 6.
i have the command set up like so:
min = 5
max = 10
percent = min / max.to_f if max != 0
# draw_circle_gradient(x, y, radius, c, t = 5, p = 1, start = Math::PI / 2)
self.contents.draw_circle_gradient(300, 300, 80, Color.new(255, 0, 0), 10, percent)
i have the max and min set to fixnum cause i was testing it.
Thanks for the translation! I tried your code, and it seems to work fine on my end. I changed the KGC drawing script to the one you included, just in case. The error sounds like it's not passing all of the arguments when it calls the function for the arc. Does it say which line number is throwing the error? (I'm guessing it's line 479.) Can you add the line "p args" there so that I can see which arguments it isn't passing along?