Bitmap Addons 1.0 [VXA] [Port]

0 Members and 1 Guest are viewing this topic.

*
Rep:
Level 82
Bitmap Addons
Version: 1.0
Author: modern algebra, ported by Logan Forrests
Date: April 29, 2013

Version History


  • <Version 1.0> 2013.04.29 - Original Release

Planned Future Versions

  • None scheduled. However, updates may be made in the future and suggestions will be considered.

Description


This is a Scripter's Tool, not a standalone script. If you are not a scripter, then you will only want this script if it is used by a script that you do want.

This script adds methods into Bitmap for drawing ellipses, as well as one for drawing a straight line.

Features

  • Can greyscale a designated Rect object within a bitmap
  • Can now set a default opacity (and greyscale boolean) for the methods blt and stretch_blt to use
  • Can draw outline or fill an ellipse (or circle)
  • Can draw rectangles with rounded edges
  • Can draw diagonally oriented lines

Screenshots

Check out the original VX thread for a screenshot: http://rmrk.net/index.php/topic,32286.0.html


Instructions

Please see header of the script for instructions.

Script


Code: [Select]
#==============================================================================
#  Bitmap Addons for RPG Maker VXAce
#  Version: 1.0
#  Author: modern algebra (rmrk.net)
#  Ported by: Logan Forrests (rmrk.net)
#  Date: April 24 2013
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#  Description:
#    This is a simple scripter's tool with methods added into Bitmap for drawing
#   ellipses, as well as one for drawing a straight line. The methods it adds
#   are:
#      outline_ellipse
#      fill_ellipse
#      fill_rounded_rect
#      draw_line
#      greyscale
#
#    It also allows you to change opacity and greyscale of blt and stretch_blt
#   externally with the public instance variables:
#
#      bitmap.ma_default_opacity = [0-255]
#      bitmap.ma_default_greyscale = false
#
#    These codes allow you to be able to change the opacity or greyscale what a
#   method like draw_character draws without overwriting it entirely. You want
#   it to draw the character opaque or grey if the character is dead? All you
#   need to do is change the default opacity or greyscale before running the
#   method.
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#  Instructions:
#    To use this, simply put it above main. For some of these, it is necessary
#   to create an ellipse object and pass it as an argument. You can create an
#   ellipse with the code:
#
#     Ellipse.new (x, y, a, b)
#       x : the top left x position
#       y : the top left y position
#       a : the width of oval from origin to the side
#       b : the height of oval from origin. If nil, then a is radius of circle
#
#   There are four new methods added to bitmap that can be used:
#
#      outline_ellipse (ellipse[, colour, width, steps])
#        ellipse : the ellipse object being drawn
#        colour  : the colour of the outline. Assumed font colour if not specified
#        width   : the thickness of the line. Assumed 1 if not specified
#        steps   : can set a number of steps for increased accuracy. If not
#                  specified, it will estimate the number of steps
#
#      fill_ellipse (ellipse[, colour, steps])
#        ellipse : the ellipse object being drawn
#        colour  : the colour of the ellipse. Assumed font colour if not specified
#        steps   : can set a number of steps for increased accuracy. If not
#                  specified, it will estimate the number of steps
#
#      fill_rounded_rect (ellipse[, colour, w)
#        ellipse : the ellipse object being drawn
#        colour  : the colour of the outline. Assumed font colour if not specified
#        w       : the number of pixels at which to round the edge.
#
#      draw_line
#        x0      : the initial x coordinate
#        y0      : the initial y coordinate
#        x1      : the end x coordinate
#        y1      : the end y coordinate
#        colour  : the colour of the outline. Assumed font colour if not specified
#
#      greyscale (rect)
#        rect : the Rect object over which that part of the bitmap will be greyed.
#==============================================================================
# ** Ellipse
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#  Stores an ellipse object.
#==============================================================================

class Ellipse < Rect
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # * Public Instance Variables
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  attr_reader   :h # The x position of the origin
  attr_reader   :k # The y position of the origin
  alias a width
  alias b height
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # * Object Initialization
  #     x : the top left x position
  #     y : the top left y position
  #     a : the width of oval from origin to the side
  #     b : the height of oval from origin. If nil, then a is radius of circle
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  def initialize(x, y, a, b = nil)
    b = a if b.nil?
    super(x, y, a, b)
    @h = x + a
    @k = y + b
  end
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # * Within?
  #    x : the x coordinate being tested
  #    y : the y coordinate being tested
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  def within?(x, y)
    x_square = ((x - @h)*(x - @h)).to_f / (a*a)
    y_square = ((y - @k)*(y - @k)).to_f / (b*b)
    # If "radius" <= 1, then it must be within the ellipse
    return (x_square + y_square) <= 1
  end
end

#==============================================================================
# ** Bitmap
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#  Summary of Changes:
#    attr_accessor - ma_default_opacity, ma_default_greyscale
#    aliased methods - blt; stretch_blt
#    new methods - fill_ellipse; outline_ellipse; fill_rounded_rect; draw_line
#==============================================================================

class Bitmap
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # * Public Instance Variables
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  attr_accessor :ma_default_opacity
  attr_accessor :ma_default_greyscale
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # * Object Initialization
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  alias mdnabr_dfltopac_init_bmpadon_2lh3 initialize unless $@
  def initialize(*args)
    # Initialize new public instance variable
    @ma_default_opacity = 255
    @ma_default_greyscale = false
    # Run Original Method
    mdnabr_dfltopac_init_bmpadon_2lh3(*args)
  end
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # * BLT
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  alias mnalgba_bitmapaddons_opacdflt_blt_2hb5 blt unless $@
  def blt(x, y, src_bmp, src_rect, opacity = @ma_default_opacity, grey = @ma_default_greyscale, *args)
    if grey
      src_bmp = src_bmp.dup
      src_bmp.greyscale(src_rect)
    end
    # Run Original Method
    mnalgba_bitmapaddons_opacdflt_blt_2hb5(x, y, src_bmp, src_rect, opacity, *args)
  end
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # * Stretch BLT
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  alias modrnalgbra_strtchblt_bmpdons_opc_0lk2 stretch_blt unless $@
  def stretch_blt(dest_rect, src_bmp, src_rect, opacity = @ma_default_opacity, grey = @ma_default_greyscale, *args)
    if grey
      src_bmp = src_bmp.dup
      src_bmp.greyscale(src_rect)
    end
    # Run Original Method
    modrnalgbra_strtchblt_bmpdons_opc_0lk2(dest_rect, src_bmp, src_rect, opacity, *args)
  end
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # * Outline Ellipse
  #    ellipse : the ellipse being drawn
  #    width   : the width of the bar
  #    colour  : the colour of the outline
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  def outline_ellipse(ellipse, colour = font.color, width = 1, steps = 0)
    # For neatness, define local variables a and b to the ellipse variables
    a, b = ellipse.a, ellipse.b
    # Use Ramanujan's approximation of the Circumference of an ellipse
    steps = Math::PI*(3*(a + b) - Math.sqrt((3*a + b)*(a + 3*b))) if steps == 0
    radian_modifier = (2*Math::PI) / steps
    for i in 0...steps
      t = (radian_modifier*i) % (2*Math::PI)
      # Expressed parametrically:
      #   x = h + acos(t), y = k + bsin(t) : where t ranges from 0 to 2pi
      x = (ellipse.h + (a*Math.cos(t)))
      y = (ellipse.k + (b*Math.sin(t)))
      set_pixel(x, y, colour)
    end
    # Thicken the line
    if width > 1
      ellipse = Ellipse.new(ellipse.x + 1, ellipse.y + 1, ellipse.a - 1, ellipse.b - 1)
      outline_ellipse(ellipse, colour, width - 1, steps)
    end
  end
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # * Fill Ellipse
  #    ellipse : the ellipse being drawn
  #    colour  : the colour of the outline
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  def fill_ellipse(ellipse, colour = font.color, steps = 0)
    # For neatness, define local variables a and b to the ellipse variables
    a, b = ellipse.a, ellipse.b
    # Use Ramanujan's approximation of the Circumference of an ellipse
    steps = Math::PI*(3*(a + b) - Math.sqrt((3*a + b)*(a + 3*b))) if steps == 0
    radian_modifier = (2*Math::PI) / steps
    for i in 0...(steps / 2)
      t = (radian_modifier*i)
      # Expressed parametrically:
      #   x = h + acos(t), y = k + bsin(t) : where t ranges from 0 to 2pi
      x = ellipse.h + (a*Math.cos(t))
      y = ellipse.k - (b*Math.sin(t))
      fill_rect(x, y, 1, 2*(ellipse.k - y), colour)
    end
  end
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # * Fill Rounded Rectangle
  #    rect    : the rectangle being drawn
  #    colour  : the colour of the outline
  #    w       : the number of pixels to cover by rounding
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  #  Used to fill a rectangle with rounded corners
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  def fill_rounded_rect(rect, colour = font.color, w = 8)
    # Draw Body of the rectangle
    fill_rect(rect.x + w, rect.y, rect.width - 2*w, rect.height, colour)
    # Draw Left Vertical Rect
    fill_rect(rect.x, rect.y + w, w, rect.height - 2*w, colour)
    # Draw Right Vertical Rect
    x = rect.x + rect.width - w
    fill_rect(x, rect.y + w, w, rect.height - 2*w, colour)
    # Make a circle
    circle = Ellipse.new(0, 0, w)
    for i in 0...w
      for j in 0...w
        # Upper Left Corner
        set_pixel(rect.x + i, rect.y + j, colour) if circle.within?(i, j)
        # Upper Right Corner
        set_pixel(rect.x + rect.width - w + i, rect.y + j, colour) if circle.within?(i + w, j)
        # Bottom Left Corner
        set_pixel(rect.x + i, rect.y + rect.height - w + j, colour) if circle.within?(i, j + w)
        # Bottom Right Corner
        set_pixel(rect.x + rect.width - w + i, rect.y + rect.height - w + j, colour) if circle.within?(i + w, j + w)
      end
    end
  end
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # * Draw Line
  #    x0, y0 : the coordinates of the start of the line.
  #    x1, y1 : the coordinates of the end of the line.
  #``````````````````````````````````````````````````````````````````````````
  #  This uses Bresenham's algorithm to draw a line
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  def draw_line(x0, y0, x1, y1, colour = font.color)
    # Set boolean for steep lines
    steep = (y1 - y0).abs > (x1 - x0).abs
    if steep
      # Reflect across y=x
      tmp = x0
      x0, y0 = y0, tmp
      tmp = x1
      x1, y1 = y1, tmp
    end
    # If in negative direction
    if x0 > x1
      # Swap initial points
      tmp = x0
      x0, x1 = x1, tmp
      tmp = y0
      y0, y1 = y1, tmp
    end
    ystep = y0 < y1 ? 1 : -1
    deltax = x1 - x0
    deltay = (y1 - y0).abs
    error = deltax / 2
    y = y0
    # Advance by Rows
    for x in x0.to_i...x1.to_i
      steep ? set_pixel(y, x, colour) : set_pixel(x, y, colour)
      error -= deltay
      if error < 0
        y += ystep
        error += deltax
      end
    end
  end
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  # * GreyScale
  #    rect : the rect to greyscale
  #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  def greyscale(rect = Rect.new(0, 0, self.width, self.height))
    # For each pixel in chosen rect of the bitmap
    for i in rect.x...rect.x + rect.width
      for j in rect.y...rect.y + rect.height
        colour = self.get_pixel(i,j)
        # Get the weighted average of the pixels for a proper shade of grey
        grey_pixel = (colour.red*0.3 + colour.green*0.59 + colour.blue*0.11)
        colour.red = colour.green = colour.blue = grey_pixel
        # Set the pixel to the new shade of grey
        self.set_pixel(i,j,colour)
      end
    end
  end
end

Credit


    Original Creator
    • modern algebra

    Ported to VXA
    • Logan Forrests

    Thanks

      This script uses:

      • Ramanujan's approximation of the Circumference of an ellipse
      • Bresenham's algorithm to draw a line

    Support


    Please post in this thread for support. Someone will help you as soon as possible.

    Known Compatibility Issues

    None known as of April 24, 2013.

    Author's Notes


    The script remains unchanged with the exception of formatting changes to allow the script to work with RGSS3. As such, credit is wholly due to modern algebra. Please ensure that you credit the original author. It is optional to include the porter's name.

    Whilst no current plans exist to increase the options available, should the script be updated, the details on who to credit will likely change to reflect. In that event, please ensure that you check your version of the script for further information on how to properly credit the use of this script.

    Terms of Use
    This script adopts the Terms of Use which can be found here: http://rmrk.net/index.php/topic,45481.0.html[/list][/list]
    (Why do I always feel like it's the end of the world and I'm the last man standing?)