(ns turtle (:import (javax.swing JFrame JLabel) (java.awt.image BufferedImage) (java.awt Dimension Color) (java.io File) (javax.imageio ImageIO))) (def deg (/ (Math/PI) 180)) (defn turtle [width height] (let [image (BufferedImage. width height BufferedImage/TYPE_INT_RGB)] (ref {:width width :height height :image image :drawing true :point [0 0] :angle 0 :color Color/white}))) (defn pen-up? "Is the pen up?" [turtle] (not (:drawing @turtle))) (defn pen-up "Disable Drawing." [turtle] (dosync (alter turtle merge {:drawing false}))) (defn pen-down "Enable Drawing." [turtle] (dosync (alter turtle merge {:drawing true}))) (defn pen-color "Set pen color" [turtle color] (dosync (alter turtle merge {:color color}))) (defn right "Turn right through the angle ." [turtle degrees] (let [angle (:angle @turtle) heading (mod (+ angle degrees) 360)] (dosync (alter turtle merge {:angle heading})))) (defn left "Turn left through the angle ." [turtle degrees] (right turtle (- degrees))) (defn- draw-line [turtle p1 p2] (doto (.getGraphics (:image @turtle)) (.translate (/ (:width @turtle) 2) (/ (:width @turtle) 2)) (.scale 1.0 -1.0) (.setColor (:color @turtle)) (.drawLine (first p1) (second p1) (first p2) (second p2)))) (defn forward "Move forward by turtle steps." [turtle steps] (let [p1 (:point @turtle) angle (:angle @turtle) p2 [(+ (first p1) (* (Math/sin (* angle deg)) steps)) (+ (second p1) (* (Math/cos (* angle deg)) steps))] ] (if (true? (:drawing @turtle)) (draw-line turtle p1 p2)) (dosync (alter turtle merge {:point p2})))) (defn back "Move backward by turtle steps." [turtle steps] (forward turtle (- steps))) (defn go "Move to the given point." [turtle x y] (let [p1 (:point @turtle) p2 [x y]] (if (true? (:drawing @turtle)) (draw-line turtle p1 p2)) (dosync (alter turtle merge {:point p2})))) (defn toward "Turn to face the given point." [turtle x y] (let [p (:point @turtle) polar (Math/atan2 (- (first p) x) (- (second p) y)) angle (mod (/ polar deg) 360)] (dosync (alter turtle merge {:angle angle})))) (defn distance "Return the distance between the turtle and the given point." [turtle x y] (let [p (:point @turtle)] (Math/sqrt (+ (Math/pow (- (first p) x) 2) (Math/pow (- (second p) y) 2))))) (defn show [turtle] (doto (JFrame.) (.add (proxy [JLabel] [] (paint [g] (.drawImage g (:image @turtle) 0 0 this)))) (.setSize (Dimension. (:width @turtle) (:height @turtle))) (.show))) (defn write [turtle fname] (ImageIO/write (:image @turtle) "png" (File. fname)))