attr_reader :pg def setup size(200, 200, P2D) @pg = create_graphics(100, 100, P3D) smooth(8) end def draw background 50 pg.begin_draw pg.background 150 pg.stroke 255 pg.stroke_weight 3 pg.translate(50, 50, 0) pg.rotate_y 0.45 pg.no_fill pg.box(40) pg.end_draw image(pg, width / 2 - 50, height / 2 - 50) end
Experiments with ruby-processing (processing-2.2.1) and JRubyArt for processing-3.0
Friday, 31 May 2013
A little offscreen buffer test with ruby-processing-2.0
A little sketch from the processing discussion board, makes me think that I should revive lazydogs mirror sketch for ruby-processing-2.0, now that would be cool.
Wednesday, 22 May 2013
Precast to a java object or use an alias method in ruby-processing (for overloaded java methods)
# alias_background.rb # class Java::ProcessingCore::PApplet java_alias :int_background, :background, [Java::int] java_alias :image_background, :background, [Java::ProcessingCore::PImage] end attr_reader :img, :show, :col_int, :back_image def setup size(640, 360) @show = false @img = loadImage("test.png") # NB: test.png size should equal frame size #@back_image = img.to_java(Java::ProcessingCore::PImage) end def draw int_background(0) # background(0) # warns about ambigious method # background(img) if show image_background(img) if show # does not warn about ambiguous method # int_background(0) if show # uses a precast java object end def mouse_pressed @show = !show end
Labels:
alias_java,
to_java
Monday, 20 May 2013
Updating to Use JRuby-1.7.4
I've recently updated ruby-processing to use jruby-1.7.4, and for Mac and Windows users, it has been updated to use processing-2.0 (untested, you might be the guinea-pig). Seems to work OK linux. I am not all interested in updating ruby-processing processing-1.5.1 to use jruby-1.7.4 so unless someone volunteers the next release of ruby-processing will be a huge leap (if you've got a crappy graphics card the experience may not be so wonderful!!!!). Processing 2.0 uses opengl2 for P2D and P3D rendering so if you've got a reasonable graphics card there are decent improvements to be had including easy access to glsl shaders and FBO (buffered on graphics card). Read this and get inspired http://codeanticode.wordpress.com/2013/06/04/processing-2-0-is-out-processing-2-0-is-in/
Labels:
jruby-1.7.4,
minitest,
processing-2.0,
ruby-processing
Tuesday, 7 May 2013
Another PBox2D sketch, features a chain, and usual physics
# The Nature of Code # <http://www.shiffman.net/teaching/nature> # Spring 2010 # PBox2D example # An uneven surface load_library :pbox2d load_library :surface include SB attr_reader :surface, :box2d, :particles def setup size(500,300) smooth # Initialize box2d physics and create the world @box2d = PBox2D.new(self) box2d.create_world # We are setting a custom gravity box2d.set_gravity(0, -20) # Create the empty list @particles = [] # Create the surface @surface = Surface.new(box2d) end def draw # If the mouse is pressed, we make new particles # We must always step through time! box2d.step background(138, 66, 54) # Draw the surface surface.display # NB question mark is reqd to call mouse_pressed value, else method gets called. particles << Particle.new(box2d, mouse_x, mouse_y, rand(2.0 .. 6)) if mouse_pressed? # Draw all particles particles.each do |p| p.display end # Particles that leave the screen, we delete them # (note they have to be deleted from both the box2d world and our list particles.each_with_index do |p, i| if (p.done) particles.delete_at(i) end end # Just drawing the framerate to see how many particles it can handle fill(0) text("framerate: #{frame_rate.to_i}", 12, 16) end
The library module, which encapsulates the import of classes, and additional classes for surface and particles.
# The Nature of Code # <http://www.shiffman.net/teaching/nature> # Spring 2010 # PBox2D example # An uneven surface boundary module SB include_package 'org.jbox2d.collision.shapes' include_package 'org.jbox2d.common' include_package 'org.jbox2d.dynamics' java_import 'pbox2d.PBox2D' class Surface # We'll keep track of all of the surface points attr_reader :surface, :body, :box2d, :y, :width, :height def initialize b2d @box2d = b2d @surface = [] @width, @height = $app.width, $app.height # This is what box2d uses to put the surface in its world chain = SB::ChainShape.new # Perlin noise argument xoff = 0.0 # This has to go backwards so that the objects bounce off the top of the surface # This "edgechain" will only work in one direction! (width + 10).step(-10, -5) do |x| # Doing some stuff with perlin noise to calculate a surface that points down on one side # and up on the other if (x > width/2) @y = 100 + (width - x)*1.1 + map(noise(xoff),0,1,-80,80) else @y = 100 + x*1.1 + map(noise(xoff),0,1,-80,80) end # Store the vertex in screen coordinates surface << SB::Vec2.new(x, y) # Move through perlin noise xoff += 0.1 end # Build an array of vertices in Box2D coordinates # from the ArrayList we made vertices = [] surface.each do |surf| vertices << box2d.coord_pixels_to_world(surf) end # Create the chain! chain.createChain(vertices, vertices.length) # The edge chain is now attached to a body via a fixture bd = SB::BodyDef.new bd.position.set(0.0, 0.0) @body = box2d.createBody(bd) # Shortcut, we could define a fixture if we # want to specify frictions, restitution, etc. body.createFixture(chain, 1) end # A simple function to just draw the edge chain as a series of vertex points def display stroke_weight(2) stroke(0) fill(135, 206, 250) beginShape vertex(width, 0) # extra vertices so we can fill sky surface.each do |v| vertex(v.x, v.y) # the mountain range end vertex(0, 0) # extra vertices so we can fill sky endShape end end class Particle # We need to keep track of a Body attr_reader :body, :box2d, :x, :y, :r # Constructor def initialize(b2d, x, y, r) @box2d, @x, @y, @r = b2d, x, y, r # This function puts the particle in the Box2d world make_body(x, y, r) end # This function removes the particle from the box2d world def kill_body box2d.destroy_body(body) end # Is the particle ready for deletion? def done pos = box2d.get_body_pixel_coord(body) # Is it off the bottom of the screen? if (pos.y > $app.height + r * 2) kill_body return true end return false end def display # We look at each body and get its screen position pos = box2d.get_body_pixel_coord(body) # Get its angle of rotation a = body.get_angle push_matrix translate(pos.x, pos.y) rotate(-a) fill(175) stroke(0) stroke_weight(1) ellipse(0,0,r*2,r*2) # Let's add a line so we can see the rotation line(0,0,r,0) pop_matrix end # This function adds the rectangle to the box2d world def make_body(x, y, r) # Define and create the body bd = SB::BodyDef.new bd.position = box2d.coord_pixels_to_world(x,y) bd.type = SB::BodyType::DYNAMIC @body = box2d.world.create_body(bd) # Make the body's shape a circle cs = SB::CircleShape.new cs.m_radius = box2d.scalar_pixels_to_world(r) fd = SB::FixtureDef.new fd.shape = cs # Parameters that affect physics fd.density = 1 fd.friction = 0.01 fd.restitution = 0.3 # Attach fixture to body body.create_fixture(fd) # Give it a random initial velocity (and angular velocity) body.set_linear_velocity(SB::Vec2.new(rand(-10 .. 10), rand(5 .. 10))) body.set_angular_velocity(rand(-10 .. 10)) end end end
Labels:
chain,
jruby,
pbox2d,
physics,
ruby-processing
Liquid like particles in ruby-processing (Shiffmans liquidy example)
Here is another pbox2d sketch in ruby-processing, where I've used a module to wrap java imports and extra classes:-
Here is the module/library
# The Nature of Code # <http://www.shiffman.net/teaching/nature> # Spring 2011 # PBox2D example # Box2D particle system example load_library :pbox2d load_library :particle_system # module PS is a wrapper for java imports, and Boundary and Particle classes include PS attr_reader :box2d, :boundaries, :systems def setup size(400,300) smooth # Initialize box2d physics and create the world @box2d = PBox2D.new(self) box2d.create_world # We are setting a custom gravity box2d.set_gravity(0, -20) # Create ArrayLists @systems = [] @boundaries = [] # Add a bunch of fixed boundaries boundaries << Boundary.new(box2d, 50,100,300,5,-0.3) boundaries << Boundary.new(box2d, 250,175,300,5,0.5) end def draw background(255) # We must always step through time! box2d.step # Run all the particle systems if systems.size > 0 systems.each do |system| system.run system.add_particles(box2d, rand(0 .. 2)) end end # Display all the boundaries boundaries.each do |wall| wall.display end end def mouse_pressed # Add a new Particle System whenever the mouse is clicked systems << ParticleSystem.new(box2d, 0, mouse_x, mouse_y) end
Here is the module/library
module PS include_package 'org.jbox2d.collision.shapes' include_package 'org.jbox2d.common' include_package 'org.jbox2d.dynamics' java_import 'pbox2d.PBox2D' # Box2D Particle System # <http://www.shiffman.net/teaching/nature> # Spring 2010 # A class to describe a group of Particles # An ArrayList is used to manage the list of Particles class ParticleSystem attr_reader :particles, :x, :y def initialize(bd, num, x, y) @particles = [] # Initialize the ArrayList @x, @y = x, y # Store the origin point num.times do particles << PS::Particle.new(bd, x, y) end end def run # Display all the particles particles.each do |p| p.display end # Particles that leave the screen, we delete them # (note they have to be deleted from both the box2d world and our list particles.each_with_index do |p, i| if (p.done) particles.delete_at(i) end end end def add_particles(bd, n) n.times do particles << PS::Particle.new(bd, x, y) end end # A method to test if the particle system still has particles def dead particles.empty? end end # The Nature of Code # <http://www.shiffman.net/teaching/nature> # Spring 2012 # PBox2D example # A Particle class Particle TRAIL_SIZE = 6 # We need to keep track of a Body attr_reader :trail, :body, :box2d # Constructor def initialize(b2d, x, y) @box2d = b2d @trail = Array.new(TRAIL_SIZE, [x, y]) # Add the box to the box2d world # Here's a little trick, let's make a tiny tiny radius # This way we have collisions, but they don't overwhelm the system make_body(PS::Vec2.new(x,y), 0.2) end # This function removes the particle from the box2d world def kill_body box2d.destroy_body(body) end # Is the particle ready for deletion? def done # Let's find the screen position of the particle pos = box2d.get_body_pixel_coord(body) # Is it off the bottom of the screen? if (pos.y > $app.height + 20) kill_body return true end return false end # Drawing the box def display # We look at each body and get its screen position pos = box2d.get_body_pixel_coord(body) # Keep track of a history of screen positions in an array (TRAIL_SIZE - 1).times do |i| trail[i] = trail[i + 1] end trail[TRAIL_SIZE - 1] = [pos.x, pos.y] # Draw particle as a trail begin_shape noFill stroke_weight(2) stroke(0,150) trail.each do |v| vertex(v[0], v[1]) end end_shape end # This function adds the rectangle to the box2d world def make_body(center, r) # Define and create the body bd = PS::BodyDef.new bd.type = PS::BodyType::DYNAMIC bd.position.set(box2d.coord_pixels_to_world(center)) @body = box2d.create_body(bd) # Give it some initial random velocity body.set_linear_velocity(PS::Vec2.new(rand(-1 .. 1), rand(-1 .. 1))) # Make the body's shape a circle cs = PS::CircleShape.new cs.m_radius = box2d.scalar_pixels_to_world(r) fd = PS::FixtureDef.new fd.shape = cs fd.density = 1 fd.friction = 0 # Slippery when wet! fd.restitution = 0.5 # We could use this if we want to turn collisions off #cd.filter.groupIndex = -10 # Attach fixture to body body.create_fixture(fd) end end # The Nature of Code # <http://www.shiffman.net/teaching/nature> # Spring 2012 # PBox2D example # A fixed boundary class (now incorporates angle) class Boundary attr_reader :box2d, :b, :x, :y, :w, :h #, :a def initialize(b2d, x, y, w, h, a) @box2d = b2d @x = x @y = y @w = w @h = h # Define the polygon sd = PS::PolygonShape.new # Figure out the box2d coordinates box2dW = box2d.scalar_pixels_to_world(w/2) box2dH = box2d.scalar_pixels_to_world(h/2) # We're just a box sd.set_as_box(box2dW, box2dH) # Create the body bd = PS::BodyDef.new bd.type = PS::BodyType::STATIC bd.angle = a bd.position.set(box2d.coord_pixels_to_world(x,y)) @b = box2d.create_body(bd) # Attached the shape to the body using a Fixture b.create_fixture(sd,1) end # Draw the boundary, it doesn't move so we don't have to ask the Body for location def display fill(0) stroke(0) stroke_weight(1) rect_mode(CENTER) a = b.get_angle push_matrix translate(x,y) rotate(-a) rect(0,0,w,h) pop_matrix end end end
Labels:
jbox2d,
jruby,
pbox2d,
physics,
ruby-processing
Sunday, 5 May 2013
Using Shiffmans PBox2D library in ruby processing
Recently I've published some sketches using the fisica library (using this library in ruby-processing is slightly problematic owing to a somewhat overly complicated polymorphic structure, and a protected abstract class that is supposed to provide "public" methods), here is a look at the Shiffman library that does essentially the same thing (as fisica) by providing a wrapper for the JBox2D java physics library. However it might be just as easy for rubyists to work directly with JBox2D, a note of caution you can't have both the fisica and the pbox2d libraries installed at he same time. Anyway it did at least provide an interesting exercise converting the following example to ruby-processing. Features to note are the required syntax to call the java constants STATIC and DYNAMIC, ie precede constant with '::' and not a '.', and the need to explicitly "to_java" required in the set "Array of Vec2" argument CustomShape class. Also it appears since we are including the library inside the Processing sketch/module we do no seem to require to include Processing::Proxy in the classes.
Here are the supporting classes, wrapped as a ruby module in a "library" custom_shape.rb, note the B2D prefix is needed in the module wrapped classes to access the "include_package" java packages, this is a jruby 'feature' they have not been able to get round as yet.
# The Nature of Code # <http://www.shiffman.net/teaching/nature> # Spring 2011 # PBox2D example # Basic example of falling rectangles load_library :pbox2d load_library :custom_shape # module B2D is a wrapper for java imports, and Boundary and CustomShape classes include B2D attr_reader :box2d, :boundaries, :polygons def setup size(640,360) smooth # Initialize box2d physics and create the world @box2d = PBox2D.new(self) box2d.create_world # We are setting a custom gravity box2d.set_gravity(0, -20) # Create Arrays @polygons = [] @boundaries = [] # Add a bunch of fixed boundaries boundaries << Boundary.new(box2d, width / 4, height - 5, width/2 - 50, 10, 0) boundaries << Boundary.new(box2d, 3*width / 4, height - 50, width/2 - 50, 10, 0) boundaries << Boundary.new(box2d, width - 5,height / 2, 10, height, 0) boundaries << Boundary.new(box2d, 5, height / 2, 10, height, 0) end def draw background(255) # We must always step through time! box2d.step # Display all the boundaries boundaries.each do |wall| wall.display end # Display all the polygons polygons.each do |cs| cs.display end # polygons that leave the screen, we delete them # (note they have to be deleted from both the box2d world and our list polygons.each_with_index do |polygon, i| if polygon.done polygons.delete_at(i) end end end def mouse_pressed polygons << CustomShape.new(box2d, mouse_x, mouse_y) end
Here are the supporting classes, wrapped as a ruby module in a "library" custom_shape.rb, note the B2D prefix is needed in the module wrapped classes to access the "include_package" java packages, this is a jruby 'feature' they have not been able to get round as yet.
module B2D include_package 'pbox2d' include_package 'org.jbox2d.collision.shapes' include_package 'org.jbox2d.common' include_package 'org.jbox2d.dynamics' java_import 'pbox2d.PBox2D' # The Nature of Code # <http://www.shiffman.net/teaching/nature> # Spring 2011 # PBox2D example # A rectangular box class CustomShape # We need to keep track of a Body and a width and height attr_reader :body, :box2d # Constructor def initialize(b2d, x, y) # Add the box to the box2d world @box2d = b2d make_body(B2D::Vec2.new(x, y)) end # This function removes the particle from the box2d world def kill_body! box2d.destroy_body(body) end # Is the particle ready for deletion? def done # Let's find the screen position of the particle pos = box2d.get_body_pixel_coord(body) # Is it off the bottom of the screen? if (pos.y > $app.height) kill_body! return true end return false end # Drawing the box def display # We look at each body and get its screen position pos = box2d.get_body_pixel_coord(body) # Get its angle of rotation a = body.get_angle f = body.get_fixture_list ps = f.get_shape rect_mode(CENTER) push_matrix translate(pos.x, pos.y) rotate(-a) fill(175) stroke(0) begin_shape # For every vertex, convert to pixel vector ps.get_vertex_count.times do |i| v = box2d.vector_world_to_pixels(ps.get_vertex(i)) vertex(v.x, v.y) end end_shape(CLOSE) pop_matrix end # This function adds the rectangle to the box2d world def make_body(center) # Define a polygon (this is what we use for a rectangle) sd = B2D::PolygonShape.new vertices = [] vertices << box2d.vector_pixels_to_world(B2D::Vec2.new(-15, 25)) vertices << box2d.vector_pixels_to_world(B2D::Vec2.new(15, 0)) vertices << box2d.vector_pixels_to_world(B2D::Vec2.new(20, -15)) vertices << box2d.vector_pixels_to_world(B2D::Vec2.new(-10, -10)) sd.set(vertices.to_java(Java::OrgJbox2dCommon::Vec2), vertices.length) # Define the body and make it from the shape bd = B2D::BodyDef.new bd.type = B2D::BodyType::DYNAMIC bd.position.set(box2d.coord_pixels_to_world(center)) @body = box2d.create_body(bd) body.create_fixture(sd, 1.0) # Give it some initial random velocity body.set_linear_velocity(Vec2.new(rand(-5 .. 5), rand(2 .. 5))) body.set_angular_velocity(rand(-5 .. 5)) end end # The Nature of Code # <http://www.shiffman.net/teaching/nature> # Spring 2012 # PBox2D example # A fixed boundary class (now incorporates angle) class Boundary attr_reader :box2d, :b, :x, :y, :w, :h #, :a def initialize(b2d, x, y, w, h, a) @box2d = b2d @x = x @y = y @w = w @h = h # Define the polygon sd = B2D::PolygonShape.new # Figure out the box2d coordinates box2dW = box2d.scalar_pixels_to_world(w/2) box2dH = box2d.scalar_pixels_to_world(h/2) # We're just a box sd.set_as_box(box2dW, box2dH) # Create the body bd = B2D::BodyDef.new bd.type = B2D::BodyType::STATIC bd.angle = a bd.position.set(box2d.coord_pixels_to_world(x,y)) @b = box2d.create_body(bd) # Attached the shape to the body using a Fixture b.create_fixture(sd,1) end # Draw the boundary, it doesn't move so we don't have to ask the Body for location def display fill(0) stroke(0) stroke_weight(1) rect_mode(CENTER) a = b.get_angle push_matrix translate(x,y) rotate(-a) rect(0,0,w,h) pop_matrix end end end
Labels:
jbox2d,
jruby,
library module,
pbox2d,
physics,
processing,
ruby-processing
Subscribe to:
Posts (Atom)
Followers
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