How to draw Pacman on Bitmap?

● ARCHIVED · READ-ONLY
Started by Jeneeus Guruman 15 posts View original ↗
  1. I don't know if this is the right thread to post this.

    I just want to ask on what line of code that can draw a circle (solid, outline, or anything as long as it draws a circle) in RGSSx (1, 2 - recommended, or 3) (or only in Ruby if there's no such thing existed in RGSS). I also searched the help files in VX and Ace and I've been googling for hours but nothing found.

    I want (to have/to know on how to make) a code to do not just a simple circle but to also can only draw parts of the circle like this:

    Spoiler
    Thanks in advance.

    EDIT: I forgot to tell that I'm not using the image itself to make a circle because I'm making a script that make the circle parts removes from time to time like this one:

    Spoiler
    EDIT 2: I found a script that draws a circle:

    Credits to SephirothSpawn for the script and PK8 for pointing me here.

    Spoiler
    Code:
    #-------------------------------------------------------------------------
    # * Name	 : Draw Circle
    # Info	 : Draws A Circle
    # Author : SephirothSpawn
    # Call Info : Integer X and Y Define Position Center Pt of Circle
    #			 Integer Radius Radius of the Circle to Draw
    #			 Color color Color of the circle to draw
    #-------------------------------------------------------------------------
    def draw_circle(x, y, radius, color = Color.new(255, 255, 255, 255))
    # Starts From Left
    for i in (x - radius)..(x + radius)
    	 # Finds Distance From Center
    	 sa = (x - i).abs
    	 # Finds X Position
    	 x_ = i < x ? x - sa : i == x ? x : x + sa
    	 # Finds Top Vertical Portion
    	 y_ = Integer((radius ** 2 - sa ** 2) ** 0.5)
    	 # Draws Vertical Bar
    	 self.fill_rect(x_, y - y_, 1, y_ * 2, color)
    end
    end
    Now I now only need how to cut the circle.
  2. You can look at this

    http://rgss3help.tk/?p=109

    For a start. Cidiomar has snippets for all sorts of shapes and lines.
  3. Thanks, Tsukihime for the link and Cidomar for the script. But I really need something that make it like these:

  4. With the arrows?
  5. Without arrows. Just the circle. Doesn't matter if filled, outlined, or something as long it's circle.
  6. Code:
    def draw_circle(x, y, r, color = Color.new(0, 0, 0), fill = true, start_angle = 0, end_angle = 0)
            for i in x - r..x + r
                for e in x - r..x + r
                    d = Math.sqrt((i - x).abs ** 2 + (e - x).abs ** 2)
                    cs, sn = Math.acos(i / d), Math.asin(e / d)
                    angle = (sn < 0) ? cs / Math.PI + 180 : cs / Math.PI
                    if (d == r or (d < r and fill)) and ((end_angle < start_angle ? (angle > start_angle and angle < end_angle) : (angle < end_angle or angle > start_angle)) or start_angle == end_angle)
                        self.set_pixel(i, e, color)
                    end
                end
            end
        end
    This is the code to draw a circle:



    Code:
    draw_circle(x, y, r[, color, fill, start_angle, end_angle])
    Parameters in square brackets are optional.

    x: x-pos of center

    y: y-pos of center

    r: radius

    color: color with which to draw the circle

    fill: whether to fill in the circle

    start_angle: angle to start the circle at

    end_angle: angle to end the circle at

    note. to draw a full circle, leave start_angle and end_angle alone or set them to the same number

    example

    Spoiler
    To draw this, assuming center 0, 0 and radius 50:



    Code:
    draw_circle(0, 0, 50, Color.new(50, 50, 50), true, 0, 90)
  7. Ah, geometry. How useful it can be.
  8. ThallionDarkshine said:
    Code:
    def draw_circle(x, y, r, color = Color.new(0, 0, 0), fill = true, start_angle = 0, end_angle = 0)
    for i in x - r..x + r
    for e in x - r..x + r
    d = Math.sqrt((i - x).abs ** 2 + (e - x).abs ** 2)
    cs, sn = Math.acos(i / d), Math.asin(e / d)
    angle = (sn < 0) ? cs / Math.PI + 180 : cs / Math.PI
    if (d == r or (d < r and fill)) and ((end_angle < start_angle ? (angle > start_angle and angle < end_angle) : (angle < end_angle or angle > start_angle)) or start_angle == end_angle)
    self.set_pixel(i, e, color)
    end
    end
    end
    end
    This is the code to draw a circle:



    Code:
    draw_circle(x, y, r[, color, fill, start_angle, end_angle])
    Parameters in square brackets are optional.

    x: x-pos of center

    y: y-pos of center

    r: radius

    color: color with which to draw the circle

    fill: whether to fill in the circle

    start_angle: angle to start the circle at

    end_angle: angle to end the circle at

    note. to draw a full circle, leave start_angle and end_angle alone or set them to the same number

    example

    Spoiler
    To draw this, assuming center 0, 0 and radius 50:



    Code:
    draw_circle(0, 0, 50, Color.new(50, 50, 50), true, 0, 90)
    A very big thanks but there's an out of range argument error in this line:



    Code:
    cs, sn = Math.acos(i / d), Math.asin(e / d)
    If you don't have time to fix this, I'll try to fix this myself and find what is wrong.

    EDIT: And set_pixel method causes lag. It's the entire loop which lags when updates.
  9. Fixed it. Sorry, but I can't make a filled circle, but I can make an outline.



    Code:
    def draw_circle(x, y, r, color = Color.new(0, 0, 0), start_angle = 0, end_angle = 0)
            for i in -r..r
                xpos = x + i.to_f
                ypos = Math.sqrt(r ** 2 - (xpos - x) ** 2).to_f
                cs, sn1, sn2 = Math.acos(i / r), Math.asin(ypos / r), Math.asin(-ypos / r)
                a1 = (cs > Math.PI / 2) ? 360 - cs * 180 / Math.PI : cs * 180 / Math.PI + 180
                a2 = cs * 180 / Math.PI
                self.set_pixel(xpos, ypos + y, color) if ((end_angle < start_angle ? (a1 > start_angle and a1 < end_angle) : (a1 < end_angle or a1 > start_angle)) or start_angle == end_angle)
                self.set_pixel(xpos, y - ypos, color) if ((end_angle < start_angle ? (a2 > start_angle and a2 < end_angle) : (a2 < end_angle or a2 > start_angle)) or start_angle == end_angle)
            end
        end
    Same parameters as before, just no fill.
  10. it's working now but it won't give me Pacman. I mean, it's always in full circle even I set it in constant 180 or 270 degress.

    EDIT: I found out that the middle-left and middle-right most are not included in set_pixel.
  11. I would recommend using Cidomars script that Tsukihime mentioned. It uses the Mid-Point Circle algoritm which is very fast compared to using trigonometry. The Mid-Point Circle algoritm draws in octants, so in 8 portions, exactly what you need.

    You could remove two "set_pixel" lines from "draw_circle" to draw an incomplete circle such that angles 180-270 are not drawn. After that you could use Brensenham's Line algoritm to draw two lines from the two disconnected points toward the center (or in the case of 180-270, just a couple straight lines).

    If you want to fill only a partial circle, again remove one or more "verts <<" lines from "fill_circle." This time instead of Bresenham's Line algoritm to fill in the rest, you would set singular points on the Y axis (assuming left or right facing pac-man) along the slope towards the center. Bresenham's Line may set multiple points which isn't necessary in scan-lines. Two scan-lines would be required if you want to fill circles with angles 315 to 45 or angles 135 to 225 missing.

    Either way, set_pixel is still slow so this is something you would only want to do once and cache/save the result for later use.
  12. I change my use of the method to Cidomars' and I already have the quarter and semi circles (0, 90, 180, 270, and 360 degress) work. If anyone can help me with this before I solve this problem, you can.

    Below is my edited code from Cidomars' draw_circle method.

    Spoiler
    Code:
    def draw_circle(cx, cy, rad, color, thick = 1, start_angle = 0, end_angle = 90)
         rad -= 1
         error = -rad
         x, y = rad, 0
         while (x >= y)
              # Draw a pixel in each octet
              self.fill_rect(cx + x, cy + y, thick, thick, color) if (end_angle >= 270)
    	      self.fill_rect(cx - x, cy + y, thick, thick, color) if (x != 0 && end_angle > 90)
    	      self.fill_rect(cx + x, cy - y, thick, thick, color) if (y != 0 && end_angle > 270)
    	      self.fill_rect(cx - x, cy - y, thick, thick, color) if (x != 0 && y != 0 && end_angle >= 90)
              if (x != y)
                   self.fill_rect(cx + y, cy + x, thick, thick, color) if (end_angle > 180)
                   self.fill_rect(cx - y, cy + x, thick, thick, color) if (y != 0 && end_angle >= 180)
                   self.fill_rect(cx + y, cy - x, thick, thick, color) if (x != 0 && end_angle >= 360)
                   self.fill_rect(cx - y, cy - x, thick, thick, color) if (y != 0 && x != 0 && end_angle > 0)
              end
              #
              #-----
              # Error correction
              error += y
              y	 += 1
              error += y
              if (error >= 0)
                   error -= x
                   x	 -= 1
                   error -= x
                   end
              print(x.to_s + " : " + y.to_s)
         end
    end
    EDIT: Also works for angles divisible by 45 (45, 135, 225, and 315 degrees). Anyone can solve this having angles not mentioned here?
  13. Finally done with the angled circle.

    In my modded code from Cidomar, I placed additional parameters, thick, start_angle, and end_angle. The angle (0 degrees) starts at the middle top and rotates counter-clockwise until 360. Start_angle doesn't work yet and you can help me too (if you want).

    Spoiler
    Code:
      def draw_circle(cx, cy, rad, color, thick = 1, start_angle = 0, end_angle = 280)
        rad -= 1
        error   = -rad
        x, y    = rad, 0
        while (x >= y)
    	  self.fill_rect(cx + x, cy + y, thick, thick, color) if (end_angle >= 270 - (61 * y / rad))
    	  self.fill_rect(cx - x, cy + y, thick, thick, color) if (x != 0 && end_angle > 90 + (61 * y / rad))
    	  self.fill_rect(cx + x, cy - y, thick, thick, color) if (y != 0 && end_angle > 270 + (61 * y / rad))
    	  self.fill_rect(cx - x, cy - y, thick, thick, color) if (x != 0 && y != 0 && end_angle >= 90 - (61 * y / rad))
    	  if (x != y)
    	    self.fill_rect(cx + y, cy + x, thick, thick, color) if (end_angle > 180 + (61 * y / rad))
    	    self.fill_rect(cx - y, cy + x, thick, thick, color) if (y != 0 && end_angle >= 180 - (61 * y / rad))
    	    self.fill_rect(cx + y, cy - x, thick, thick, color) if (x != 0 && end_angle >= 360 - (61 * y / rad))
    	    self.fill_rect(cx - y, cy - x, thick, thick, color) if (y != 0 && x != 0 && end_angle > (61 * y / rad))
    	  end
    	  error += y
    	  y	 += 1
    	  error += y
    	  if (error >= 0)
    	    error -= x
    	    x	 -= 1
    	    error -= x
    	  end
        end
      end
  14. I'll work on this tomorrow, and once someone's completed it, i'll make a dll for it to speed it up a lot.
  15. Thanks. I already solved this problem but maybe yours are better. I'll wait till then.