Experiments with ruby-processing (processing-2.2.1) and JRubyArt for processing-3.0

Wednesday, 14 April 2010

An Translation Exercise (Very Clever Pseudo 3D Animation)

I've created a little ruby script for myself that translates (somewhat imperfectly) vanilla processing (ie. *.pde files) to ruby processing. Here is the tidied up version of a cool sketch I found on open-processing.

# Made by Jared "BlueThen" C.
# November 5, 2009.
# www.bluethen.com
# translated to ruby processing by monkstone April 14 2010
# variable a is used for determining the shape's y position, coupled with the distance they are from the center.
# setup(), the first function called when the applet is started

attr_reader :a, :y

def setup()
  @a = 0
  @y = 0
  # the applet is set to 500 pixels by 500 pixels
  size(500, 500)
  # RGB mode set to maximum of 6, since we'll be using 6 colors. 0 for black, 6 for white, and everything in between.
  color_mode(RGB, 6)
  # The stroke color is used to determine the border color of each quadrilateral.
  stroke(0)
  # frame rate is set to 30.
  frame_rate(30)
end

def draw()

  # a is decreased by 0.08. it represents the amount of radians the height of our boxes changes, and their speed.
  # if we did nothing to a, then none of our shapes will move, so a is a key component in our formulas.

  @a -= 0.08
  # screen is cleared and background is set to 6 (white).
  background(6)  

  # (x, z) is the ground, while y is vertical)  
  (-7..7).each do |x# loop over range for the x axis
    (-7..7).each do |z# loop over range for the z axis
    
      # The y variable is set to determine the height of the box.
      # We use formula radius * cos(angle) to determine this.
      # Since cosine, when graphed, creates a wave, we can use this to have the boxes transition from small to big smoothly.
      # The radius pretty much stands for our range. cosine alone will return values between -1 and 1, so we multiply this
      # by 24 to increase this value. the formula will return something in between -24 and 24.
      # The angle is in radians. an entire loop (circle) is 2PI radians, or roughly 6.283185.
      # distance is used to create the circular effect. it makes the boxes of the same radius around the center similar.
      # The distance ranges from 0 to 7, so 0.55 * distance will be between 0 and 3.85. this will make the highest and lowest
      # box a little more than half a loop's difference. a is added on, (subtracted if you want to be technical, since a is
      # negative), to provide some sort of change for each frame. if we don't include '+ a' in the algorithm, the boxes would
      # be still.
    
      @y = (24 * cos(0.55 * distance(x,z,0,0) + a)).round()
    
    
      # These are 2 coordinate variations for each quadrilateral.
      # since they can be found in 4 different quadrants (+ and - for x, and + and - for z),
      # we'll only need 2 coordinates for each quadrilateral (but we'll need to pair them up differently
      # for this to work fully).
      #
      # Multiplying the x and z variables by 17 will space them 17 pixels apart.
      # The 8.5 will determine half the width of the box ()
      # 8.5 is used because it is half of 17. since 8.5 is added one way, and 8.5 is subtracted the other way, the total
      # width of each box is 17. this will eliminate any sort of spacing in between each box.
      #
      # If you enable no_stroke(), then the whole thing will appear as one 3d shape. try it.
    
      xm = x * 17 - 8.5
      xt = x * 17 + 8.5
      zm = z * 17 - 8.5
      zt = z * 17 + 8.5
    
      # We use an integer to define the width and height of the window. this is used to save resources on further calculating
      halfw = width/2
      halfh = height/2
    
    
      # Here is where all the isometric calculating is done.
      # We take our 4 coordinates for each quadrilateral, and find their (x,y) coordinates using an isometric formula.
      # You'll probably find a similar formula used in some of my other isometric animations. however, I normally use
      # these in a function. to avoid using repetitive calculation (for each coordinate of each quadrilateral, which
      # would be 3 quads * 4 coords * 3 dimensions = 36 calculations).
      #
      # Formerly, the isometric formula was ((x - z) * cos(radians(30)) + width/2, (x + z) * sin(radians(30)) - y + height/2).
      # However, the cosine and sine are constant, so they could be precalculated. cosine of 30 degrees returns roughly 0.866,
      # which can round to 1, leaving it out would have little artifacts (unless placed side_by_side to accurate versions, where
      # everything would appear wider in this version) sine of 30 returns 0.5.
      #
      # We left out subtracting the y value, since this changes for each quadrilateral coordinate. (-40 for the base, and our y
      # variable) these are later subtracted in the actual quad().
    
      isox1 = (xm - zm + halfw).round
      isoy1 = ((xm + zm) * 0.5 + halfh).round
      isox2 = (xm - zt + halfw).round
      isoy2 = ((xm + zt) * 0.5 + halfh).round
      isox3 = (xt - zt + halfw).round
      isoy3 = ((xt + zt) * 0.5 + halfh).round
      isox4 = (xt - zm + halfw).round
      isoy4 = ((xt + zm) * 0.5 + halfh).round
    
      #the side quads. 2 and 4 is used for the coloring of each of these quads
      fill(2)
      quad(isox2, isoy2 - y, isox3, isoy3 - y, isox3, isoy3 + 40, isox2, isoy2 + 40)
      fill(4)
      quad(isox3, isoy3 - y, isox4, isoy4 - y, isox4, isoy4 + 40, isox3, isoy3 + 40)
    
    
      # the top quadrilateral.
      # y, which ranges between -24 and 24, multiplied by 0.05 ranges between -1.2 and 1.2
      # we add 4 to get the values up to between 2.8 and 5.2.
      # this is a very fair shade of grays, since it doesn't become one extreme or the other.
    
      fill(4 + y * 0.05)
      quad(isox1, isoy1 - y, isox2, isoy2 - y, isox3, isoy3 - y, isox4, isoy4 - y)
    end
  end
end

# the distance formula
def distance(x, y, cx, cy)
  sqrt(sq(cx - x) + sq(cy - y))
end







One of the problems with my script is that it turns all '-' to '_' also it can't cope with C++ style multi-line comments they should probably be banned anyway!!!

No comments:

Post a Comment

Followers

Blog Archive

About Me

My photo
I have developed JRubyArt and propane new versions of ruby-processing for JRuby-9.1.5.0 and processing-3.2.2