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

Showing posts with label conway game of life. Show all posts
Showing posts with label conway game of life. Show all posts

Tuesday, 6 August 2013

Conways Game of Life in ruby-processing (featuring MDArray)

# 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 'mdarray'

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

# signature-specific aliases for overloaded methods
java_alias :my_color, :color, [Java::float, Java::float, Java::float]
java_alias :my_fill, :fill, [Java::int]
java_alias :my_stroke, :stroke, [Java::float, Java::float]
java_alias :my_background, :background, [Java::int]

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

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

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

    # 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
      my_fill(0) #reflect changed status
    else  # Cell is dead
      cells.set([x_cell_over, y_cell_over], ALIVE) # Make alive
      my_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
          if [(xx>=0), (xx<row), (yy>=0), (yy<column)].all? {|in_bounds| in_bounds == true}
            # Make sure to check against self
            if ![(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 if grid bounds
        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
  data = []
  (0 ... row * column).each do
    data << (rand(1000) < ALIVE_START)
  end
  return data
end

Saturday, 30 March 2013

Conways Game Of Life (ruby-processing)

Somewhat more concise code in ruby-processing cf the vanilla-processing original (replaced 0, 1 DEAD-ALIVE with a boolean for which they were only place-holder and hence much scope to dry code).
#
# 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.
#

CELL_SIZE = 5
ALIVE = true
DEAD = false
ALIVE_START = 150
INTERVAL = 100

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

def setup
  size(960, 640)
  @pause = false
  # Instantiate arrays 
  @row = width / CELL_SIZE
  @column = height / CELL_SIZE
  @cells = Array.new(row) {Array.new(column) {(rand(1000) > ALIVE_START)? DEAD : ALIVE}}
  @last_time = 0
  @alive = color(100, 255, 100)
  # This stroke will draw the background grid (live cells)
  stroke(48, 100)
  noSmooth
end

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

  # Create  new cells manually on pause
  if (pause && mouse_pressed?)
    # # Map and avoid out of bound errors
    xCellOver = (map(mouseX, 0, width, 0, row)).to_i
    xCellOver = constrain(xCellOver, 0, row - 1)
    yCellOver = (map(mouseY, 0, height, 0, column)).to_i
    yCellOver = constrain(yCellOver, 0, column - 1)

    # Check against cells in buffer
    if (cells_buffer[xCellOver][yCellOver])  # Cell is alive
      cells[xCellOver][yCellOver] = DEAD # Kill
      fill(0) #reflect changed status
    else  # Cell is dead
      cells[xCellOver][yCellOver] = 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 = clone2d(cells)
  end
end

def tick!  # When the clock ticks
  # Save cells to buffer (so we operate with one array keeping the other intact)
  @cells_buffer = clone2d(cells)
  # Visit each cell:
  row.times do |x|
    column.times 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
          if [(xx>=0), (xx<row), (yy>=0), (yy<column)].all? {|in_bounds| in_bounds == true}
            # Make sure to check against self
            if ![(xx == x), (yy == y)].all? {|is_self| is_self == true}
              if (cells_buffer[xx][yy]) # true == ALIVE
                neighbours += 1 # Check alive neighbours and count them
              end # alive
            end # End of if self
          end # End of if grid bounds
        end # End of yy loop
      end #End of xx loop
      # We've checked the neighbours: apply rules in one line (only in ruby)!
      cells[x][y] = (cells_buffer[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 = Array.new(row) {Array.new(column) {(rand(1000) > ALIVE_START)? DEAD : ALIVE}}
  when ' ' # On/off of pause
    @pause = !pause
  when 'c', 'C' # Clear all
    @cells = Array.new(row) {Array.new(column) {DEAD}}
  end
end

def clone2d array
  result = []
  array.each do |val|
    result << val.clone
  end
  return result
end




Wednesday, 13 February 2013

Conway game of life using shaders in ruby-processing

Hot off the press this example has only just been posted by Andrés Colubri as a vanilla processing example at github (I'm not sure he really meant to create a P3D sketch initially though, P2D seems to work just as well) see java/examples/Topics/Shaders/Conway/data/conway.glsl for shader.
# GLSL version of Conway's game of life, ported from GLSL sandbox:
# http://glsl.heroku.com/e//207.3
# Exemplifies the use of the buffer uniform in the shader, that gives
# access to the previous frame.
attr_accessor :pg, :conway

def setup
  size(400, 400, P3D)
  @pg = createGraphics(400, 400, P2D)
  pg.no_smooth
  @conway = load_shader("data/conway.glsl")
  conway.set("resolution", width.to_f, height.to_f)
end

def draw
  conway.set("time", millis() / 1000.0)
  xm = map(mouse_x, 0, width, 0, 1)
  ym = map(mouse_y, 0, height, 1, 0)
  conway.set("mouse", xm, ym)
  pg.begin_draw
  pg.background(0)
  pg.shader(conway)
  pg.rect(0, 0, pg.width, pg.height)
  pg.end_draw
  image(pg, 0, 0, width, height)
end

Followers

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