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

Saturday 4 October 2014

Rubygems with latest JRubyArt

With regular ruby-processing, the only way to use gems was to use an installed version of jruby (well apart from using some complicated bundler tool). Interestingly currently you seem to be able to use jruby-complete to launch a sketch with JRubyArt (providing youve've installed the gem with your installed jruby). Now the interest in using jruby-complete is all about being able to run sketches that load_image, shaders etc. Many sketches run just fine with an installed jruby.
                                                   
java -jar jruby-complete game_of_life.rb                                    

Here is the sketch
# game_of_life.rb featuring MDArray in ruby-processing
# A Processing implementation of Game of Life
# By Joan Soler-Adillon
#
# Press SPACE BAR to pause and change the cell's values with the mouse
# On pause, click to activate/deactivate cells
# Press R to randomly reset the cells' grid
# Press C to clear the cells' grid
#
# The original Game of Life was created by John Conway in 1970.
#
require 'jruby_art'
require 'mdarray'

class GameOfLife < Processing::App
  CELL_SIZE = 5
  ALIVE = true
  DEAD = false
  ALIVE_START = 150
  WIDTH = 960
  HEIGHT = 640
  SKIP = 10
  INTERVAL = 100

  attr_reader :pause, :cells, :row, :column, :last_time, :alive, :cells_buffer

  def setup
    size WIDTH, HEIGHT
    @row = WIDTH / CELL_SIZE
    @column = HEIGHT / CELL_SIZE
    background 0
    stroke_weight 2
    @last_time = 0
    @pause = false
    @cells = MDArray.boolean([row, column], random_data)
    @alive = color(100, 255, 100)
    stroke(48, 100)
    no_smooth
  end

  def draw
    background(0)
    # Draw live cells
    (0...row).each do |x|
      (0...column).each do |y|
        if cells.get([x, y])
          fill(alive)
          rect(x * CELL_SIZE, y * CELL_SIZE, CELL_SIZE, CELL_SIZE)
        end
      end
    end
    # Iterate if timer ticks
    unless pause
      tick!
      @last_time = millis
    end if millis - last_time > INTERVAL

    # Create  new cells manually on pause
    if pause && mouse_pressed?
      # Map and avoid out of bound errors (use map1d range and range.clip)
      x_cell_over = (map1d(mouse_x, (0..width), (0..row))).to_i
      x_cell_over = (0..row - 1).clip(x_cell_over)
      y_cell_over = (map1d(mouse_y, (0..height), (0..column))).to_i
      y_cell_over = (0..column - 1).clip(y_cell_over)

      # Check against cells in buffer
      if cells_buffer.get([x_cell_over, y_cell_over])  # Cell is alive
        cells.set([x_cell_over, y_cell_over], DEAD) # Kill
        fill(0) # reflect changed status
      else  # Cell is dead
        cells.set([x_cell_over, y_cell_over], ALIVE) # Make alive
        fill(alive) # Fill alive color
      end

    elsif pause && !mouse_pressed?  # And then save to buffer once mouse goes up
      # Save cells to buffer (so we operate with one array keeping the other intact)
      @cells_buffer = cells.copy
    end
  end

  def tick!  # When the clock ticks
    # Save cells to buffer (so we operate with one array keeping the other intact)
    @cells_buffer = cells.copy
    # Visit each cell:
    (0...row).each do |x|
      (0...column).each do |y|
        # And visit all the neighbours of each cell
        neighbours = 0 # We'll count the neighbours
        (x - 1..x + 1).each do |xx|
          (y - 1..y + 1).each do |yy|
            # Make sure you are not out of bounds
            next unless [(xx >= 0), (xx < row), (yy >= 0), (yy < column)].all? { |in_bounds| in_bounds == true }
            # Make sure to check against self
            unless [(xx == x), (yy == y)].all? { |is_self| is_self == true }
              if cells_buffer.get([xx, yy]) # true == ALIVE
                neighbours += 1 # Check alive neighbours and count them
              end # alive
            end # End of if self
          end # End of yy loop
        end # End of xx loop
        # We've checked the neighbours: apply rules in one line (only in ruby)!
        cells.set([x, y], (cells_buffer.get([x, y])) ? ((2..3) === neighbours) : (neighbours == 3))
      end # End of y loop
    end # End of x loop
  end # End of function

  def key_pressed
    case key
    when 'r', 'R'
      # Restart: reinitialization of cells
      @cells = MDArray.boolean([row, column], random_data)
    when ' ' # On/off of pause
      @pause = !pause
    when 'c', 'C' # Clear all
      @cells = MDArray.boolean([row, column], DEAD)
    end
  end

  def random_data
    (0...row * column).map { rand(1000) < ALIVE_START }
  end
end

GameOfLife.new(title: 'Game of Life mdarray version')

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