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.
@@ -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
- # This module allows package access to the wrapped java packages
8
- module PB
9
- include_package 'org.jbox2d.collision.shapes'
10
- include_package 'org.jbox2d.common'
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
- ContactListener = Java::OrgJbox2dCallbacks::ContactListener
17
- Transform = PB::Transform
18
- Vec2 = PB::Vec2
19
- Body = PB::Body
20
- BodyDef = PB::BodyDef
21
- BodyType = PB::BodyType
22
- World = PB::World
23
- Joint = PB::Joint
24
- JointDef = PB::JointDef
25
- FixtureDef = PB::FixtureDef
26
- PolygonShape = PB::PolygonShape
27
- CircleShape = PB::CircleShape
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 step_options(args = {})
21
- time_step = args.fetch(:time_step, 1.0 / 60)
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)
@@ -1,4 +1,4 @@
1
1
  # Module here just to keep namespace tidy
2
2
  module Pbox2D
3
- VERSION = '0.3.1'
3
+ VERSION = '0.4.0'
4
4
  end
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.3.1
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: 2014-12-09 00:00:00.000000000 Z
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