(defpackage #:clog-user (:use #:cl #:clog) (:export start-tutorial)) (in-package :clog-user) (defun on-click (obj) (setf (text obj) "DEAD") (setf (connection-data-item obj "done") t) (set-on-click obj nil)) (defun on-new-window (body) (handler-case ; Disconnects from the browser can be handled gracefully using the condition system. (progn (setf (title (html-document body)) "Tutorial 7") ;; Show a "splash" screen (setf (hiddenp (prog1 (create-section body :h2 :content "KILL Darth's Tie Fighter - Click on it!") (sleep 2))) t) ;; Setup main game (let* ((mover (create-div body :content "(-o-)")) bounds-x bounds-y mover-x mover-y) (flet ((set-bounds () (setf bounds-x (parse-integer (width (window body)) :junk-allowed t)) (setf bounds-y (parse-integer (height (window body)) :junk-allowed t)))) (set-bounds) (setf mover-x (random bounds-x)) (setf mover-y (random bounds-y)) ;; Capture browser size changes to adjust playing field (set-on-resize (window body) (lambda (obj) (declare (ignore obj)) (set-bounds)))) ;; Setup our "mover". Darth (setf (positioning mover) :fixed) (set-on-click mover #'on-click) ;; Get Darth moving! (bordeaux-threads:make-thread ; In addtion to the main task (the on-new-window) (lambda () ; and the task created for each event like clicks (loop ; threads can be created as needed and used with (unless (validp body) ; CLOG. (return)) (when (connection-data-item body "done") (return)) (sleep .5) (setf (text mover) ")-o-(") (sleep .2) (setf (text mover) "(-o-)")) (setf (inner-html mover) "