trtl 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in trtl.gemspec
4
+ gemspec
data/LICENSE.md ADDED
@@ -0,0 +1,7 @@
1
+ Copyright (c) 2012 Peter Cooper
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,62 @@
1
+ # Trtl - Simple Ruby Turtle Graphics
2
+
3
+ ![example session](http://no.gd/p/trtl-20120708-034138.jpg)
4
+
5
+ ## Installation
6
+ gem install trtl
7
+
8
+ ## Description
9
+
10
+ Trtl is a simple turtle system inspired by Python's turtle.py. It provides
11
+ simple turtle drawing capabilities in Ruby, even if you're just at an IRb
12
+ prompt. It leans on Tk which is part of MRI 1.9's standard library so in theory it should
13
+ work 'out of the box' with most MRI 1.9 installs.
14
+
15
+ ## Usage
16
+
17
+ If Trtl detects you're in an IRb or Pry session, it'll automatically make turtle
18
+ methods available directly at the prompt. For example:
19
+
20
+ $ irb
21
+ > require 'trtl'
22
+ > forward 100
23
+ # At this point, a window appears with the turtle
24
+
25
+ If you wish to use Trtl from a regular Ruby script, you have a few options. You
26
+ can create a Trtl instance and use it directly:
27
+
28
+ require 'trtl'
29
+ t = Trtl.new
30
+ 10.times { t.left(24); t.forward(30); t.ensure_drawn }
31
+ t.wait
32
+
33
+ You can use Trtl's `run` method to use it in a more interactive fashion:
34
+
35
+ Trtl.new.run { 10.times { left(24); forward(30); ensure_drawn } }
36
+
37
+ Or you can include InteractiveTurtle and get a similar effect as if you were in
38
+ IRb:
39
+
40
+ include InteractiveTurtle
41
+ 10.times { left(24); forward(30) }
42
+
43
+ Note: Using InteractiveTurtle makes drawing slower as it ensures all graphics
44
+ are drawn after every action (as necessary for IRb use).
45
+
46
+ ## Examples
47
+
48
+ The examples in the `examples` folder should be reasonably illustrative. If you
49
+ try any of them, try `example4.rb` - it renders an awesome looking tree.
50
+
51
+ ![tree](http://no.gd/p/trtltree-20120708-035127.jpg)
52
+
53
+ ## Credits
54
+
55
+ * turtle.py for inspiration
56
+ * Some of the examples taken from examples for an earlier Ruby turtle found at http://www.rubyquiz.com/quiz104.html
57
+
58
+ ## Copyright and License
59
+
60
+ Copyright (c) 2012 Peter Cooper (other than minor parts of some samples.)
61
+
62
+ MIT licensed. See LICENSE.md
data/Rakefile ADDED
@@ -0,0 +1,5 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new
5
+ task :default => :test
@@ -0,0 +1,14 @@
1
+ require_relative '../lib/trtl'
2
+
3
+ # Example of using Trtl in a 'simple' interactive fashion
4
+
5
+ # In irb or pry this isn't needed as InteractiveTurtle will be
6
+ # included by default.
7
+ include InteractiveTurtle
8
+
9
+ 10.times do
10
+ left(24)
11
+ forward(30)
12
+ end
13
+
14
+ wait
@@ -0,0 +1,14 @@
1
+ require_relative '../lib/trtl'
2
+
3
+ # Example of using Trtl in a more traditional fashion
4
+
5
+ t = Trtl.new
6
+
7
+ 10.times do
8
+ t.left(24)
9
+ t.forward(30)
10
+ t.dot
11
+ t.ensure_drawn
12
+ end
13
+
14
+ gets
@@ -0,0 +1,21 @@
1
+ require_relative '../lib/trtl'
2
+
3
+ include InteractiveTurtle
4
+
5
+ # Example below taken from Ruby quiz turtle_graphics archive
6
+ # http://www.rubyquiz.com/quiz104.html
7
+
8
+ # BYZANTIUM
9
+
10
+ def byzantium(r, n)
11
+ return if n < 1
12
+ fd r; rt 135
13
+ 4.times {
14
+ pd; fd 2 * r * Math.sin(45 * DEG); pu
15
+ byzantium(r / 2, n - 1)
16
+ rt 90
17
+ }
18
+ lt 135; bk r
19
+ end
20
+
21
+ byzantium(100, 4)
@@ -0,0 +1,33 @@
1
+ require_relative '../lib/trtl'
2
+
3
+ # Example below adapted from Ruby quiz turtle_graphics archive
4
+ # http://www.rubyquiz.com/quiz104.html
5
+
6
+ # TREE
7
+
8
+ Trtl.new(:width => 2, :color => 'brown').run do
9
+ def tree(_size)
10
+ if _size < 10
11
+ forward _size; back _size; return
12
+ end
13
+ color 'brown'
14
+ forward _size / 3
15
+ color %w{green darkgreen darkolivegreen}.sample
16
+ left 30; tree _size * 2 / 3; right 30
17
+ forward _size / 6
18
+ right 25; tree _size / 2; left 25
19
+ forward _size / 3
20
+ width rand(2) + 1
21
+ right 25; tree _size / 2; left 25
22
+ forward _size / 6
23
+ back _size
24
+ ensure_drawn
25
+ end
26
+
27
+ left 90
28
+ back 180
29
+ pen_down
30
+ tree 300.0
31
+
32
+ wait
33
+ end
@@ -0,0 +1,12 @@
1
+ require_relative '../lib/trtl'
2
+
3
+ t = Trtl.new :color => 'blue', :width => 5
4
+
5
+ 10.times do
6
+ t.circle rand(100), 180, rand(10) + 15
7
+ t.dot 20
8
+ t.forward rand(100)
9
+ t.color %w{blue cyan yellow}.sample
10
+ end
11
+
12
+ t.wait
@@ -0,0 +1,12 @@
1
+ require_relative '../lib/trtl'
2
+
3
+ Trtl.new(:color => 'blue', :width => 5).run do
4
+ 10.times do
5
+ circle rand(100), 180, rand(10) + 15
6
+ dot 20
7
+ forward rand(100)
8
+ color %w{blue cyan yellow}.sample
9
+ end
10
+
11
+ wait
12
+ end
data/lib/trtl.rb ADDED
@@ -0,0 +1,171 @@
1
+ require 'tk'
2
+
3
+ class Trtl
4
+ VERSION = "0.0.1"
5
+
6
+ CANVAS_WIDTH = 800
7
+ CANVAS_HEIGHT = 600
8
+ HOME_X = CANVAS_WIDTH / 2
9
+ HOME_Y = CANVAS_HEIGHT / 2
10
+ COLORS = %w{red blue green white cyan pink yellow}
11
+ DEG = Math::PI / 180.0
12
+
13
+ attr_accessor :heading, :x, :y
14
+ attr_writer :color, :width
15
+ attr_reader :canvas
16
+
17
+ def initialize(options = {})
18
+ @color = options[:color] || COLORS.sample
19
+ @interactive = options[:interactive]
20
+ @canvas = options[:canvas] || self.class.canvas
21
+ @width = options[:width] || 1
22
+ @drawing = true
23
+ home
24
+ draw
25
+ end
26
+
27
+ def self.canvas
28
+ return @canvas if @canvas
29
+
30
+ root = TkRoot.new(:title => 'trtl', :minsize => [CANVAS_WIDTH, CANVAS_HEIGHT])
31
+ @canvas = TkCanvas.new(root, :bg => 'black', :highlightthickness => 0, :width => CANVAS_WIDTH, :height => CANVAS_HEIGHT)
32
+ @canvas.pack(:fill => 'both', :expand => 1)
33
+ @canvas
34
+ end
35
+
36
+ def pen_up
37
+ @drawing = false
38
+ end
39
+
40
+ def pen_down
41
+ @drawing = true
42
+ end
43
+
44
+ def is_drawing?
45
+ @drawing
46
+ end
47
+
48
+ def color(color)
49
+ @color = color.to_s
50
+ end
51
+
52
+ def width(width)
53
+ @width = width
54
+ end
55
+
56
+ def forward(amount = 20)
57
+ new_x = (@x + dx * amount)
58
+ new_y = (@y + dy * amount)
59
+ move(new_x, new_y)
60
+ end
61
+
62
+ def back(amount = 20)
63
+ new_x = (@x - dx * amount)
64
+ new_y = (@y - dy * amount)
65
+ move(new_x, new_y)
66
+ end
67
+
68
+ def move(new_x, new_y)
69
+ TkcLine.new(canvas, @x, @y, new_x, new_y, :width => @width, :fill => @color) if @drawing
70
+ @x, @y = new_x, new_y
71
+ draw
72
+ end
73
+
74
+ def right(offset)
75
+ @heading = (@heading + offset) % 360
76
+ draw
77
+ end
78
+
79
+ def left(offset)
80
+ @heading = (@heading - offset) % 360
81
+ draw
82
+ end
83
+
84
+ def dot(size = nil)
85
+ size ||= [@width + 4, @width * 2].max
86
+ TkcOval.new(canvas, @x - size / 2, @y - size / 2, @x + size / 2, @y + size / 2, :fill => @color, :outline => @color)
87
+ end
88
+
89
+ # TODO / TOFIX: This is horribly wrong with the fewer steps due to circumference varying ;-)
90
+ def circle(radius, extent = 360, steps = 360)
91
+ circumference = (Math::PI * 2 * radius) * (extent / 360.0)
92
+ steps.times do
93
+ left extent / steps.to_f
94
+ forward circumference / steps.to_f
95
+ end
96
+ end
97
+
98
+ def position
99
+ [@x, @y]
100
+ end
101
+
102
+ def home
103
+ @x = HOME_X
104
+ @y = HOME_Y
105
+ @heading = 0
106
+ draw
107
+ end
108
+
109
+ def sleep(time = 100000)
110
+ Tk.sleep(time)
111
+ end
112
+
113
+ def ensure_drawn
114
+ sleep 30
115
+ end
116
+
117
+ def wait
118
+ ensure_drawn and gets
119
+ end
120
+
121
+ alias :run :instance_eval
122
+
123
+ # Compatibility aliases (with turtle.py and KidsRuby primarily)
124
+ alias :fd :forward
125
+ alias :bk :back
126
+ alias :rt :right
127
+ alias :lt :left
128
+ alias :pu :pen_up
129
+ alias :pd :pen_down
130
+ alias :penup :pen_up
131
+ alias :pendown :pen_down
132
+ alias :up :pen_up
133
+ alias :down :pen_down
134
+ alias :turnright :right
135
+ alias :turnleft :left
136
+ alias :backward :back
137
+ alias :pencolor :color
138
+ alias :goto :move
139
+ alias :setpos :move
140
+ alias :setposition :move
141
+ alias :pos :position
142
+
143
+ private
144
+ def dx
145
+ Math.cos(@heading * DEG)
146
+ end
147
+
148
+ def dy
149
+ Math.sin(@heading * DEG)
150
+ end
151
+
152
+ def draw
153
+ canvas.delete(@turtle_line) if @turtle_line
154
+ @turtle_line = TkcLine.new(canvas, @x, @y, @x + dx * 5 , @y + dy * 5, :arrow => 'last', :width => 10, :fill => @color)
155
+ # Can probably just use ensure_drawn actually..
156
+ TkTimer.new(60, 1) { Tk.update }.start.wait if @interactive
157
+ true
158
+ end
159
+ end
160
+
161
+ module InteractiveTurtle
162
+ DEG = Math::PI / 180.0
163
+
164
+ Trtl.instance_methods(false).each do |meth|
165
+ define_method meth do |*args, &p|
166
+ (@turtle ||= ::Trtl.new(:interactive => true)).send(meth, *args, &p)
167
+ end
168
+ end
169
+ end
170
+
171
+ include InteractiveTurtle if %w{irb pry}.include?($0)
data/test/helper.rb ADDED
@@ -0,0 +1,3 @@
1
+ require 'minitest/spec'
2
+ require 'minitest/autorun'
3
+ require 'trtl'
data/test/test_trtl.rb ADDED
@@ -0,0 +1,64 @@
1
+ require_relative 'helper'
2
+
3
+ # Note: Only very simple high level tests here. Just stretching
4
+ # some of the public API. One day I may care to stub out Tk ;-)
5
+
6
+ describe Trtl do
7
+ before do
8
+ @trtl = Trtl.new
9
+ end
10
+
11
+ it "gets a default canvas when none is provided" do
12
+ @trtl.canvas.must_be_instance_of TkCanvas
13
+ end
14
+
15
+ it "has pen down by default" do
16
+ @trtl.is_drawing?.must_equal true
17
+ end
18
+
19
+ it "can have pen moved up" do
20
+ @trtl.pen_up
21
+ @trtl.is_drawing?.must_equal false
22
+ end
23
+
24
+ it "has default X and Y set" do
25
+ @trtl.x.must_equal Trtl::CANVAS_WIDTH / 2
26
+ @trtl.y.must_equal Trtl::CANVAS_HEIGHT / 2
27
+ end
28
+
29
+ it "can report its position" do
30
+ @trtl.position.must_equal [@trtl.x, @trtl.y]
31
+ end
32
+
33
+ it "can rotate and change heading" do
34
+ @trtl.left 20
35
+ @trtl.heading.must_equal 340
36
+ @trtl.right 40
37
+ @trtl.heading.must_equal 20
38
+ end
39
+
40
+ it "can move in straight lines" do
41
+ start_x, start_y = @trtl.position
42
+ @trtl.heading = 0
43
+ @trtl.forward 50
44
+ @trtl.x.must_equal start_x + 50
45
+ @trtl.heading = 90
46
+ @trtl.forward 50
47
+ @trtl.y.must_equal start_y + 50
48
+ @trtl.back 50
49
+ @trtl.y.must_equal start_y
50
+ end
51
+
52
+ it "can move at angles" do
53
+ start_x, start_y = @trtl.position
54
+ @trtl.heading = 45
55
+ @trtl.forward 100
56
+ @trtl.x.must_be_close_to start_x + 100 / Math.sqrt(2)
57
+ @trtl.y.must_be_close_to start_y + 100 / Math.sqrt(2)
58
+ end
59
+
60
+ it "can be moved absolutely" do
61
+ @trtl.move(310, 201)
62
+ @trtl.position.must_equal [310, 201]
63
+ end
64
+ end
data/trtl.gemspec ADDED
@@ -0,0 +1,20 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "trtl"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "trtl"
7
+ s.version = Trtl::VERSION
8
+ s.authors = ["Peter Cooper"]
9
+ s.email = ["git@peterc.org"]
10
+ s.homepage = "https://github.com/peterc/trtl"
11
+ s.summary = %q{Ruby turtle graphics (ideal for use from IRb)}
12
+ s.description = %q{A Logo / turtle.py style turtle graphics system for Ruby}
13
+
14
+ s.rubyforge_project = "trtl"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+ end
metadata ADDED
@@ -0,0 +1,62 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: trtl
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Peter Cooper
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-07-08 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: A Logo / turtle.py style turtle graphics system for Ruby
15
+ email:
16
+ - git@peterc.org
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - .gitignore
22
+ - Gemfile
23
+ - LICENSE.md
24
+ - README.md
25
+ - Rakefile
26
+ - examples/example1.rb
27
+ - examples/example2.rb
28
+ - examples/example3.rb
29
+ - examples/example4.rb
30
+ - examples/example5.rb
31
+ - examples/example6.rb
32
+ - lib/trtl.rb
33
+ - test/helper.rb
34
+ - test/test_trtl.rb
35
+ - trtl.gemspec
36
+ homepage: https://github.com/peterc/trtl
37
+ licenses: []
38
+ post_install_message:
39
+ rdoc_options: []
40
+ require_paths:
41
+ - lib
42
+ required_ruby_version: !ruby/object:Gem::Requirement
43
+ none: false
44
+ requirements:
45
+ - - ! '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ required_rubygems_version: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ requirements: []
55
+ rubyforge_project: trtl
56
+ rubygems_version: 1.8.24
57
+ signing_key:
58
+ specification_version: 3
59
+ summary: Ruby turtle graphics (ideal for use from IRb)
60
+ test_files:
61
+ - test/helper.rb
62
+ - test/test_trtl.rb