None of this is working very well; bit it is working a bit.
This commit is contained in:
parent
3551623374
commit
357d4c5853
7 changed files with 2518 additions and 2 deletions
222
index.html
Normal file
222
index.html
Normal file
|
|
@ -0,0 +1,222 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en-GB">
|
||||
<head>
|
||||
<title>Tittle: Turtles in Scittle</title>
|
||||
<script src="resources/js/scittle.js" type="application/javascript"></script>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Tittle: Turtles in <a href="https://github.com/babashka/scittle/tree/main">Scittle</a></h1>
|
||||
<svg id="playing-field"
|
||||
stype="width: 2000; height: 2000"
|
||||
version="1.1"
|
||||
width="594mm"
|
||||
height="420mm"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
|
||||
</svg>
|
||||
<script type="application/x-scittle">
|
||||
(def turtle (atom {:theta 0 :x 0 :y 0 :pen :up :ink "blue"}))
|
||||
|
||||
(defn log-turtle! []
|
||||
(.log js/console
|
||||
(apply str
|
||||
(map #(str % " " (@turtle %) "; ") (keys @turtle)))))
|
||||
|
||||
(log-turtle!)
|
||||
|
||||
(def playing-field (.getElementById js/document "playing-field"))
|
||||
|
||||
(defn- not-a-number! [n]
|
||||
(throw (js/Error. (str "not a number: " n))))
|
||||
|
||||
(defn number-or-error!
|
||||
"If `n` is a number, return it, else throw an exception."
|
||||
[n]
|
||||
(cond (.isNaN js/Number n) (not-a-number! n)
|
||||
(number? n) n
|
||||
:else (not-a-number! n)))
|
||||
|
||||
(defn sanitise-angle
|
||||
[angle]
|
||||
(let [v (cond (.isNaN js/Number angle) 0
|
||||
(< (abs angle) 0.5) 0
|
||||
(< (abs angle) 360) angle
|
||||
:else (rem 360 angle))]
|
||||
(.log js/console (str "(sanitise-angle " angle ") -> " v))
|
||||
v))
|
||||
|
||||
(defn turn!
|
||||
"Turn the turtle clockwise by this `angle`, expressed in degrees with
|
||||
respect to the X axis. If `angle` is not a number, throw an exception."
|
||||
[angle]
|
||||
(.info js/console (str "(turn! " angle ")"))
|
||||
(if (number? angle)
|
||||
(swap! turtle assoc :theta
|
||||
(sanitise-angle
|
||||
(rem 360 (+ (:theta @turtle) angle))))
|
||||
(not-a-number! angle))
|
||||
(.info js/console (str "(turn! " angle
|
||||
") :: :theta now " (:theta @turtle)))
|
||||
(log-turtle!))
|
||||
|
||||
(defn turn-to!
|
||||
"Turn the turtle to face `angle`, expressed in degrees with respect to the
|
||||
X axis. If `angle` is not a number, throw an exception."
|
||||
[angle]
|
||||
(.info js/console (str "(turn-to! " angle ")"))
|
||||
(if (number? angle)
|
||||
(swap! turtle assoc :theta (sanitise-angle angle))
|
||||
(not-a-number! angle))
|
||||
(.info js/console (str "(turn-to! " angle
|
||||
") :: :theta now " (:theta @turtle))))
|
||||
|
||||
(defn pen-down!
|
||||
"Put the turtle's pen down."
|
||||
[]
|
||||
(.info js/console "pen-down!")
|
||||
(swap! turtle assoc :pen :down))
|
||||
|
||||
(defn pen-up!
|
||||
"Lift the turtle's pen up"
|
||||
[]
|
||||
(.info js/console "pen-up!")
|
||||
(swap! turtle assoc :pen :up))
|
||||
|
||||
(defn pen-down?
|
||||
"Return `true` if the turtle's pen is down, else `false`."
|
||||
[]
|
||||
(let [v (= (@turtle :pen) :down)]
|
||||
(.info js/console "(pen-down?) =>" v)
|
||||
v))
|
||||
|
||||
(defn pen-up?
|
||||
"Return `true` if the turtle's pen is not down, else `false`."
|
||||
[]
|
||||
(not (pen-down?)))
|
||||
|
||||
(defn move-to!
|
||||
"Move the turtle absolutely to the coordinates `x`, `y`."
|
||||
[x y]
|
||||
(.info js/console (str "(move-to! " x " " y ")"))
|
||||
(when (map number-or-error! [x y])
|
||||
(let [x' (:x @turtle)
|
||||
y' (:y @turtle)]
|
||||
(when (pen-down?)
|
||||
(let [elt (.createElementNS js/document "http://www.w3.org/2000/svg" "line")
|
||||
id (gensym "line")]
|
||||
(.setAttribute elt "id" id)
|
||||
(.setAttribute elt "x1" x')
|
||||
(.setAttribute elt "y1" y')
|
||||
(.setAttribute elt "x2" x)
|
||||
(.setAttribute elt "y2" y)
|
||||
(.setAttribute elt "stroke" (or (:ink @turtle) "blue"))
|
||||
(.appendChild playing-field elt)))
|
||||
(swap! turtle assoc :x x :y y))))
|
||||
|
||||
(def ^:const pi 3.141592653589793)
|
||||
|
||||
(defn degrees->radians
|
||||
"Return the equivalent, in radians, of this `angle` espressed in degrees"
|
||||
[angle]
|
||||
(let [v (when (number-or-error! angle)
|
||||
(* angle (/ pi 180)))]
|
||||
(.log js/console (str "(degrees->radians " angle ") => " v))
|
||||
v))
|
||||
|
||||
(defn radians->degrees
|
||||
"Return the equivalent, in degrees, of this `angle` espressed in radians"
|
||||
[angle]
|
||||
(let [v (when (number-or-error! angle)
|
||||
(/ (* angle 180) pi))]
|
||||
(.log js/console (str "(radians->degrees " angle ") => " v))
|
||||
v))
|
||||
|
||||
(defn sin
|
||||
"Return the sine of this `angle`, considered to be expressed in degrees."
|
||||
[angle]
|
||||
(let [v (.sin js/Math (degrees->radians angle))]
|
||||
(.log js/console (str "(sin " angle ") => " v))
|
||||
v))
|
||||
|
||||
(defn cos
|
||||
"Return the cosine of this `angle`, considered to be expressed in degrees."
|
||||
[angle]
|
||||
(let [v (.cos js/Math (degrees->radians angle))]
|
||||
(.log js/console (str "(cos " angle ") => " v))
|
||||
v))
|
||||
|
||||
(defn move!
|
||||
"Move the turtle forward on its current heading by `distance` units."
|
||||
[distance]
|
||||
(.info js/console (str "(move! " distance ")"))
|
||||
(move-to! (+ (:x @turtle) (* distance (sin (:theta @turtle))))
|
||||
(+ (:y @turtle) (* distance (cos (:theta @turtle))))))
|
||||
|
||||
(defn set-ink!
|
||||
"Set the ink with which the turtle draws to this `colour`, which
|
||||
should be a string representation of a colour known to CSS."
|
||||
[colour]
|
||||
(.log js/console (str "(set-ink! " colour ")"))
|
||||
(when (string? colour)
|
||||
(swap! turtle assoc :ink colour)))
|
||||
|
||||
(defn draw-tree!
|
||||
[length left-branch right-branch curvature branch-fraction trunk-fraction depth]
|
||||
(log-turtle!)
|
||||
(when (> depth 0)
|
||||
(pen-down!)
|
||||
(set-ink! (if (<= depth 2) "green" "brown"))
|
||||
(move! length)
|
||||
(turn! curvature)
|
||||
(draw-tree! (* length trunk-fraction)
|
||||
(* left-branch branch-fraction)
|
||||
(* right-branch branch-fraction)
|
||||
curvature
|
||||
branch-fraction
|
||||
trunk-fraction
|
||||
(dec depth))
|
||||
(turn! (- 0 (+ curvature left-branch)))
|
||||
(draw-tree! (* length trunk-fraction)
|
||||
left-branch
|
||||
right-branch
|
||||
curvature
|
||||
branch-fraction
|
||||
trunk-fraction
|
||||
(dec depth))
|
||||
(turn! (+ left-branch right-branch))
|
||||
(draw-tree! (* length trunk-fraction)
|
||||
left-branch
|
||||
right-branch
|
||||
curvature
|
||||
branch-fraction
|
||||
trunk-fraction
|
||||
(dec depth))
|
||||
(turn! (- 0 right-branch curvature))
|
||||
(pen-up!)
|
||||
(move! (- 0 length))))
|
||||
|
||||
(defn draw-polygon!
|
||||
[sides side-length]
|
||||
(when {<= 3 sides 360}
|
||||
(let [angle (/ 360 sides)]
|
||||
(pen-down!)
|
||||
(loop [side 0]
|
||||
(turn! angle)
|
||||
(move! side-length)
|
||||
(when (< side sides)
|
||||
(recur (inc side))))
|
||||
(pen-up!))))
|
||||
|
||||
(log-turtle!)
|
||||
(pen-up!)
|
||||
(log-turtle!)
|
||||
(move-to! 500 500)
|
||||
(log-turtle!)
|
||||
(turn-to! 180)
|
||||
;; (draw-tree! 100 70 60 5 0.25 0.7 3)
|
||||
;; (map #(draw-polygon! % 100) (range 3 20))
|
||||
(draw-polygon! 3 100)
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Loading…
Add table
Add a link
Reference in a new issue