Caught this on twitter
So here is the liquidy.rb example updated:-
load_libraries :box2d_processing, :particle_system
include PS
attr_reader :box2d, :boundaries, :systems
def setup
size(400,300)
smooth
@box2d = PS::Box2DProcessing.new(self)
box2d.create_world
box2d.set_gravity(0, -20)
@systems = []
@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)
box2d.step
if systems.size > 0
systems.each do |system|
system.run
system.add_particles(box2d, rand(0 .. 2))
end
end
boundaries.each do |wall|
wall.display
end
end
def mouse_pressed
systems << ParticleSystem.new(box2d, 0, mouse_x, mouse_y)
end
Here is the particle_system library, particle_system.rb
module PS
include_package 'org.jbox2d.collision.shapes'
include_package 'org.jbox2d.common'
include_package 'org.jbox2d.dynamics'
include_package 'shiffman.box2d'
class ParticleSystem
attr_reader :particles, :x, :y
def initialize(bd, num, x, y)
@particles = []
@x, @y = x, y
num.times do
particles << PS::Particle.new(bd, x, y)
end
end
def run
particles.each do |p|
p.display
end
particles.delete_if { |p| p.done}
end
def add_particles(bd, n)
n.times do
particles << PS::Particle.new(bd, x, y)
end
end
def dead
particles.empty?
end
end
class Particle
TRAIL_SIZE = 6
attr_reader :trail, :body, :box2d
def initialize(b2d, x, y)
@box2d = b2d
@trail = Array.new(TRAIL_SIZE, [x, y])
make_body(PS::Vec2.new(x,y), 0.2)
end
def kill_body
box2d.destroy_body(body)
end
def done
pos = box2d.get_body_pixel_coord(body)
if (pos.y > $app.height + 20)
kill_body
return true
end
return false
end
def display
pos = box2d.get_body_pixel_coord(body)
(TRAIL_SIZE - 1).times do |i|
trail[i] = trail[i + 1]
end
trail[TRAIL_SIZE - 1] = [pos.x, pos.y]
begin_shape
noFill
stroke_weight(2)
stroke(0,150)
trail.each do |v|
vertex(v[0], v[1])
end
end_shape
end
def make_body(center, r)
bd = PS::BodyDef.new
bd.type = PS::BodyType::DYNAMIC
bd.position.set(box2d.coord_pixels_to_world(center))
@body = box2d.create_body(bd)
body.set_linear_velocity(PS::Vec2.new(rand(-1 .. 1), rand(-1 .. 1)))
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
fd.restitution = 0.5
body.create_fixture(fd)
end
end
class Boundary
attr_reader :box2d, :b, :x, :y, :w, :h
def initialize(b2d, x, y, w, h, a)
@box2d = b2d
@x = x
@y = y
@w = w
@h = h
sd = PS::PolygonShape.new
box2dW = box2d.scalar_pixels_to_world(w/2)
box2dH = box2d.scalar_pixels_to_world(h/2)
sd.set_as_box(box2dW, box2dH)
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)
b.create_fixture(sd,1)
end
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
It occurs to me, that with a bit more work and I could create a ruby-processing library to simplify the use of JBox2D? Thus replacing need for both fisica and box2d_processing libraries.
Except that Ricard Marxer and Daniel Shiffman have both created some very nice examples. See other examples
here.