vydd / sketch

A Common Lisp framework for the creation of electronic art, visual design, game prototyping, game making, computer graphics, exploration of human-computer interaction, and more.
MIT License
1.4k stars 67 forks source link

Make defsketch generate a function for running sketches. #169

Open Kevinpgalligan opened 5 months ago

Kevinpgalligan commented 5 months ago

This provides better abstraction for sketches, as the CLOS details of their implementation don't leak as much.

I also considered not generating a new run function for each sketch, but something like (run-sketch 'blah) would lead to a worse development experience because the expected arguments wouldn't show up in Emacs.

Testing

I ran some of the example sketches, they still work. Also:

> (defsketch blah ()
     (circle 10 10 10))
> (run-blah :title "Testing!")
> (macroexpand-1
   '(defsketch blah ()
     (circle 10 10 10))
(PROGN
 (DEFCLASS BLAH (SKETCH) NIL)
 (DEFMETHOD PREPARE
            ((*SKETCH* BLAH)
             &KEY ((:TITLE TITLE) (SKETCH-TITLE *SKETCH*))
             ((:WIDTH WIDTH) (SKETCH-WIDTH *SKETCH*))
             ((:HEIGHT HEIGHT) (SKETCH-HEIGHT *SKETCH*))
             ((:FULLSCREEN FULLSCREEN) (SKETCH-FULLSCREEN *SKETCH*))
             ((:RESIZABLE RESIZABLE) (SKETCH-RESIZABLE *SKETCH*))
             ((:COPY-PIXELS COPY-PIXELS) (SKETCH-COPY-PIXELS *SKETCH*))
             ((:Y-AXIS Y-AXIS) (SKETCH-Y-AXIS *SKETCH*))
             ((:CLOSE-ON CLOSE-ON) (SKETCH-CLOSE-ON *SKETCH*))
             &ALLOW-OTHER-KEYS)
   (SETF (SKETCH-TITLE *SKETCH*) TITLE
         (SKETCH-WIDTH *SKETCH*) WIDTH
         (SKETCH-HEIGHT *SKETCH*) HEIGHT
         (SKETCH-FULLSCREEN *SKETCH*) FULLSCREEN
         (SKETCH-RESIZABLE *SKETCH*) RESIZABLE
         (SKETCH-COPY-PIXELS *SKETCH*) COPY-PIXELS
         (SKETCH-Y-AXIS *SKETCH*) Y-AXIS
         (SKETCH-CLOSE-ON *SKETCH*) CLOSE-ON))
 (DEFMETHOD DRAW ((*SKETCH* BLAH) &KEY X Y WIDTH HEIGHT MODE &ALLOW-OTHER-KEYS)
   (DECLARE (IGNORE X Y WIDTH HEIGHT MODE))
   (WITH-ACCESSORS ((TITLE SKETCH-TITLE) (WIDTH SKETCH-WIDTH)
                    (HEIGHT SKETCH-HEIGHT) (FULLSCREEN SKETCH-FULLSCREEN)
                    (RESIZABLE SKETCH-RESIZABLE)
                    (COPY-PIXELS SKETCH-COPY-PIXELS) (Y-AXIS SKETCH-Y-AXIS)
                    (CLOSE-ON SKETCH-CLOSE-ON))
       *SKETCH*
     (CIRCLE 10 10 10)))
 (DEFUN RUN-BLAH
        (
         &REST ARGS
         &KEY (TITLE "Sketch") (WIDTH *DEFAULT-WIDTH*)
         (HEIGHT *DEFAULT-HEIGHT*) (FULLSCREEN NIL) (RESIZABLE NIL)
         (COPY-PIXELS NIL) (Y-AXIS :DOWN) (CLOSE-ON :ESCAPE) &ALLOW-OTHER-KEYS)
   (DECLARE
    (IGNORE TITLE WIDTH HEIGHT FULLSCREEN RESIZABLE COPY-PIXELS Y-AXIS
     CLOSE-ON))
   (APPLY #'MAKE-INSTANCE 'BLAH ARGS))
 (MAKE-INSTANCES-OBSOLETE 'BLAH)
 (FIND-CLASS 'BLAH))
Kevinpgalligan commented 5 months ago

Ended up adding a run-sketch function as well! I think it's useful to have both: run-blah looks nicer and we get to see the function signature in Emacs, run-sketch is useful for me personally because in my mini-framework for Sketch I keep a list of all my sketches and it's nicer to be able to say (run-sketch sketch-var) than (funcall (alexandria:symbolicate 'run sketch-var)). Well, I just think it's nice to have both options.

Latest testing

SKETCH> (defsketch test ()
          (circle (/ width 2) (/ height 2) 20))
#<STANDARD-CLASS SKETCH::TEST>
SKETCH> (run-sketch 'test :width 200)
#<TEST {100821F773}>
SKETCH> (run-sketch 'missing)
; Evaluation aborted on #<SIMPLE-ERROR "Couldn't find a sketch called MISSING" {1008D31043}>.
SKETCH> (run-test :width 200)
#<TEST {1007A412B3}>