Skip to content

Commit b85c810

Browse files
committed
pure JRubyArt lenny explorer
1 parent efc9846 commit b85c810

File tree

7 files changed

+170
-0
lines changed

7 files changed

+170
-0
lines changed

contributed/lenny_explorer.rb

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# lenny_explorer.rb
2+
# After 'The Explorer' by Leander Herzog, and a toxiclibs version by Karsten
3+
# Schmidt. This is a pure JRubyArt version by Martin Prout
4+
load_library :lenny
5+
attr_reader :path
6+
7+
def settings
8+
size(600, 600)
9+
end
10+
11+
def setup
12+
sketch_title 'Lenny Explorer'
13+
no_fill
14+
# @path = Path.new(
15+
# Boundary.new(
16+
# Rect.new(
17+
# Vec2D.new(10, 10),
18+
# Vec2D.new(width - 20, height - 20)
19+
# )
20+
# ),
21+
# 10,
22+
# 0.03,
23+
# 3_000
24+
# )
25+
@path = Path.new(
26+
Boundary.new(Circle.new(Vec2D.new(width / 2, height / 2), 250)),
27+
10,
28+
0.03,
29+
3_000
30+
)
31+
end
32+
33+
def draw
34+
background(255)
35+
50.times { path.grow }
36+
path.render(g)
37+
end
38+
39+
def mouse_pressed
40+
save_frame data_path('lenny.png')
41+
end

contributed/library/lenny/lenny.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
require_relative 'lib/rect'
2+
require_relative 'lib/circle'
3+
require_relative 'lib/boundary'
4+
require_relative 'lib/path'
5+
require_relative 'lib/line2d'
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Duck typing Boundary
2+
class Boundary
3+
attr_reader :bounds
4+
def initialize(bounds)
5+
@bounds = bounds
6+
end
7+
8+
def contains?(vec)
9+
bounds.contains?(vec)
10+
end
11+
12+
def centroid
13+
bounds.centroid
14+
end
15+
end
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# For use with Boundary
2+
class Circle
3+
attr_reader :centroid, :radius
4+
def initialize(center, radius)
5+
@centroid = center
6+
@radius = radius
7+
end
8+
9+
def contains?(vec)
10+
centroid.dist(vec) < radius
11+
end
12+
end
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Use to detect whether instances of line intersect
2+
class Line2D
3+
attr_reader :a, :b
4+
def initialize(a, b)
5+
@a = a
6+
@b = b
7+
end
8+
9+
def intersecting?(line)
10+
denom = (line.b.y - line.a.y) * (b.x - a.x) - (line.b.x - line.a.x) * (b.y - a.y)
11+
na = (line.b.x - line.a.x) * (a.y - line.a.y) - (line.b.y - line.a.y) * (a.x - line.a.x)
12+
nb = (b.x - a.x) * (a.y - line.a.y) - (b.y - a.y) * (a.x - line.a.x)
13+
return false if denom.zero?
14+
15+
ua = na / denom
16+
ub = nb / denom
17+
(ua >= 0.0 && ua <= 1.0 && ub >= 0.0 && ub <= 1.0)
18+
end
19+
end
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# Stores and manipulates the path
2+
class Path
3+
attr_reader :path, :last, :bounds, :cut, :theta, :delta, :speed, :searches
4+
5+
def initialize(bounds, speed, delta, history)
6+
@bounds = bounds
7+
@speed = speed
8+
@delta = delta
9+
@theta = 0
10+
@path = (0..history).map { bounds.centroid.copy }
11+
@searches = 0
12+
@last = Vec2D.new(path.first)
13+
end
14+
15+
def grow
16+
@delta = rand(-0.2..0.2) if rand < 0.1
17+
if !intersecting?
18+
move
19+
else
20+
search
21+
end
22+
end
23+
24+
def move
25+
@last = path.first
26+
path.pop
27+
@theta += delta
28+
path.unshift last + Vec2D.new(speed * Math.cos(theta), speed * Math.sin(theta))
29+
@searches = 0
30+
end
31+
32+
def search
33+
@theta += delta
34+
path[0] = last + Vec2D.new(speed * Math.cos(theta), speed * Math.sin(theta))
35+
@searches += 1
36+
end
37+
38+
def render(gfx)
39+
gfx.begin_shape
40+
path.map { |vec| gfx.curve_vertex(vec.x, vec.y) }
41+
gfx.end_shape
42+
end
43+
44+
def intersecting?
45+
return true unless bounds.contains?(path.first)
46+
47+
if searches < 100
48+
a = Line2D.new(path[0], path[1])
49+
(3...path.length).each do |i|
50+
b = Line2D.new(path[i], path[i - 1])
51+
return true if a.intersecting?(b)
52+
end
53+
end
54+
false
55+
end
56+
end
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# For use with Boundary
2+
class Rect
3+
attr_reader :vec1, :vec2
4+
def initialize(vec1, vec2)
5+
@vec1 = vec1
6+
@vec2 = vec2
7+
end
8+
9+
def centroid
10+
(vec1 + vec2) / 2
11+
end
12+
13+
def contains?(vec)
14+
xminmax = [vec1.x, vec2.x]
15+
yminmax = [vec1.y, vec2.y]
16+
return false if vec.x < xminmax[0]
17+
return false if vec.x > xminmax[1]
18+
return false if vec.y < yminmax[0]
19+
20+
vec.y < yminmax[1]
21+
end
22+
end

0 commit comments

Comments
 (0)