pbox2d 0.3.1-java → 0.4.0-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +4 -2
- data/Rakefile +2 -2
- data/examples/bumpy_surface_noise.rb +41 -0
- data/examples/distance_joint/boundary.rb +39 -0
- data/examples/distance_joint/distance_joint.rb +38 -0
- data/examples/distance_joint/pair.rb +41 -0
- data/examples/distance_joint/particle.rb +75 -0
- data/examples/lib/boundary.rb +30 -0
- data/examples/lib/box.rb +15 -0
- data/examples/lib/custom_shape.rb +0 -0
- data/examples/lib/particle_system.rb +154 -0
- data/examples/lib/surface.rb +136 -0
- data/examples/liquid_fun_test.rb +42 -0
- data/examples/liquidy.rb +36 -0
- data/examples/polygons.rb +39 -0
- data/examples/quick_test.rb +141 -0
- data/examples/revolute_joint/box.rb +68 -0
- data/examples/revolute_joint/particle.rb +86 -0
- data/examples/revolute_joint/revolute_joint.rb +44 -0
- data/examples/revolute_joint/windmill.rb +53 -0
- data/examples/test_contact/lib/boundary.rb +33 -0
- data/examples/test_contact/lib/custom_listener.rb +29 -0
- data/examples/test_contact/lib/particle.rb +77 -0
- data/examples/test_contact/test_contact.rb +25 -0
- data/lib/box2d.jar +0 -0
- data/lib/pbox2d.rb +16 -20
- data/lib/pbox2d/box2d.rb +8 -6
- data/lib/pbox2d/version.rb +1 -1
- metadata +24 -2
@@ -0,0 +1,86 @@
|
|
1
|
+
# The Nature of Code
|
2
|
+
# Daniel Shiffman
|
3
|
+
# http://natureofcode.com
|
4
|
+
require 'forwardable'
|
5
|
+
|
6
|
+
# A circular particle
|
7
|
+
class Particle
|
8
|
+
extend Forwardable
|
9
|
+
def_delegators(:@app, :box2d, :push_matrix, :pop_matrix, :fill, :rotate,
|
10
|
+
:line, :stroke_weight, :translate, :rect_mode, :stroke,
|
11
|
+
:ellipse, :height)
|
12
|
+
# We need to keep track of a Body and a radius
|
13
|
+
attr_reader :body, :r
|
14
|
+
|
15
|
+
def initialize(x, y, r)
|
16
|
+
@app = $app
|
17
|
+
@r = r
|
18
|
+
# This function puts the particle in the Box2d world
|
19
|
+
makeBody(x, y, r)
|
20
|
+
body.setUserData(self)
|
21
|
+
end
|
22
|
+
|
23
|
+
# This function removes the particle from the box2d world
|
24
|
+
def kill_body
|
25
|
+
box2d.destroyBody(body)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Is the particle ready for deletion?
|
29
|
+
def done?
|
30
|
+
# Let's find the screen position of the particle
|
31
|
+
pos = box2d.body_coord(body)
|
32
|
+
# Is it off the bottom of the screen?
|
33
|
+
if pos.y > height + r * 2
|
34
|
+
kill_body
|
35
|
+
return true
|
36
|
+
end
|
37
|
+
false
|
38
|
+
end
|
39
|
+
|
40
|
+
#
|
41
|
+
def display
|
42
|
+
# We look at each body and get its screen position
|
43
|
+
pos = box2d.body_coord(body)
|
44
|
+
# Get its angle of rotation
|
45
|
+
a = body.getAngle
|
46
|
+
push_matrix
|
47
|
+
translate(pos.x, pos.y)
|
48
|
+
rotate(-a)
|
49
|
+
fill(127)
|
50
|
+
stroke(0)
|
51
|
+
stroke_weight(2)
|
52
|
+
ellipse(0, 0, r * 2, r * 2)
|
53
|
+
# Let's add a line so we can see the rotation
|
54
|
+
line(0, 0, r, 0)
|
55
|
+
pop_matrix
|
56
|
+
end
|
57
|
+
|
58
|
+
# Here's our function that adds the particle to the Box2D world
|
59
|
+
def makeBody(x, y, r)
|
60
|
+
# Define a body
|
61
|
+
bd = BodyDef.new
|
62
|
+
# Set its position
|
63
|
+
bd.position = box2d.processing_to_world(x, y)
|
64
|
+
bd.type = BodyType::DYNAMIC
|
65
|
+
|
66
|
+
@body = box2d.world.createBody(bd)
|
67
|
+
|
68
|
+
# Make the body's shape a circle
|
69
|
+
cs = CircleShape.new
|
70
|
+
cs.m_radius = box2d.scale_to_world(r)
|
71
|
+
|
72
|
+
fd = FixtureDef.new
|
73
|
+
fd.shape = cs
|
74
|
+
|
75
|
+
fd.density = 2.0
|
76
|
+
fd.friction = 0.01
|
77
|
+
fd.restitution = 0.3 # Restitution is bounciness
|
78
|
+
|
79
|
+
body.createFixture(fd)
|
80
|
+
|
81
|
+
# Give it a random initial velocity (and angular velocity)
|
82
|
+
# body.setLinearVelocity(Vec2.new(rand(-10.0..10), rand(5.0..10)))
|
83
|
+
body.setAngularVelocity(rand(-10.0..10))
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# The Nature of Code
|
2
|
+
# Daniel Shiffman
|
3
|
+
# http://natureofcode.com
|
4
|
+
|
5
|
+
# Example demonstrating revolute joint
|
6
|
+
require 'pbox2d'
|
7
|
+
require_relative 'windmill'
|
8
|
+
require_relative 'particle'
|
9
|
+
|
10
|
+
attr_reader :box2d, :windmill, :particles
|
11
|
+
|
12
|
+
def setup
|
13
|
+
size(640,360)
|
14
|
+
@box2d = Box2D.new(self)
|
15
|
+
box2d.createWorld
|
16
|
+
@windmill = Windmill.new(width / 2, 175)
|
17
|
+
@particles = []
|
18
|
+
end
|
19
|
+
|
20
|
+
# Click the mouse to turn on or off the motor
|
21
|
+
def mouse_pressed
|
22
|
+
windmill.toggle_motor
|
23
|
+
end
|
24
|
+
|
25
|
+
def draw
|
26
|
+
background(255)
|
27
|
+
if rand < 0.1
|
28
|
+
sz = rand(4.0..8)
|
29
|
+
particles << Particle.new(rand(width / 2 - 100..width / 2 + 100), -20, sz)
|
30
|
+
end
|
31
|
+
# Look at all particles, in reverse order
|
32
|
+
particles.reverse_each do |p|
|
33
|
+
p.display
|
34
|
+
# Particles that leave the screen, we delete them
|
35
|
+
# (note they have to be deleted from both the box2d world and our list
|
36
|
+
next unless p.done?
|
37
|
+
particles.shift
|
38
|
+
end
|
39
|
+
# Draw the windmill
|
40
|
+
windmill.display
|
41
|
+
status = windmill.motor_on? ? "ON" : "OFF"
|
42
|
+
fill(0)
|
43
|
+
text(format("Click mouse to toggle motor.\nMotor: %s", status), 10, height - 30)
|
44
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# The Nature of Code
|
2
|
+
# Daniel Shiffman
|
3
|
+
# http://natureofcode.com
|
4
|
+
require 'forwardable'
|
5
|
+
require_relative 'box'
|
6
|
+
|
7
|
+
# Class to describe a fixed spinning object
|
8
|
+
class Windmill
|
9
|
+
extend Forwardable
|
10
|
+
def_delegators(:@app, :ellipse, :no_stroke, :box2d, :fill)
|
11
|
+
# Our object is two boxes and one joint
|
12
|
+
# Consider making the fixed box much smaller and not drawing it
|
13
|
+
attr_reader :joint, :box1, :box2
|
14
|
+
|
15
|
+
def initialize(x, y)
|
16
|
+
@app = $app
|
17
|
+
# Initialize locations of two boxes
|
18
|
+
@box1 = Box.new(x, y - 20, 120, 10, false)
|
19
|
+
@box2 = Box.new(x, y, 10, 40, true)
|
20
|
+
# Define joint as between two bodies
|
21
|
+
rjd = RevoluteJointDef.new
|
22
|
+
# NB: using java_send to access the unreachable 'initialize' method
|
23
|
+
rjd.java_send :initialize, [Body, Body, Vec2], box1.body, box2.body, box1.body.getWorldCenter
|
24
|
+
# Turning on a motor (optional)
|
25
|
+
rjd.motorSpeed = Math::PI * 2 # how fast?
|
26
|
+
rjd.maxMotorTorque = 1000.0 # how powerful?
|
27
|
+
rjd.enableMotor = false # is it on?
|
28
|
+
# There are many other properties you can set for a Revolute joint
|
29
|
+
# For example, you can limit its angle between a minimum and a maximum
|
30
|
+
# See box2d manual for more
|
31
|
+
# Create the joint
|
32
|
+
@joint = box2d.world.createJoint(rjd)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Turn the motor on or off
|
36
|
+
def toggle_motor
|
37
|
+
joint.enableMotor(!joint.isMotorEnabled)
|
38
|
+
end
|
39
|
+
|
40
|
+
def motor_on?
|
41
|
+
joint.isMotorEnabled
|
42
|
+
end
|
43
|
+
|
44
|
+
def display
|
45
|
+
box2.display
|
46
|
+
box1.display
|
47
|
+
# Draw anchor just for debug
|
48
|
+
anchor = box2d.vector_to_processing(box1.body.getWorldCenter)
|
49
|
+
fill(0)
|
50
|
+
no_stroke
|
51
|
+
ellipse(anchor.x, anchor.y, 8, 8)
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
3
|
+
CENTER ||= Java::ProcessingCore::PConstants::CENTER
|
4
|
+
# The boundary class is used to create a floor in this
|
5
|
+
# sketch. Note it does not have a change method
|
6
|
+
class Boundary
|
7
|
+
extend Forwardable
|
8
|
+
def_delegators(:@app, :fill, :stroke, :rect, :rect_mode, :box2d)
|
9
|
+
attr_reader :x, :y, :w, :h, :b
|
10
|
+
def initialize(app, x, y, w, h)
|
11
|
+
@app, @x, @y, @w, @h = app, x, y, w, h
|
12
|
+
sd = PolygonShape.new
|
13
|
+
box2d_w = box2d.scale_to_world(w / 2)
|
14
|
+
box2d_h = box2d.scale_to_world(h / 2)
|
15
|
+
sd.set_as_box(box2d_w, box2d_h)
|
16
|
+
# Create the body
|
17
|
+
bd = BodyDef.new
|
18
|
+
bd.type = BodyType::STATIC
|
19
|
+
bd.position.set(box2d.processing_to_world(x, y))
|
20
|
+
@b = box2d.create_body(bd)
|
21
|
+
# Attached the shape to the body using a Fixture
|
22
|
+
b.create_fixture(sd, 1)
|
23
|
+
b.set_user_data(self)
|
24
|
+
end
|
25
|
+
|
26
|
+
# Draw the boundary, if it were at an angle we'd have to do something fancier
|
27
|
+
def display
|
28
|
+
fill(0)
|
29
|
+
stroke(0)
|
30
|
+
rect_mode(CENTER)
|
31
|
+
rect(x, y, w, h)
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# A custom listener allows us to get the physics engine to
|
2
|
+
# to call our code, on say contact (collisions)
|
3
|
+
class CustomListener
|
4
|
+
include ContactListener
|
5
|
+
|
6
|
+
def begin_contact(cp)
|
7
|
+
# Get both fixtures
|
8
|
+
f1 = cp.getFixtureA
|
9
|
+
f2 = cp.getFixtureB
|
10
|
+
# Get both bodies
|
11
|
+
b1 = f1.getBody
|
12
|
+
b2 = f2.getBody
|
13
|
+
# Get our objects that reference these bodies
|
14
|
+
o1 = b1.getUserData
|
15
|
+
o2 = b2.getUserData
|
16
|
+
return unless [o1, o2].all? { |obj| obj.respond_to?(:change) }
|
17
|
+
o1.change
|
18
|
+
o2.change
|
19
|
+
end
|
20
|
+
|
21
|
+
def end_contact(_cp)
|
22
|
+
end
|
23
|
+
|
24
|
+
def pre_solve(_cp, _m)
|
25
|
+
end
|
26
|
+
|
27
|
+
def post_solve(_cp, _ci)
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# Note the particle class change method is use to change color to red
|
2
|
+
# when two particles collide (no change just hitting boundary)
|
3
|
+
class Particle
|
4
|
+
extend Forwardable
|
5
|
+
def_delegators(:@app, :box2d, :begin_shape, :end_shape, :line, :pop_matrix,
|
6
|
+
:ellipse, :translate, :rotate, :stroke, :push_matrix,
|
7
|
+
:fill, :no_fill, :stroke_weight)
|
8
|
+
attr_accessor :body
|
9
|
+
attr_reader :radius, :col
|
10
|
+
|
11
|
+
def initialize(app, x, y, r)
|
12
|
+
@app, @x, @y, @radius = app, x, y, r
|
13
|
+
# This function puts the particle in the Box2d world
|
14
|
+
make_body(x, y, radius)
|
15
|
+
@col = -5_263_441 # grey
|
16
|
+
body.setUserData(self)
|
17
|
+
end
|
18
|
+
|
19
|
+
# This function removes the particle from the box2d world
|
20
|
+
def kill_body
|
21
|
+
box2d.destroy_body(body)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Change color when hit
|
25
|
+
def change
|
26
|
+
@col = -65_536 # red
|
27
|
+
end
|
28
|
+
|
29
|
+
# Is the particle ready for deletion?
|
30
|
+
def done
|
31
|
+
# Let's find the screen position of the particle
|
32
|
+
pos = box2d.body_coord(body)
|
33
|
+
# Is it off the bottom of the screen?
|
34
|
+
return false unless pos.y > (box2d.height + radius * 2)
|
35
|
+
kill_body
|
36
|
+
true
|
37
|
+
end
|
38
|
+
|
39
|
+
def display
|
40
|
+
# We look at each body and get its screen position
|
41
|
+
pos = box2d.body_coord(body)
|
42
|
+
# Get its angle of rotation
|
43
|
+
a = body.get_angle
|
44
|
+
push_matrix
|
45
|
+
translate(pos.x, pos.y)
|
46
|
+
rotate(a)
|
47
|
+
fill(col)
|
48
|
+
stroke(0)
|
49
|
+
stroke_weight(1)
|
50
|
+
ellipse(0, 0, radius * 2, radius * 2)
|
51
|
+
# Let's add a line so we can see the rotation
|
52
|
+
line(0, 0, radius, 0)
|
53
|
+
pop_matrix
|
54
|
+
end
|
55
|
+
|
56
|
+
# Here's our function that adds the particle to the Box2D world
|
57
|
+
def make_body(x, y, r)
|
58
|
+
# Define a body
|
59
|
+
bd = BodyDef.new
|
60
|
+
# Set its position
|
61
|
+
bd.position = box2d.processing_to_world(x, y)
|
62
|
+
bd.type = BodyType::DYNAMIC
|
63
|
+
@body = box2d.create_body(bd)
|
64
|
+
# Make the body's shape a circle
|
65
|
+
cs = CircleShape.new
|
66
|
+
cs.m_radius = box2d.scale_to_world(r)
|
67
|
+
fd = FixtureDef.new
|
68
|
+
fd.shape = cs
|
69
|
+
# Parameters that affect physics
|
70
|
+
fd.density = 1
|
71
|
+
fd.friction = 0.01
|
72
|
+
fd.restitution = 0.3
|
73
|
+
# Attach fixture to body
|
74
|
+
body.create_fixture(fd)
|
75
|
+
body.set_angular_velocity(rand(-10.0..10))
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'pbox2d'
|
2
|
+
require 'forwardable'
|
3
|
+
require_relative 'lib/custom_listener'
|
4
|
+
require_relative 'lib/particle'
|
5
|
+
require_relative 'lib/boundary'
|
6
|
+
|
7
|
+
attr_reader :box2d, :particles, :wall
|
8
|
+
|
9
|
+
def setup
|
10
|
+
size 400, 400
|
11
|
+
@box2d = Box2D.new(self)
|
12
|
+
box2d.create_world
|
13
|
+
box2d.add_listener(CustomListener.new)
|
14
|
+
@particles = []
|
15
|
+
@wall = Boundary.new(self, width / 2, height - 5, width, 10)
|
16
|
+
end
|
17
|
+
|
18
|
+
def draw
|
19
|
+
col = color('#ffffff')
|
20
|
+
background(col)
|
21
|
+
particles << Particle.new(self, rand(width), 20, rand(4..8)) if rand < 0.1
|
22
|
+
particles.each(&:display)
|
23
|
+
particles.reject!(&:done)
|
24
|
+
wall.display
|
25
|
+
end
|
data/lib/box2d.jar
CHANGED
Binary file
|
data/lib/pbox2d.rb
CHANGED
@@ -4,27 +4,23 @@ Dir[File.join(working_directory, '*.jar')].each do |jar|
|
|
4
4
|
require jar
|
5
5
|
end
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
include_package 'org.jbox2d.dynamics'
|
12
|
-
include_package 'org.jbox2d.dynamics.joints'
|
13
|
-
include_package 'processing.box2d'
|
7
|
+
ContactListener = Java::OrgJbox2dCallbacks::ContactListener
|
8
|
+
|
9
|
+
def import_class_list(list, string)
|
10
|
+
list.each { |d| java_import format(string, d) }
|
14
11
|
end
|
15
12
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
ChainShape = PB::ChainShape
|
13
|
+
common = %w( Vec2 Transform )
|
14
|
+
common_format = 'org.jbox2d.common.%s'
|
15
|
+
import_class_list(common, common_format)
|
16
|
+
shape = %w( PolygonShape CircleShape ChainShape Shape )
|
17
|
+
shape_format = 'org.jbox2d.collision.shapes.%s'
|
18
|
+
import_class_list(shape, shape_format)
|
19
|
+
world = %w( Body BodyDef BodyType World FixtureDef )
|
20
|
+
world_format = 'org.jbox2d.dynamics.%s'
|
21
|
+
import_class_list(world, world_format)
|
22
|
+
joint = %w( Joint JointDef DistanceJointDef RevoluteJoint RevoluteJointDef )
|
23
|
+
joint_format = 'org.jbox2d.dynamics.joints.%s'
|
24
|
+
import_class_list(joint, joint_format)
|
29
25
|
|
30
26
|
require_relative 'pbox2d/box2d.rb'
|
data/lib/pbox2d/box2d.rb
CHANGED
@@ -13,15 +13,17 @@ class Box2D < Java::ProcessingBox2d::Box2DProcessing
|
|
13
13
|
)
|
14
14
|
end
|
15
15
|
|
16
|
+
def step_options(args = {})
|
17
|
+
default_step.merge(args)
|
18
|
+
set_step(args[:time_step], args[:velocity_iter], args[:position_iter])
|
19
|
+
end
|
20
|
+
|
16
21
|
def defaults
|
17
|
-
{scale: 10.0, gravity: [0, -10], warm: true, continuous: true}
|
22
|
+
{ scale: 10.0, gravity: [0, -10], warm: true, continuous: true }
|
18
23
|
end
|
19
24
|
|
20
|
-
def
|
21
|
-
time_step
|
22
|
-
velocity = args.fetch(:velocity_iter, 8)
|
23
|
-
position = args.fetch(:position_iter, 10)
|
24
|
-
set_step(time_step, velocity, position)
|
25
|
+
def default_step
|
26
|
+
{ time_step: 1.0 / 60, velocity_iter: 8, position_iter: 10 }
|
25
27
|
end
|
26
28
|
|
27
29
|
def gravity(args)
|
data/lib/pbox2d/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pbox2d
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: java
|
6
6
|
authors:
|
7
7
|
- Martin Prout
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-04-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
@@ -74,6 +74,28 @@ files:
|
|
74
74
|
- lib/pbox2d.rb
|
75
75
|
- lib/pbox2d/box2d.rb
|
76
76
|
- lib/pbox2d/version.rb
|
77
|
+
- examples/bumpy_surface_noise.rb
|
78
|
+
- examples/distance_joint/boundary.rb
|
79
|
+
- examples/distance_joint/distance_joint.rb
|
80
|
+
- examples/distance_joint/pair.rb
|
81
|
+
- examples/distance_joint/particle.rb
|
82
|
+
- examples/lib/boundary.rb
|
83
|
+
- examples/lib/box.rb
|
84
|
+
- examples/lib/custom_shape.rb
|
85
|
+
- examples/lib/particle_system.rb
|
86
|
+
- examples/lib/surface.rb
|
87
|
+
- examples/liquid_fun_test.rb
|
88
|
+
- examples/liquidy.rb
|
89
|
+
- examples/polygons.rb
|
90
|
+
- examples/quick_test.rb
|
91
|
+
- examples/revolute_joint/box.rb
|
92
|
+
- examples/revolute_joint/particle.rb
|
93
|
+
- examples/revolute_joint/revolute_joint.rb
|
94
|
+
- examples/revolute_joint/windmill.rb
|
95
|
+
- examples/test_contact/lib/boundary.rb
|
96
|
+
- examples/test_contact/lib/custom_listener.rb
|
97
|
+
- examples/test_contact/lib/particle.rb
|
98
|
+
- examples/test_contact/test_contact.rb
|
77
99
|
- lib/box2d.jar
|
78
100
|
- lib/jbox2d-library-2.2.1-ds.jar
|
79
101
|
homepage: https://github.com/ruby-processing/jbox2d
|