Skip to content

Commit

Permalink
add jbox2d examples
Browse files Browse the repository at this point in the history
  • Loading branch information
monkstone committed Dec 3, 2014
1 parent 6a179d1 commit 0141b62
Show file tree
Hide file tree
Showing 17 changed files with 895 additions and 0 deletions.
3 changes: 3 additions & 0 deletions samples/external_library/ruby_gem/jbox2d/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
### java_args.txt

The `data` folder contains java_args.txt, which currently silently enables the OpenGl-based pipeline using `-Dsun.java2d.opengl=true` add any other java args here, use `True` instead of `true` to get a message.
41 changes: 41 additions & 0 deletions samples/external_library/ruby_gem/jbox2d/bumpy_surface_noise.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# The Nature of Code
# PBox2D example
# An uneven surface

require 'pbox2d'
require_relative 'lib/surface'

attr_reader :surface, :box2d, :particles

def setup
size(500, 300)
smooth 4
# Initialize box2d physics and create the world
@box2d = Box2D.new(self)
box2d.init_options(gravity: [0, -20])
box2d.create_world
# to later set a custom gravity
# box2d.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!
background(138, 66, 54)
# Draw the surface
surface.display
# NB ? 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(&:display)
# Particles that leave the screen, we delete them
# (note they have to be deleted from both the box2d world and our list
particles.reject!(&:done)
# Just drawing the framerate to see how many particles it can handle
fill(0)
text("framerate: #{frame_rate.to_i}", 12, 16)
end
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
-Dsun.java2d.opengl=true
27 changes: 27 additions & 0 deletions samples/external_library/ruby_gem/jbox2d/lib/boundary.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# The boundary class is used to create fixtures
class Boundary
include Processing::Proxy
attr_reader :box2d, :x, :y, :w, :h, :b
def initialize(b2d, x, y, w, h)
@box2d, @x, @y, @w, @h = b2d, x, y, w, h
sd = PolygonShape.new
box2d_w = box2d.scale_to_world(w / 2)
box2d_h = box2d.scale_to_world(h / 2)
sd.setAsBox(box2d_w, box2d_h)
# Create the body
bd = BodyDef.new
bd.type = BodyType::STATIC
bd.position.set(box2d.processing_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, if it were at an angle we'd have to do something fancier
def display
fill(0)
stroke(0)
rect_mode(CENTER)
rect(x, y, w, h)
end
end
15 changes: 15 additions & 0 deletions samples/external_library/ruby_gem/jbox2d/lib/box.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# A Box class, note how to access class ParticleGroupDef in jruby
# which is currently not on an included path for pbox2d
class Box
attr_accessor :pg
def initialize(b2d, x, y)
w = rand(1..3)
h = rand(1..3)
shape = PolygonShape.new
pos = b2d.processing_to_world(x, y)
shape.setAsBox(w, h, pos, 0)
pd = Java::OrgJbox2dParticle::ParticleGroupDef.new
pd.shape = shape
@pg = b2d.world.create_particle_group(pd)
end
end
111 changes: 111 additions & 0 deletions samples/external_library/ruby_gem/jbox2d/lib/custom_shape.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
require 'pbox2d'

class CustomShape
include Processing::Proxy
# 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(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.body_coord(body)
# Is it off the bottom of the screen?
return false unless pos.y > box2d.height
kill_body!
true
end

# Drawing the box
def display
# We look at each body and get its screen position
pos = box2d.body_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_to_processing(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 = PolygonShape.new
vertices = []
vertices << box2d.vector_to_world(Vec2.new(-15, 25))
vertices << box2d.vector_to_world(Vec2.new(15, 0))
vertices << box2d.vector_to_world(Vec2.new(20, -15))
vertices << box2d.vector_to_world(Vec2.new(-10, -10))
sd.set(vertices.to_java(Java::OrgJbox2dCommon::Vec2), vertices.length)
# Define the body and make it from the shape
bd = BodyDef.new
bd.type = BodyType::DYNAMIC
bd.position.set(box2d.processing_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.0..5), rand(2.0..5)))
body.set_angular_velocity(rand(-5.0..5))
end
end

class Boundary
include Processing::Proxy
attr_reader :box2d, :b, :x, :y, :w, :h
def initialize(b2d, x, y, w, h, a)
@box2d, @x, @y, @w, @h = b2d, x, y, w, h
# Define the polygon
sd = PolygonShape.new
# Figure out the box2d coordinates
box2d_w = box2d.scale_to_world(w / 2)
box2d_h = box2d.scale_to_world(h / 2)
# We're just a box
sd.set_as_box(box2d_w, box2d_h)
# Create the body
bd = BodyDef.new
bd.type = BodyType::STATIC
bd.angle = a
bd.position.set(box2d.processing_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
148 changes: 148 additions & 0 deletions samples/external_library/ruby_gem/jbox2d/lib/particle_system.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
require 'forwardable'

module Runnable
def run
reject! { |item| item.done }
each { |item| item.display }
end
end

class ParticleSystem
include Enumerable, Runnable
extend Forwardable
def_delegators(:@particles, :each, :reject!, :<<, :empty?)
def_delegator(:@particles, :empty?, :dead?)

attr_reader :x, :y

def initialize(bd, num, x, y)
@particles = [] # Initialize the Array
@x, @y = x, y # Store the origin point
num.times do
self << Particle.new(bd, x, y)
end
end

def add_particles(bd, n)
n.times do
self << Particle.new(bd, x, y)
end
end
end

# A Particle
require 'pbox2d'

class Particle
include Processing::Proxy
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(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.body_coord(body)
# Is it off the bottom of the screen?
return false unless (pos.y > box2d.height + 20)
kill_body
true
end

# Drawing the box
def display
# We look at each body and get its screen position
pos = box2d.body_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
no_fill
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(x, y, r)
# Define and create the body
bd = BodyDef.new
bd.type = BodyType::DYNAMIC
bd.position.set(box2d.processing_to_world(x, y))
@body = box2d.create_body(bd)
# Give it some initial random velocity
body.set_linear_velocity(Vec2.new(rand(-1.0..1), rand(-1.0..1)))
# Make the body's shape a circle
cs = CircleShape.new
cs.m_radius = box2d.scale_to_world(r)
fd = 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

class Boundary
include Processing::Proxy
attr_reader :box2d, :b, :x, :y, :w, :h

def initialize(b2d, x, y, w, h, a)
@box2d, @x, @y, @w, @h = b2d, x, y, w, h
# Define the polygon
sd = PolygonShape.new
# Figure out the box2d coordinates
box2d_w = box2d.scale_to_world(w / 2)
box2d_h = box2d.scale_to_world(h / 2)
# We're just a box
sd.set_as_box(box2d_w, box2d_h)
# Create the body
bd = BodyDef.new
bd.type = BodyType::STATIC
bd.angle = a
bd.position.set(box2d.processing_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
Loading

0 comments on commit 0141b62

Please sign in to comment.