# # 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
Experiments with ruby-processing (processing-2.2.1) and JRubyArt for processing-3.0
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).
Labels:
conway game of life,
graphics,
jruby,
ruby-processing
Wednesday, 20 March 2013
XML example Yahoo Weather
This example is more or less a direct translation of the vanilla processing example to ruby-processing (the main difference is how easy it to create a formatted string in ruby cf java)...
NB: requires current version of ruby-processing-2+
NB: requires current version of ruby-processing-2+
# # Loading XML Data # by Daniel Shiffman. # # This example demonstrates how to use loadXML() # to retrieve data from an XML document via a URI # attr_reader :zip, :weather, :temperature def setup size(600, 360) @zip = 10003 font = create_font("Merriweather-Light.ttf", 28) text_font(font) # The URL for the XML document url = "http://xml.weather.yahoo.com/forecastrss?p=#{zip}" # Load the XML document xml = loadXML(url) # Grab the element we want forecast = xml.get_child("channel").get_child("item").get_child("yweather:forecast") # Get the attributes we want @temperature = forecast.get_int("high") @weather = forecast.get_string("text") end def draw background(255) fill(0) # Display all the stuff we want to display text("Zip code: #{zip}", width*0.15, height*0.33) text("Today's high: #{temperature}", width*0.15, height*0.5) text("Forecast: #{weather}", width*0.15, height*0.66) end
Labels:
ruby processing,
uri,
xml
Demonstrating regex in ruby-processing
There is a example in the vanilla processing distribution, that demonstrates the use of regex (based on java) to extract links from the processing web-site. This more rubified variant extracts only the web addresses using split with a regex. Note this just to demonstrate/explore regex there is the 'uri' module to do this sort of thing if you are serious.
NB: tested with development version of ruby-processing see here.
NB: tested with development version of ruby-processing see here.
# # Regular Expression example # by Martin Prout. # # This uses ruby scan # # Here we'll load the raw HTML from a URI and search for web-links # attr_reader :links, :url def setup size(360, 480) @url = "http://processing.org" # Load the links @links = load_links(url) links.uniq! # get rid of the duplicates text_font(create_font("Georgia", 16)) end def draw background(0) # Display the bare links fill(0, 255, 255) links.each_with_index do |link, i| text(link, 10, 20 + i * 20) end end def load_links(s) result = [] # Load the raw HTML lines = load_strings(s) # Put it in one big string all_txt = lines.join('\n') all_txt.scan(/ https?:\/\/ \w+ (?: [.-]\w+ )* (?: \/ [0-9]{1,5} \? [\w=]* )? /ix) end
Labels:
regex,
ruby-processing
Saturday, 16 March 2013
Another word counting sketch translated to ruby processing
Here is another sketch that was based on a examples by Daniel Schiffman to illustrate the use of a HashMap in vanilla processing.
NB: tested with development version of ruby-processing see here.
Here is the required word.rb:-
Here is the sketch:-
Here is the display:-
NB: tested with development version of ruby-processing see here.
Here is the required word.rb:-
####### # word.rb # the word class stores data about words (text, source, frequency) # thanks to processing mixin words are rendered according to # source and frequency ######## class Word include Processing::Proxy # Store a count for occurences in two different books attr_reader :count_dracula, :count_franken, :total_count, :word, :position, :width, :height, :speed def initialize(s) @width, @height = $app.width, $app.height @count_dracula, @count_franken, @total_count = 0, 0, 0 @position = [rand(width), rand(-height .. height*2)] @word = s end # We will display a word if it appears at least 5 times # and only in one of the books def qualify? return ((count_dracula == total_count || count_franken == total_count) && total_count > 5) end # Increment the count for Dracula def increment_dracula @count_dracula += 1 @total_count += 1 end # Increment the count for Frankenstein def increment_franken @count_franken += 1 @total_count += 1 end # The more often it appears, the faster it falls def move @speed = map(total_count, 5, 25, 0.1, 0.4).to_f @speed = constrain(speed, 0, 10.0) @position[Y] += speed if (position[Y] > height*2) @position[Y] = -height end end # Depending on which book it gets a color def display if (count_dracula > 0) fill(255) elsif (count_franken > 0) fill(0) end # Its size is also tied to number of occurences fs = map(total_count,5,25,2,24.0).to_f fs = constrain(fs, 2, 48) text_size(fs) text_align(CENTER) text(word, position[X], position[Y]) end end
Here is the sketch:-
# # After a HashMap example # by Daniel Shiffman. # # This example demonstrates how to use a Hash to store # a collection of objects referenced by a key. This is much like an array, # only instead of accessing elements with a numeric index, we use a String. # If you are familiar with associative arrays from other languages, # this is the same idea. # # The Processing classes IntHash, FloatHash, and StringHash offer a simple # way of pairing Strings with numbers or other Strings. But are probably of # less interest to rubyists. # # In this example, words that appear in one book (Dracula) are colored white # whilst words in the other book (Frankenstein) are colored black. # load './word.rb' DRACULA = "dracula.txt" FRANKENSTEIN = "frankenstein.txt" attr_accessor :words def setup size(640, 360) # Create the HashMap @words = {} # Load two files load_file(DRACULA) load_file(FRANKENSTEIN) # Create the font text_font(create_font("Georgia", 24)) end def draw background(126) # Show words words.values.each do |w| if w.qualify? w.display w.move end end end # Load a file def load_file(filename) tokens = File.open(data_path(filename), "r"){|file| file.read.scan(/[\w'-]+/)} tokens.each do |s| s = s.downcase # Is the word in the HashMap if (words.has_key?(s)) # Get the word object and increase the count # We access objects from a Hash via its key, the String w = words[s] # Which book am I loading? if (filename == DRACULA) w.increment_dracula elsif (filename == FRANKENSTEIN) w.increment_franken end else # Otherwise make a new word w = Word.new(s) # And add entry to the Hash # The key for us is the String and the value is the Word object words[s] = w if (filename == DRACULA) w.increment_dracula elsif (filename == FRANKENSTEIN) w.increment_franken end end end end
Here is the display:-
Labels:
concordance,
file read,
frequency,
ruby processing
Thursday, 14 March 2013
Translating a Word counting sketch to ruby-processing
Here is a sketch that was based on a prototype by Daniel Schiffman to illustrate the use of the processing HashInt class, I can't see the HashInt class catching on really, particularly not for rubyists where alternative options abound. Anyway I liked the sketch and I think sometimes less is more, in later versions Schiffman sorts the words according to their frequency (to show off IntClass functionality), however to my mind it spoils the sketch!
class Word # A helper to keep track of word frequency. attr_accessor :word attr_reader :count def initialize word @word = word @count = 1 end def increment @count += 1 end end ################################ # This sketch is translated from a vanilla processing sketch by Daniel Schiffman # that was designed to demonstrate the use IntHash class in vanilla processing. # Similar results can easily be obtained using more idiomatic ruby. Here IntHash # has been replaced by a String => Word hash (as used in a Schiffman prototype). # Read about concordance here:- # http://en.wikipedia.org/wiki/Concordance_(publishing) ################################ attr_reader :concordance, :lines, :tokens, :counter def setup size 640, 360 @counter = 0 @concordance = {} # Open a file, read its contents, and 'scan' for words using a regex. # Include words with apostrophe eg Harker's (alt. source 'hamlet.txt') @tokens = File.read(data_path("dracula.txt")).scan(/[\w'-]+/) text_font(create_font("Georgia", 24)) end def draw background 51 fill 255 s = (tokens[counter] == "I")? tokens[counter] : tokens[counter].downcase @counter = (counter + 1) % tokens.length if (concordance.has_key?(s)) # Get the word object and increase the count # We access objects from a Hash via its key, the String w = concordance[s] w.increment # increment word count else # Otherwise make a new Word instance and add it to # the Hash using the word String as the key concordance[s] = Word.new(s) end # x and y will be used to locate each word x = 0 y = height - 10 # Look at each word concordance.values.each do |w| # Only display words that appear 3 times if (w.count > 3) # access word count # The size is the count fsize = constrain(w.count, 0, 100) text_size(fsize) text(w.word, x, y) # Move along the x-axis x += text_width(w.word) + 1 end # If x gets to the end, move y # If y == 0 we are done if (y == 0) no_loop else if (x > width) x = 0 y = (y < 0)? 0 : y - 100 end end end end
Labels:
display,
hash,
processing-2.0,
ruby-processing,
word frequency,
words
Wednesday, 13 March 2013
PeasyCam for processing-2.0 under the Hood
Now more interestingly lets take a look at PeasyCam (an unofficial update for processing-2.0 that uses reflection to registerMethod("mouseEvent", this) here we can see lots of "access" methods, this must be when java reflection is used:-
puts cam.class.methods
access$2600 access$2800 access$2000 access$100 access$1402 java_send access$1000 access$2400 access$600 access$1800 access$500 access$900 access$2500 [] apply access$600? access$2200 access$700 access$800 access$1500 access$2300 access$000 access$1302 access$1400 access$1500? access$300 access$1700 access$2700 access$1200 java_method access$1600 access$2302 access$400? access$200 access$1900 access$1300 access$2102 access$1100 access$1002 access$400 access$000? inherited new singleton_class java_class field_writer new_array __persistent__= __persistent__ field_accessor field_reader java_class= yaml_tag allocate superclass const_get private_constant public_instance_methods autoload? freeze class_variable_get const_missing included_modules == class_exec psych_yaml_as public_class_method ancestors instance_method < yaml_as protected_method_defined? > === private_instance_methods hash class_variables public_constant <= method_defined? instance_methods class_variable_defined? name private_method_defined? const_set autoload include? protected_instance_methods module_exec module_eval <=> constants private_class_method class_variable_set to_s public_method_defined? class_eval >= remove_class_variable const_defined? handle_different_imports psych_to_yaml include_class to_yaml java_kind_of? to_yaml_properties java_signature methods define_singleton_method initialize_clone extend nil? tainted? method is_a? instance_variable_defined? instance_variable_get instance_variable_set public_method display send private_methods enum_for com to_java public_send instance_of? taint class java_annotation instance_variables !~ org untrust =~ protected_methods trust inspect java_implements tap frozen? initialize_dup java respond_to? java_package untaint respond_to_missing? clone java_name to_enum singleton_methods untrusted? eql? kind_of? dup java_require javax public_methods instance_exec __send__ instance_eval equal? object_id __id__ ! !=
Labels:
jruby,
methods,
mouseEvent,
peasycam,
processing-2.0,
reflection
ArcBall library example under the Hood
Here is my simple ruby-processing example under the hood
puts self.inspect
#<Processing::App::Sketch>
puts self.inspect
#<Processing::App::Sketch>
puts self.class.ancestors
Sketch Processing::App Processing::HelperMethods Math Java::ProcessingCore::PApplet Java::ProcessingCore::PConstants Java::JavaLang::Runnable Java::JavaAwtEvent::MouseListener Java::JavaAwtEvent::MouseWheelListener Java::JavaAwtEvent::MouseMotionListener Java::JavaAwtEvent::KeyListener Java::JavaAwtEvent::FocusListener Java::JavaUtil::EventListener Java::JavaApplet::Applet Java::JavaAwt::Panel Java::JavaxAccessibility::Accessible Java::JavaAwt::Container Java::JavaAwt::Component Java::JavaAwtImage::ImageObserver Java::JavaAwt::MenuContainer Java::JavaIo::Serializable Java::JavaLang::Object ConcreteJavaProxy JavaProxy JavaProxyMethods Object Kernel BasicObject
puts self.class.methods
java_interfaces java_proxy_class= const_missing java_proxy_class library_loaded? has_slider method_added sketch_class load_java_library inherited load_library load_ruby_library load_libraries full_screen url_encode show_depth_warning_xyz show_method_warning java_send dist exec splice main print blendColor createInput load_strings split parse_int nf lerp run_sketch show_missing_warning reverse createReader lerp_color lerpColor acos sort floor sqrt parseInt nfs hour atan get_extension unhex selectOutput min nfp str match_pattern trim create_path unbinary nfc url_decode parseFloat urlDecode expand debug match urlEncode round minute arraycopy cos tan radians ceil atan2 parseChar save_bytes matchAll loadStrings parse_char match_all create_writer array_copy append create_reader parse_byte month map parse_float degrees saveStream println asin show_variation_warning save_stream select_impl showDepthWarningXYZ shorten exp select_input join saveBytes createOutput max second createPath getExtension save_strings parseByte sq select_folder showVariationWarning binary loadBytes create_input blend_color save_stream? hex subset norm log parseBoolean open parse_boolean? year mag show_depth_warning showMissingWarning selectFolder day selectImpl matchPattern split_tokens access$000 showMethodWarning sin arrayCopy splitTokens select_output java_method saveStrings parse_boolean constrain runSketch pow selectInput create_output abs concat createWriter showDepthWarning load_bytes newAudioClip new_audio_clip access$100 access$500 access$002 instance_of access$500? is_instance_of request_focus_controller= set_request_focus_controller is_instance_of? instanceOf access$400 setRequestFocusController isInstanceOf requestFocusController= new singleton_class java_class field_writer new_array __persistent__= __persistent__ [] field_accessor field_reader java_class= yaml_tag allocate superclass const_get private_constant public_instance_methods autoload? freeze class_variable_get included_modules == class_exec psych_yaml_as public_class_method ancestors instance_method < yaml_as protected_method_defined? > === private_instance_methods hash class_variables public_constant <= method_defined? instance_methods class_variable_defined? name private_method_defined? const_set autoload include? protected_instance_methods module_exec module_eval <=> constants private_class_method class_variable_set to_s public_method_defined? class_eval >= remove_class_variable const_defined? handle_different_imports psych_to_yaml include_class to_yaml java_kind_of? to_yaml_properties java_signature methods define_singleton_method initialize_clone extend nil? tainted? method is_a? instance_variable_defined? instance_variable_get instance_variable_set public_method display send private_methods enum_for com to_java public_send instance_of? taint class java_annotation instance_variables !~ org untrust =~ protected_methods trust inspect java_implements tap frozen? initialize_dup java respond_to? java_package untaint respond_to_missing? clone java_name to_enum singleton_methods untrusted? eql? kind_of? dup java_require javax public_methods instance_exec __send__ instance_eval equal? object_id __id__ ! !=
Tuesday, 12 March 2013
Ruby Processing under the Hood
Here is some under the hood analysis of the "array.rb" sample.
puts self.inspect
#<Processing::App::Sketch>
puts self.class.ancestors
Sketch Processing::App Processing::HelperMethods Math Java::ProcessingCore::PApplet Java::ProcessingCore::PConstants Java::JavaLang::Runnable Java::JavaAwtEvent::MouseListener Java::JavaAwtEvent::MouseWheelListener Java::JavaAwtEvent::MouseMotionListener Java::JavaAwtEvent::KeyListener Java::JavaAwtEvent::FocusListener Java::JavaUtil::EventListener Java::JavaApplet::Applet Java::JavaAwt::Panel Java::JavaxAccessibility::Accessible Java::JavaAwt::Container Java::JavaAwt::Component Java::JavaAwtImage::ImageObserver Java::JavaAwt::MenuContainer Java::JavaIo::Serializable Java::JavaLang::Object ConcreteJavaProxy JavaProxy JavaProxyMethods Object Kernel BasicObject
puts self.class.methods
java_proxy_class= java_proxy_class java_interfaces library_loaded? has_slider method_added sketch_class load_java_library inherited load_library load_ruby_library load_libraries full_screen url_encode show_depth_warning_xyz show_method_warning java_send dist exec splice main print blendColor createInput load_strings split parse_int nf lerp run_sketch show_missing_warning reverse createReader lerp_color lerpColor acos sort floor sqrt parseInt nfs hour atan get_extension unhex selectOutput min nfp str match_pattern trim create_path unbinary nfc url_decode parseFloat urlDecode expand debug match urlEncode round minute arraycopy cos tan radians ceil atan2 parseChar save_bytes matchAll loadStrings parse_char match_all create_writer array_copy append create_reader parse_byte month map parse_float degrees saveStream println asin show_variation_warning save_stream select_impl showDepthWarningXYZ shorten exp select_input join saveBytes createOutput max second createPath getExtension save_strings parseByte sq select_folder showVariationWarning binary loadBytes create_input blend_color save_stream? hex subset norm log parseBoolean open parse_boolean? year mag show_depth_warning showMissingWarning selectFolder day selectImpl matchPattern split_tokens access$000 showMethodWarning sin arrayCopy splitTokens select_output java_method saveStrings parse_boolean constrain runSketch pow selectInput create_output abs concat createWriter showDepthWarning load_bytes newAudioClip new_audio_clip access$100 access$500 access$002 instance_of access$500? is_instance_of request_focus_controller= set_request_focus_controller is_instance_of? instanceOf access$400 setRequestFocusController isInstanceOf requestFocusController= new singleton_class java_class field_writer new_array __persistent__= __persistent__ [] field_accessor field_reader java_class= yaml_tag allocate superclass const_get private_constant public_instance_methods autoload? freeze class_variable_get const_missing included_modules == class_exec psych_yaml_as public_class_method ancestors instance_method < yaml_as protected_method_defined? > === private_instance_methods hash class_variables public_constant <= method_defined? instance_methods class_variable_defined? name private_method_defined? const_set autoload include? protected_instance_methods module_exec module_eval <=> constants private_class_method class_variable_set to_s public_method_defined? class_eval >= remove_class_variable const_defined? handle_different_imports psych_to_yaml include_class to_yaml java_kind_of? to_yaml_properties java_signature methods define_singleton_method initialize_clone extend nil? tainted? method is_a? instance_variable_defined? instance_variable_get instance_variable_set public_method display send private_methods enum_for com to_java public_send instance_of? taint class java_annotation instance_variables !~ org untrust =~ protected_methods trust inspect java_implements tap frozen? initialize_dup java respond_to? java_package untaint respond_to_missing? clone java_name to_enum singleton_methods untrusted? eql? kind_of? dup java_require javax public_methods instance_exec __send__ instance_eval equal? object_id __id__ ! !=
Labels:
ancestors,
ruby processing
Thursday, 7 March 2013
Stochastic Menger using PShape api
NB: This sketch requires the development version of ruby-processing see here.
########################## # StochasticMenger.rb # (processing-2.0) # author Martin Prout ########################## load_library 'arcball' import "arcball" PTS = [-1, 0, 1] MIN_SIZE = 50 X = 0 Y = 1 Z = 2 attr_reader :arcball, :menger def setup size(640, 480, P3D) smooth(8) camera camera(width/2.0, height/2.0, (height/2.0) / tan(PI*30.0 / 180.0), 0, 0, 0, 0, 1, 0) @arcball = ArcBall.new(0, 0, min(width - 20, height - 20) * 0.8) @menger = create_shape(GROUP) create_menger(0, 0, 0, height * 0.8) end def draw background(40, 40, 180) no_stroke lights update define_lights render end def render menger.set_ambient(50) menger.set_specular(150) shape(menger) end def create_menger(xx, yy, zz, sz) u = sz / 3.0 if (sz < MIN_SIZE) # recursion limited by minimum cube size no_stroke menger.add_child(create_cube(xx, yy, zz, sz)) # create and add a cube else PTS.each do |i| PTS.each do |j| PTS.each do |k| if ((i.abs + j.abs + k.abs) > 1) create_menger(xx + (i * u), yy + (j * u), zz + (k * u), u) end end end end end end def create_cube(xx, yy, zz, sz) dim = sz / 2.0 chance = rand if chance < 0.8 cube = create_shape(BOX, sz, sz, sz) cube.set_fill(color(0, 0, 219)) else cube = create_shape(SPHERE, dim) cube.set_fill(color(224, 223, 219)) end cube.translate(xx, yy, zz) return cube end def update theta, x, y, z = arcball.update rotate(theta, x, y, z) end def mouse_pressed arcball.mouse_pressed(mouse_x, mouse_y) end def mouse_dragged arcball.mouse_dragged(mouse_x, mouse_y) end def define_lights ambient_light(50, 50, 50) point_light(30, 30, 30, 200, 240, 0) directional_light(50, 50, 50, 1, 0, 0) spot_light(30, 30, 30, 0, 40, 200, 0, -0.5, -0.5, PI / 2, 2) end def key_pressed case(key) when 'x' arcball.select_axis(X) when 'y' arcball.select_axis(Y) when 'z' arcball.select_axis(Z) end end def key_released arcball.select_axis(-1) end
Labels:
processing-2.0,
pshape,
ruby-processing
Subscribe to:
Posts (Atom)
Followers
Blog Archive
-
▼
2013
(94)
-
▼
March
(9)
- Conways Game Of Life (ruby-processing)
- XML example Yahoo Weather
- Demonstrating regex in ruby-processing
- Another word counting sketch translated to ruby pr...
- Translating a Word counting sketch to ruby-processing
- PeasyCam for processing-2.0 under the Hood
- ArcBall library example under the Hood
- Ruby Processing under the Hood
- Stochastic Menger using PShape api
-
▼
March
(9)
About Me
- monkstone
- I have developed JRubyArt and propane new versions of ruby-processing for JRuby-9.1.5.0 and processing-3.2.2