Turtle graphics

Hi. Sorry, I am a complete beginner on programming and racket, but keen to learn and help my son learn at the same time. I am interested in combining turtle graphics with 2htdp/image and 2htdp/universe. Any clues how to achieve this? My motivation is to be able to relate the movement of the images in htdp to how we move our body (Seymour Papert's theory). Hopefully someone can give me some clues. Thank you.

3 Likes

Hi @Lambda17

Sounds like a fun project.

There are two ways to go:

  1. Implement turtles yourself using 2htdp.
  2. Use an existing turtle library.

Route 2 doesn't use 2hdtp, but that might not be that important.

The program below opens a new window with a turtle.
The commands can be either in the program or be entered in the repl.

#lang racket
(require graphics/turtles)

(turtles)

(draw 100)
(turn 90)
(draw 100)
(turn 90)

image

2 Likes

I forgot the link to the documentation:

https://docs.racket-lang.org/turtles/Traditional_Turtles.html

Consider working thru

Bloch’s Picturing Programs
https://www.amazon.com/Picturing-Programs-Introduction-Computer-Programming/dp/1848900155

(I vaguely recall that Stephen took back the copyright and put the book on the web. I couldn’t find it this morning. So this is not an ad for Amazon just a link so you can visualize it.)

1 Like

It's here:

http://www.picturingprograms.com/

2 Likes

Thank you soegaard
I tried graphics/turtle, but I couldn't work out how to build a game in it like you can do using 2htdp (currently using Realm of Racket). The problem I find in 2htdp is that to make an image move you tend to use its coordinates, which is not as intuitive as using turtle graphics commands. The example you gave for instance, in 2htdp would be achieved by enter the coordinates of start and end points of two lines, not simple for a Y3 kid, let alone moving an image along a curved line.
I was hoping that someone would have already implemented a solution to use turtle graphics moves in 2htdp, although implementing it myself may not be as complex? Thanks for your advice.

Thanks EmEf and soegard for the link to this book. It looks like a really good source to learn racket. Much appreciated.

I don't know whether this is useful or not - but I amused myself implementing a little turtle in the "Advanced Student Language" using 2htdp.

I am sorry about all the bangs!

The names up, down, left, right were all taken for mouse and key events.

;; The turtle has a direction, stored in degrees.
(define direction 0)                
;; The turtle has a position.
(define position  (make-posn 200 200))
;; The trail made by the turtle.
(define trail (list position))

; convert from degrees to radian
(define (radian degrees)
  (* pi (/ degrees 180)))

; change direction turning right, return the new direction
(define (right! degrees)
  (begin
    (set! direction (+ direction degrees))
    direction))

; change direction turning left, return the new direction
(define (left! degrees)
  (right! (- degrees)))

; distance along x-axis, if we want to move `amount` in the current direction
(define (dx amount)
  (* amount (cos (radian direction))))

; distance along x-axis, if we want to move `amount` in the current direction
(define (dy amount)
  (* amount (sin (radian direction))))

; compute the position the turtle ends in, if it starts in old-position and moves `amount` forward
(define (forward old-position amount)
  (make-posn (+ (posn-x old-position) (dx amount))
             (+ (posn-y old-position) (dy amount))))

(define (back old-position amount)
  (forward old-position (- amount)))

; the turtle moves to `new-position` and leaves a trail
(define (move-to! new-position)
  (begin
    (set! trail (cons new-position trail))
    (set! position new-position)))

; move the turtle forward, update the position and trail  
(define (forward! amount)
  (move-to! (forward position amount)))

; move the turtle backward, update the position and trail  
(define (back! amount)
  (forward! (- amount)))


; draw a line segment from position p1 to position p2 ontop of the image
(define (segment image p1 p2)
  (add-line image (posn-x p1) (posn-y p1) (posn-x p2) (posn-y p2) "black"))

; draw the trail on a 400x400 white rectangle
(define (draw-trail)
  (draw-trail-on-image trail (rectangle 400 400 "solid" "white")))

; draw the trail on top of the image
(define (draw-trail-on-image trail image)
  (cond
    [(empty? trail)
     image]
    [(and (cons? trail) (not (empty? (rest trail))))
     (draw-trail-on-image (rest trail)
                          (segment image (first trail) (second trail)))]
    [else
     image]))

; draw a square with side length `side`
(define (square! side)
  (begin
    (forward! side)
    (left! 90)
    (forward! side)
    (left! 90)
    (forward! side)
    (left! 90)
    (forward! side)
    (left! 90)))

; draw `amount` squares, rotate `angle` between each square
(define (rotating-squares angle amount)
  (when (> amount 0)
    (begin
      (square! 100)
      (left! angle )
      (rotating-squares angle (- amount 1)))))


(rotating-squares 10 (/ 360 10))
(draw-trail)

Here's another take on turtle graphics in racket, this one with an animated turtle drawing on some ideas from the excellent PLAI course:

Thanks soegaard.
It is actually very useful. I think I can adapt it to my needs. I'll share the outcome. The code works for me, only thing was missing was the definition of posn-x and posn-y, which was easy enough to add back.

Thanks for sharing danprager. I had an initial look at the code. It is a bit too advance for me at the moment. But it is useful to have as reference. A basic thing for instance that wouldn't know how to achieve with your implementation is to create the drawing in stand alone window. My medium term goal is to be able to create games (micro-world) like the example Seymour gives in his video: VPRI-0857 Seymour Papert on Logo: Teaching - YouTube (minute 18), and also animations for exploring and understanding maths concepts, like the multiplication circle (which I managed to implement, but not in a simple or elegant way: e.g. not using turtle graphic commands, which may be a better way in terms of making it the code less abstract, and more approachable to a kid):

#lang racket
(require 2htdp/image 2htdp/universe)

;; *********** My Constants ************
(define MULTIPLICATOR-INCREMENT 0.1)
(define RADIO 420)
(define NUMBER-OF-LINES 900)
(define DELTA-NUMBER-OF-LINES 10)
;;**************************************

(define (start-game multiplicator number-of-lines)
(big-bang (cons multiplicator number-of-lines)
[on-key deal-with-key]
[to-draw escena]))

(define (deal-with-key world key)
(cond [(key=? key "up") (increase-multiplicator world)]
[(key=? key "down") (decrease-multiplicator world)]
[(key=? key "right") (increase-number-of-lines world)]
[(key=? key "left") (decrease-number-of-lines world)]
[else world]))

(define (increase-multiplicator world)
(cons (+ (car world) MULTIPLICATOR-INCREMENT)
(cdr world)))
(define (decrease-multiplicator world)
(cons (- (car world) MULTIPLICATOR-INCREMENT)
(cdr world)))
(define (increase-number-of-lines world)
(cons (car world)
(+ (cdr world) DELTA-NUMBER-OF-LINES)))
(define (decrease-number-of-lines world)
(cons (car world)
(if (<= (cdr world) 10)
10
(- (cdr world) DELTA-NUMBER-OF-LINES))))

(define (background-circle radio multiplicator)
(place-image (circle radio "outline" "pink")
radio radio
(place-image (text (number->string multiplicator) 24 "olive")
200 24
(square (* 2 radio) "solid" "black"))))

(define (escena world)
(define (iter counter red green blue)
(add-line (if (= counter (cdr world))
(background-circle RADIO (car world))
(iter (add1 counter) red green blue))
(car (p1 (cdr world) counter)) (cdr (p1 (cdr world) counter))
(car (p2 (car world) (cdr world) counter)) (cdr (p2 (car world) (cdr world) counter))
"pink"))
(iter 1 10 10 10))

;; *********** Geometry ************
(define (p1 number-of-lines counter)
(cons (- RADIO (* RADIO (cos (* counter (/ (* 2 pi) number-of-lines)))))
(- RADIO (* RADIO (sin (* counter (/ (* 2 pi) number-of-lines)))))))

(define (p2 multiplicator number-of-lines counter)
(cons (- RADIO (* RADIO (cos (* multiplicator counter (/ (* 2 pi) number-of-lines)))))
(- RADIO (* RADIO (sin (* multiplicator counter (/ (* 2 pi) number-of-lines)))))))

(start-game 2 10)

Here's a set of exercises on turtle graphics using those libraries:
https://homes.luddy.indiana.edu/samth/full-211/ps7.html#(part._.Turtle_graphics)
https://homes.luddy.indiana.edu/samth/full-211/lab10.html
https://homes.luddy.indiana.edu/samth/full-211/ps11.html#(part._.Generating_fractals)