pbox2d 0.3.1-java → 0.4.0-java
Sign up to get free protection for your applications and to get access to all the features.
- 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
|