RMRK is retiring.
Registration is disabled. The site will remain online, but eventually become a read-only archive. More information.

RMRK.net has nothing to do with Blockchains, Cryptocurrency or NFTs. We have been around since the early 2000s, but there is a new group using the RMRK name that deals with those things. We have nothing to do with them.
NFTs are a scam, and if somebody is trying to persuade you to buy or invest in crypto/blockchain/NFT content, please turn them down and save your money. See this video for more information.
[XP] Drawing Circles

0 Members and 2 Guests are viewing this topic.

**
Rep: +0/-0Level 81
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.

Code: [Select]
#==============================================================================
#  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. 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.
Code: [Select]
#==============================================================================
# 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:

Spoiler for Screenshot:

And something a little more practical looking:

Spoiler for Screenshot:
« Last Edit: May 24, 2010, 02:21:43 PM by scanime »

*****
Rep:
Level 84
This text is way too personal.
Bronze - GIAW 11 (Hard)Silver - GIAW Halloween
Looks cute.

Too bad it's not for VX, or I might have stolen this :P

*
Rep:
Level 97
2014 Most Unsung Member2014 Best RPG Maker User - Engine2013 Best RPG Maker User (Scripting)2012 Best Member2012 Best RPG Maker User (Scripting)2012 Favorite Staff Member2012 Most Mature MemberSecret Santa 2012 ParticipantProject of the Month winner for July 20092011 Best Use of Avatar and Signature Space2011 Best RPG Maker User (Scripting)2011 Most Mature Member2011 Favourite Staff Member2011 Best Veteran2010 Most Mature Member2010 Favourite Staff Member
I don't see anything that would make this not work in VX. I could just be missing something though.

Anyway, nice job scanime. Since you are only filling one pixel at a time though, I would recommend the method:

Code: [Select]
set_pixel (x, y, colour)

It's a little more direct.
« Last Edit: May 21, 2010, 02:31:23 AM by modern algebra »

*****
Rep:
Level 84
This text is way too personal.
Bronze - GIAW 11 (Hard)Silver - GIAW Halloween
Oh never mind, it did work. I was sure that VX's bitmap method would screw it up, but I guess I was wrong. Great job Scan.

****
Rep:
Level 83
This is cool that you made this, im sure that this took a lot of work.  Will you be adding more features to it?

isn't there a compilation script that allows you to draw all kinds of objects in 2D in the base class?
« Last Edit: May 21, 2010, 09:33:21 AM by Mr_Wiggles »
Spoiler for:
METALFRESH is a paint contractor that specializes in refinishing metal and vinyl siding. We paint metal buildings as well as siding on homes.

We also

    Refinish decks
    Do custom interior painting
    Strip wallpaper
    Refinish cedar siding
    Metal front doors and sidelights
    Metal garage and service doors
    Grained fiberglass doors

    If your structure is *RUSTED *FADED *CHALKING *IN NEED OF COLOR CHANGE, we can fix it with a guarentee!

northern Illinois and southern Wisconsin.

http://metalfreshcoatings.com


**
Rep: +0/-0Level 81
Thanks all!  I'll definitely be updating the script with set_pixel (thanks, MA!) and I'm planning on adding a few other functions.  I'll at least be adding a way to draw an arc from one point on the circle to another by using radians instead of using a percentage.  The percentage just made it easier for making circle-shaped gradient bars.

The KGC_Drawing 2D tools look like they have a lot of features... I'll definitely take a look at them.  I especially like the way the functions can handle multiple arguments... I never thought of that with Ruby before!

****
Rep:
Level 83
The KGC_Drawing 2D tools look like they have a lot of features... I'll definitely take a look at them.  I especially like the way the functions can handle multiple arguments... I never thought of that with Ruby before!

I have the script translated into English already i can send it to you if you'd like.
Spoiler for:
METALFRESH is a paint contractor that specializes in refinishing metal and vinyl siding. We paint metal buildings as well as siding on homes.

We also

    Refinish decks
    Do custom interior painting
    Strip wallpaper
    Refinish cedar siding
    Metal front doors and sidelights
    Metal garage and service doors
    Grained fiberglass doors

    If your structure is *RUSTED *FADED *CHALKING *IN NEED OF COLOR CHANGE, we can fix it with a guarentee!

northern Illinois and southern Wisconsin.

http://metalfreshcoatings.com


**
Rep: +0/-0Level 81
Okay, I've made a minor update to my script, and added a new script that works with the KGC Drawing tools.  I've updated my original post with the new code.

I have the script translated into English already i can send it to you if you'd like.

I wish I had checked the forums over the weekend!  That would be a great help, thanks.

****
Rep:
Level 83
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:
Code: [Select]
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.
« Last Edit: May 24, 2010, 06:04:22 PM by Mr_Wiggles »
Spoiler for:
METALFRESH is a paint contractor that specializes in refinishing metal and vinyl siding. We paint metal buildings as well as siding on homes.

We also

    Refinish decks
    Do custom interior painting
    Strip wallpaper
    Refinish cedar siding
    Metal front doors and sidelights
    Metal garage and service doors
    Grained fiberglass doors

    If your structure is *RUSTED *FADED *CHALKING *IN NEED OF COLOR CHANGE, we can fix it with a guarentee!

northern Illinois and southern Wisconsin.

http://metalfreshcoatings.com


**
Rep: +0/-0Level 81
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:
Code: [Select]
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?

****
Rep:
Level 83
yea hold on a sec.

yea it is line 479
« Last Edit: May 24, 2010, 06:41:59 PM by Mr_Wiggles »
Spoiler for:
METALFRESH is a paint contractor that specializes in refinishing metal and vinyl siding. We paint metal buildings as well as siding on homes.

We also

    Refinish decks
    Do custom interior painting
    Strip wallpaper
    Refinish cedar siding
    Metal front doors and sidelights
    Metal garage and service doors
    Grained fiberglass doors

    If your structure is *RUSTED *FADED *CHALKING *IN NEED OF COLOR CHANGE, we can fix it with a guarentee!

northern Illinois and southern Wisconsin.

http://metalfreshcoatings.com


**
Rep: +0/-0Level 81
Huh, it's breaking when it draws just the circle, then, and not the arc like I thought.  They're basically the same thing, but the circle automatically goes from 0 to 360 degrees.  So let's try changing line 67 of my code from this:

draw_circle(x, y, radius - i - 1, Color.new(gr-255, gg-255, gb-255))

To this:

draw_arc(x, y, radius - i - 1, 0, 360, Color.new(gr-255, gg-255, gb-255))

And see if that works.

****
Rep:
Level 83
yea it works but when i was using it it seemed to lag a lot. i was using it in my HUD, and i have a limit on the script so that it will only update when its time, (every 10 frames) i suppose i could put another limiter on the bar so that it will update less often or if the old value changed.

[edit]
did that, but still lags when the value changes any suggestions? (i have it update only when the actor's hp changes, but there is some noticeable lag when it does this.)
« Last Edit: May 26, 2010, 12:04:39 AM by Mr_Wiggles »
Spoiler for:
METALFRESH is a paint contractor that specializes in refinishing metal and vinyl siding. We paint metal buildings as well as siding on homes.

We also

    Refinish decks
    Do custom interior painting
    Strip wallpaper
    Refinish cedar siding
    Metal front doors and sidelights
    Metal garage and service doors
    Grained fiberglass doors

    If your structure is *RUSTED *FADED *CHALKING *IN NEED OF COLOR CHANGE, we can fix it with a guarentee!

northern Illinois and southern Wisconsin.

http://metalfreshcoatings.com


**
Rep: +0/-0Level 81
yea it works but when i was using it it seemed to lag a lot. i was using it in my HUD, and i have a limit on the script so that it will only update when its time, (every 10 frames) i suppose i could put another limiter on the bar so that it will update less often or if the old value changed.

[edit]
did that, but still lags when the value changes any suggestions? (i have it update only when the actor's hp changes, but there is some noticeable lag when it does this.)

Glad to know the fix worked!

How much lag are you seeing? If I have four gradient circles, the fps will drop to 25-35 if they are redrawn all at once.  Like you, I've got it set up on my HUD so that the circles are only redrawn when HP or SP changes.  That's using the KGC drawing methods.  Using my original stand-alone script, the framerate changes to 33-36, so it's a little bit faster, but the lag is still noticeable sometimes.  KGC draws better circles, but that requires more calls to set_pixel, which slows it down a bit more.  I don't know if there's a good way to speed up the process.  If a filled circle would work, it could be drawn faster, but the hollow circles require a lot of calls to set_pixel.

****
Rep:
Level 83
ah, well that makes sense. i bet it could be how i have it set up (81 diameter, 7 thickness) but its only one circle.

well im still working on my game and ATM it runs at 34 - 38 fps (i blame my pc), when the hp changes it will drop down to 21 - 26 fps.
Spoiler for:
METALFRESH is a paint contractor that specializes in refinishing metal and vinyl siding. We paint metal buildings as well as siding on homes.

We also

    Refinish decks
    Do custom interior painting
    Strip wallpaper
    Refinish cedar siding
    Metal front doors and sidelights
    Metal garage and service doors
    Grained fiberglass doors

    If your structure is *RUSTED *FADED *CHALKING *IN NEED OF COLOR CHANGE, we can fix it with a guarentee!

northern Illinois and southern Wisconsin.

http://metalfreshcoatings.com