On Wed, 16 May 2001, meredith wrote: > I've been trying to persuade my teacher friends to use Ruby to teach > their kids. The bottom line for most of them is that they need to have > turtle graphics. If I knew TK I might attempt it myself, but I don't and > so the learning curve would be way too big. Anyone out there want to > take it on? > Getting it into the schools is a really good way to help a language > catch on. Three parts: * a sample program using the turtle * the turtle package (yellow window) commands typed in the red box may be "forward", "back", "right", "left", or any ruby expression. * the listener package (type commands in the red box) I originally wrote this last part for another project; it has a command history. ----------------8<----------------cut-here----------------8<---------------- # this draws a recursive tree. # unfortunately you'll have to put the whole def on one line to feed it to # the listener, unless you wrap it in $listener.instance_eval { } just # before the mainloop. def tree(d,n) return if n<1 forward d left 45 tree d*3/4,n-1 right 90 tree d*3/4,n-1 left 45 back d end back 50 tree 50,6 --------8<----------------cut-here----------------8<-------- TkTurtle.rb # Ruby/Tk Turtle Graphics # Copyright (c) 2001 by Mathieu Bouchard # under the same license as Ruby itself require 'tk' require 'TkRubyListener' $root = TkRoot.new { title "Tortue" } $canvas = TkCanvas.new($root) { background "#888800" # dark yellow width 512 height 384 }.pack $listener = TkRubyListener.new($root,60,8) $listener.frame.pack("fill"=>"both") module Turtle def turtle_init @pos_x = $canvas.width/2 @pos_y = $canvas.height/2 @angle = 0 @turtle_lines ||= (0...3).map {|i| l = TkcLine.new($canvas,0,0,0,0) l.fill "white" l } turtle_draw end def forward(distance) nx = @pos_x + distance * Math.sin(@angle) ny = @pos_y - distance * Math.cos(@angle) TkcLine.new($canvas,@pos_x,@pos_y,nx,ny).fill "black" @pos_x = nx @pos_y = ny turtle_draw return distance end def right(angle) @angle += angle * Math::PI / 180 turtle_draw return angle end def back(distance); forward -distance; end def left(angle); right(-angle); angle; end def turtle_draw @turtle_points = [[8,0],[-8,0],[0,20]].map {|x,y| [ @pos_x + y * Math.sin(@angle) + x * Math.cos(@angle), @pos_y - y * Math.cos(@angle) + x * Math.sin(@angle) ]} (0...3).each {|i| @turtle_lines[i].coords(*( @turtle_points[i] + @turtle_points[(i+1)%3] )) } end end $listener.extend Turtle $listener.turtle_init # $listener.instance_eval { } Tk.mainloop ----8<----------------cut-here----------------8<---- TkRubyListener.rb # Interactive Ruby/Tk # Copyright (c) 2000,2001 by Mathieu Bouchard # under the same license as Ruby itself require "tk" class TkRubyListener attr_reader :entry attr_reader :text attr_reader :hist attr_reader :frame def initialize(parent,w=80,h=10) @frame = TkFrame.new(parent) @hist = [] @histn = 0 _line = @line = TkVariable.new @text = TkText.new(frame) { background "#006090" foreground "#ffffff" highlightbackground "#000000" highlightcolor "#ffffff" width w height h }.pack("fill"=>"both") @entry = TkEntry.new(frame) { background "#900060" foreground "#ffffff" highlightbackground "#000000" highlightcolor "#ffffff" width w textvariable _line }.pack("fill"=>"x") @entry.bind("Return") { self.eval_entry } @entry.bind("Up") { self.history_up } @entry.bind("Down") { self.history_down } end def line=(value) # bug? # @line.value = value @entry.delete("0","end") @entry.insert("0",value) end def line() @line.value end def hist_peek(i) hist[i] end def histn=(v) @histn = v > hist.length ? hist.length : v < 0 ? 0 : v end attr_reader :histn def add_history(v) @hist.push v self.histn = hist.length end # there is a bug that causes spurious '(undef)' to appear (and possibly # not even executing the code) but i don't know what it is # this was in perl, may not occur in ruby. def eval_entry @text.delete("1.0", "end") @text.insert("end","\n<< #{self.line}\n") _result_,_err_ = nil begin _result_ = eval line rescue Exception => _err_ text.insert("end","!> #{_err_}\n") end if not _err_ @text.insert("end",">> #{_result_.inspect}\n") end add_history(line) self.line = "" text.yview("moveto",1) end def history_up self.histn -= 1 self.line = hist_peek(histn) entry.cursor = 'end' end def history_down self.histn += 1 self.line = hist_peek(histn) entry.cursor = 'end' end end ----------------8<----------------cut-here----------------8<---------------- matju