Skip to content

Commit dd5138a

Browse files
author
monkstone
committed
pbox2d examples
1 parent f248a7b commit dd5138a

File tree

13 files changed

+709
-0
lines changed

13 files changed

+709
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# The Nature of Code
2+
# Daniel Shiffman
3+
# http://natureofcode.com
4+
require 'forwardable'
5+
6+
# A fixed boundary class
7+
class Boundary
8+
extend Forwardable
9+
def_delegators(:@app, :box2d, :rect_mode, :rect, :fill, :stroke)
10+
# A boundary is a simple rectangle with x, y, width, and height
11+
attr_reader :x, :y, :w, :h
12+
13+
def initialize(x, y, w, h)
14+
@x, @y, @w, @h = x, y, w, h
15+
@app = $app
16+
# Define the polygon
17+
sd = PolygonShape.new
18+
# Figure out the box2d coordinates
19+
box2dW = box2d.scale_to_world(w / 2)
20+
box2dH = box2d.scale_to_world(h / 2)
21+
# We're just a box
22+
sd.setAsBox(box2dW, box2dH)
23+
# Create the body
24+
bd = BodyDef.new
25+
bd.type = BodyType::STATIC
26+
bd.position.set(box2d.processing_to_world(x,y))
27+
b = box2d.createBody(bd)
28+
# Attached the shape to the body using a Fixture
29+
b.createFixture(sd,1)
30+
end
31+
32+
# Draw the boundary, if it were at an angle we'd have to do something fancier
33+
def display
34+
fill(0)
35+
stroke(0)
36+
rect_mode(Java::ProcessingCore::PConstants::CENTER)
37+
rect(x, y, w, h)
38+
end
39+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# The Nature of Code
2+
# Daniel Shiffman
3+
# http://natureofcode.com
4+
5+
# Example demonstrating distance joints
6+
# A bridge is formed by connected a series of particles with joints
7+
8+
require 'pbox2d'
9+
require_relative 'boundary'
10+
require_relative 'pair'
11+
require_relative 'particle'
12+
13+
attr_reader :box2d, :boundaries, :pairs
14+
15+
def setup
16+
size(640, 360)
17+
# Initialize box2d physics and create the world
18+
@box2d = Box2D.new(self)
19+
box2d.create_world
20+
@pairs = []
21+
@boundaries = []
22+
# Add a bunch of fixed boundaries
23+
boundaries << Boundary.new(width / 4, height - 5, width / 2 - 50, 10)
24+
boundaries << Boundary.new(3 * width / 4, height - 50, width / 2 - 50, 10)
25+
end
26+
27+
def draw
28+
background(255)
29+
pairs.each(&:display)
30+
# Display all the boundaries
31+
boundaries.each(&:display)
32+
fill(0)
33+
text('Click mouse to add connected particles.', 10, 20)
34+
end
35+
36+
def mouse_pressed
37+
pairs << Pair.new(mouse_x, mouse_y)
38+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# The Nature of Code
2+
# Daniel Shiffman
3+
# http://natureofcode.com
4+
require 'forwardable'
5+
6+
# Series of Particles connected with distance joints
7+
class Pair
8+
extend Forwardable
9+
def_delegators(:@app, :box2d, :stroke, :line, :stroke_weight)
10+
attr_reader :p1, :p2, :len
11+
# Chain constructor
12+
def initialize(x, y)
13+
@app = $app
14+
@len = 32
15+
@p1 = Particle.new(x, y)
16+
@p2 = Particle.new(x + rand(-1..1.0), y + rand(-1..1.0))
17+
djd = DistanceJointDef.new
18+
# Connection between previous particle and this one
19+
djd.bodyA = p1.body
20+
djd.bodyB = p2.body
21+
# Equilibrium length
22+
djd.length = box2d.scale_to_world(len)
23+
# These properties affect how springy the joint is
24+
djd.frequencyHz = 3 # Try a value less than 5 (0 for no elasticity)
25+
djd.dampingRatio = 0.1 # Ranges between 0 and 1 (1 for no springiness)
26+
# Make the joint. Note we aren't storing a reference to the joint ourselves anywhere!
27+
# We might need to someday, but for now it's ok
28+
box2d.world.create_joint(djd)
29+
end
30+
31+
def display
32+
pos1 = box2d.body_coord(p1.body)
33+
pos2 = box2d.body_coord(p2.body)
34+
stroke(0)
35+
stroke_weight(2)
36+
line(pos1.x, pos1.y, pos2.x, pos2.y)
37+
p1.display
38+
p2.display
39+
end
40+
end
41+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
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, :fill, :stroke, :stroke_weight, :box2d, :height, :line,
10+
:push_matrix, :pop_matrix, :ellipse, :rotate, :translate)
11+
# We need to keep track of a Body and a radius
12+
attr_reader :body, :r
13+
14+
def initialize(x, y)
15+
@r = 8
16+
@app = $app
17+
# Define a body
18+
bd = BodyDef.new
19+
# Set its position
20+
bd.position = box2d.processing_to_world(x,y)
21+
bd.type = BodyType::DYNAMIC
22+
@body = box2d.world.createBody(bd)
23+
24+
# Make the body's shape a circle
25+
cs = CircleShape.new
26+
cs.m_radius = box2d.scale_to_world(r)
27+
28+
fd = FixtureDef.new
29+
fd.shape = cs
30+
# Parameters that affect physics
31+
fd.density = 1
32+
fd.friction = 0.01
33+
fd.restitution = 0.3
34+
35+
# Attach fixture to body
36+
body.createFixture(fd)
37+
body.setLinearVelocity(Vec2.new(rand(-5..5), rand(2..5)))
38+
end
39+
40+
# This function removes the particle from the box2d world
41+
def kill_body
42+
box2d.destroy_body(body)
43+
end
44+
45+
# Is the particle ready for deletion?
46+
def done
47+
# Let's find the screen position of the particle
48+
pos = box2d.body_coord(body)
49+
# Is it off the bottom of the screen?
50+
if pos.y > height + r * 2
51+
kill_body
52+
return true
53+
end
54+
false
55+
end
56+
57+
def display
58+
# We look at each body and get its screen position
59+
pos = box2d.body_coord(body)
60+
# Get its angle of rotation
61+
a = body.get_angle
62+
push_matrix
63+
translate(pos.x, pos.y)
64+
rotate(a)
65+
fill(127)
66+
stroke(0)
67+
stroke_weight(2)
68+
ellipse(0, 0, r * 2, r * 2)
69+
# Let's add a line so we can see the rotation
70+
line(0, 0, r, 0)
71+
pop_matrix
72+
end
73+
end
74+
75+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# The Nature of Code
2+
# Daniel Shiffman
3+
# http://natureofcode.com
4+
5+
# A fixed boundary class (now incorporates angle)
6+
class Boundary
7+
extend Forwardable
8+
def_delegators(:@app, :fill, :no_fill, :stroke, :rect, :rect_mode, :box2d,
9+
:stroke_weight, :translate, :push_matrix, :pop_matrix, :rotate)
10+
# A boundary is a simple rectangle with x,y,width,and height
11+
attr_reader :x, :y, :w, :h, :b
12+
13+
def initialize(x, y, w, h, a)
14+
@x, @y, @w, @h, @a = x, y, w, h, a
15+
@app = $app
16+
# Define the polygon
17+
sd = PolygonShape.new
18+
# Figure out the box2d coordinates
19+
box2dw = box2d.scale_to_world(w / 2)
20+
box2dh = box2d.scale_to_world(h / 2)
21+
# We're just a box
22+
sd.setAsBox(box2dw, box2dh)
23+
# Create the body
24+
bd = BodyDef.new
25+
bd.type = BodyType::STATIC
26+
bd.angle = a
27+
bd.position.set(box2d.processing_to_world(x, y))
28+
@b = box2d.create_body(bd)
29+
# Attached the shape to the body using a Fixture
30+
b.create_fixture(sd, 1)
31+
end
32+
33+
# Draw the boundary, if it were at an angle we'd have to do something fancier
34+
def display
35+
no_fill
36+
stroke(127)
37+
fill(127)
38+
stroke_weight(1)
39+
rect_mode(Java::ProcessingCore::PConstants::CENTER)
40+
a = b.get_angle
41+
push_matrix
42+
translate(x, y)
43+
rotate(-a)
44+
rect(0, 0, w, h)
45+
pop_matrix
46+
end
47+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# The Nature of Code
2+
# Daniel Shiffman
3+
# http://natureofcode.com
4+
5+
# A rectangular box
6+
class Box
7+
extend Forwardable
8+
def_delegators(:@app, :fill, :stroke, :stroke_weight, :rect, :rect_mode,
9+
:box2d, :rotate, :translate, :push_matrix, :pop_matrix)
10+
# We need to keep track of a Body and a width and height
11+
attr_accessor :body, :w, :h
12+
# Constructor
13+
def initialize(x, y)
14+
@app = $app
15+
@w, @h = 24, 24
16+
# Add the box to the box2d world
17+
make_body(Vec2.new(x, y), w, h)
18+
end
19+
20+
# This function removes the particle from the box2d world
21+
def kill_body
22+
box2d.destroy_body(body)
23+
end
24+
25+
def contains(x, y)
26+
world_point = box2d.processing_to_world(x, y)
27+
f = body.get_fixture_list
28+
f.test_point(world_point)
29+
end
30+
31+
# Drawing the box
32+
def display
33+
# We look at each body and get its screen position
34+
pos = box2d.body_coord(body)
35+
# Get its angle of rotation
36+
a = body.getAngle
37+
rect_mode(Java::ProcessingCore::PConstants::CENTER)
38+
push_matrix
39+
translate(pos.x, pos.y)
40+
rotate(a)
41+
fill(127)
42+
stroke(0)
43+
stroke_weight(2)
44+
rect(0, 0, w, h)
45+
pop_matrix
46+
end
47+
48+
# This function adds the rectangle to the box2d world
49+
def make_body(center, w, h)
50+
# Define and create the body
51+
bd = BodyDef.new
52+
bd.type = BodyType::DYNAMIC
53+
bd.position.set(box2d.processing_to_world(center))
54+
@body = box2d.createBody(bd)
55+
# Define a polygon (this is what we use for a rectangle)
56+
sd = PolygonShape.new
57+
box2dw = box2d.scale_to_world(w / 2)
58+
box2dh = box2d.scale_to_world(h / 2)
59+
sd.setAsBox(box2dw, box2dh)
60+
# Define a fixture
61+
fd = FixtureDef.new
62+
fd.shape = sd
63+
# Parameters that affect physics
64+
fd.density = 1
65+
fd.friction = 0.3
66+
fd.restitution = 0.5
67+
body.create_fixture(fd)
68+
# Give it some initial random velocity
69+
body.set_linear_velocity(Vec2.new(rand(-5.0..5), rand(2.0..5)))
70+
body.set_angular_velocity(rand(-5.0..5))
71+
end
72+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# The Nature of Code
2+
# Daniel Shiffman
3+
# http://natureofcode.com
4+
5+
# This class avoids test for nil
6+
class DummySpring
7+
def initialize; end
8+
9+
# If it exists we set its target to the mouse location
10+
def update(_x, _y); end
11+
12+
def display; end
13+
14+
# This is the key function where
15+
# we attach the spring to an x,y location
16+
# and the Box object's location
17+
def bind(x, y, box)
18+
spring = Spring.new
19+
spring.bind(x, y, box)
20+
spring
21+
end
22+
23+
def destroy; end
24+
end

0 commit comments

Comments
 (0)