Hearter than I thought: LISP McCLIM DRAWING
*Prepare for valentine's day by drawing a heart with LISP McCLIM!
I'm not an artist. Prahou is the show artist.
Setting-stuff-up I'll link in an appendix. Let's just roll into some lisp.
1. Loading mcclim using quicklisp
I guess you got into lisp using M-x slime in emacs or $ sbcl in shell.
(ql:quickload :mcclim)
2. Using mcclim clim
(in-package :clim-user)
This package is nicely set up for being a user of clim.
3. Make an application frame at all
(define-application-frame heart () ((current-ink :initform +red+)) (:pane :application :display-function 'display-function))
=+red+=
has red ink inside of it.
3.1. Drawing a heart.
We can incrementally change clim stuff by
- define-application-frame heart'ing again. This doesn't actually "redo everything". It's smart. It only does the changes.
- Redefining 'display-function over and over again to try different things. It works better than it sounds.
If you're not playing along properly, remember that lisp, and particularly clim interactively and semi/automatically handle "errors" very, very well. Nothing bad happens, ever.
It's a bit random, but this is just what display-function(s) do:
3.1.1. Display-function
(defun display-function (frame pane) (draw-circle* pane 60 80 25))
- We're ready to run it
(find-application-frame 'heart)
congratulations. I guess we should use that blue ink. Here we begin just redefining display-function over and over. Sure, whatever better way you just thought of is better.
- A red heart.
(defun display-function (frame pane) (with-slots (current-ink) frame (with-drawing-options (pane :ink current-ink) (draw-circle* pane 60 80 25))))
and try it again
(find-application-frame 'heart)
Okay! Moving on up in this world.
- A second circle.
(defun display-function (frame pane) (with-slots (current-ink) frame (with-drawing-options (pane :ink current-ink) (draw-circle* pane 60 80 25) (draw-circle* pane 100 80 25))))
and try it again
(find-application-frame 'heart)
Er, let's move these circles differently for clarity. And let's make them not filled and things.
(defun display-function (frame pane) (with-slots (current-ink) frame (with-drawing-options (pane :ink current-ink) (with-translation (pane 0 0) (draw-circle* pane 60 80 25 :filled nil)) (with-translation (pane 40 0) (draw-circle* pane 60 80 23 :filled nil)))))
- Only specific arcs
(defun display-function (frame pane) (with-slots (current-ink) frame (with-drawing-options (pane :ink current-ink) (with-translation (pane 0 0) (draw-circle* pane 60 80 25 :filled nil :start-angle 0.0 :end-angle (+ pi (/ pi 6)))) (with-translation (pane 40 0) (draw-circle* pane 60 80 25 :filled nil :start-angle (* pi -1/6) :end-angle pi)))))
Well, hey, we got into some math stuff after all. Er, with a radius of 25, I guess
(list (* rad (cos (* pi 1/6))) (* rad (sin (* pi 1/6))))
<colgroup> <col class="org-right" /> <col class="org-right" /> </colgroup>
21.65063509461097d0 12.499999999999998d0 We can tell intuitively what directions we have to go these magnitudes in.
- Fiddling with that trig
(defun display-function (frame pane &aux (rad 25)) (with-slots (current-ink) frame (with-drawing-options (pane :ink current-ink) (with-translation (pane 60 80) (draw-circle* pane 0 0 rad :filled nil :start-angle 0.0 :end-angle (+ pi (/ pi 6))) (destructuring-bind (x y) (list (* rad (cos (* pi 1/6))) (* rad (sin (* pi 1/6)))) (let* ((dx (+ (* 2 rad) (- (* 2 (- rad x)) ))) (dy (* dx (- (/ x y))))) (draw-line* pane (- x) y (+ (- x) dx) (+ y (- dy)))) )) (with-translation (pane (+ 60 40) 80) (draw-circle* pane 0 0 rad :filled nil :start-angle (* pi -1/6) :end-angle pi) (destructuring-bind (x y) (list (* rad (cos (* pi 1/6))) (* rad (sin (* pi 1/6)))) (let* ((dx (+ (* 2 rad) (- (* 2 (- rad x)) ))) (dy (* dx (- (/ x y))))) (draw-line* pane (+ x) y (- x dx) (+ y (- dy)))))) )))
- Let's get rid of those straggly bits
(defun display-function (frame pane &aux (rad 25)) (with-slots (current-ink) frame (with-drawing-options (pane :ink current-ink) (with-translation (pane 60 80) (draw-circle* pane 0 0 rad :filled nil :start-angle (/ pi 6) :end-angle (+ pi (/ pi 6))) (destructuring-bind (x y) (list (* rad (cos (* pi 1/6))) (* rad (sin (* pi 1/6)))) (let* ((dx (+ (* 2 rad) (- (* 2 (- rad x)) ))) (dy (* dx (- (/ x y))))) (draw-line* pane (- x) y (+ (- x) dx) (+ y (- dy)))) )) (with-translation (pane (+ 60 40) 80) (draw-circle* pane 0 0 rad :filled nil :start-angle (* pi -1/6) :end-angle (- pi (/ pi 6))) (destructuring-bind (x y) (list (* rad (cos (* pi 1/6))) (* rad (sin (* pi 1/6)))) (let* ((dx (+ (* 2 rad) (- (* 2 (- rad x)) ))) (dy (* dx (- (/ x y))))) (draw-line* pane (+ x) y (- x dx) (+ y (- dy)))))) )))
4. Verdict
I'm giving myself a solid 6 out of 10 for valentines day.
Get lispmoo2
lispmoo2
Status | Prototype |
Author | screwtape |
Tags | common-lisp, emacs, lisp, mcclim, moo, new-kind-of-society, swank, Text based |
More posts
- LISP CLIM LOVE HEART DRAWING 2: [DOUG'S] RECKONING17 hours ago
- Lengthy detailed GIT and ASDF LISP story3 days ago
- Add Another System Definition to Arrokoth PR9 days ago
- NUD GOLF graphics choices and more on the live show in a mo'10 days ago
- NUD GOLF 2 more nconc11 days ago
- NUD GOLF12 days ago
- A sidescrolling game as a Pratt parser13 days ago
- LISPMOO2 INSTRUCTIONS (IMPORTANT)72 days ago
- repeatedly-eval-qt - good old-fashioned AI, in my lispmoo2?75 days ago
Comments
Log in with itch.io to leave a comment.
Errr I said I would include beginner material. Hey, I did a bunch of peertube videos a while ago:
Talk with me on the mastodon:
https://mastodon.sdf.org/@screwtape
(Hang out at the weekly show btw)
and then bug McCLIM's JackDaniel instead:
https://turtleware.eu/
Or @mdhughes :
https://mdhughes.tech/software/arrokoth/