;;;; examples/06-sprite.lisp (defpackage #:ww.examples/6 (:use #:cl) (:export #:start)) (in-package #:ww.examples/6) (defclass sprite-example (ww::application) ()) (defclass dude (ww::sprite) ((walkingp :accessor walkingp :initform nil))) (defun set-key-if-not (sprite key ) "Sets the frame kyey for sprite if that key is not already set. Also sets the frameset's RUNNINGP to T if it is not already." (unless (eql key (ww::frameset-key sprite)) (setf (ww::runningp (ww::current-frameset sprite)) nil) (setf (ww::frameset-key sprite) key)) (unless (ww::runningp (ww::current-frameset sprite)) (setf (ww::runningp (ww::current-frameset sprite)) t))) (define-symbol-macro +walking-speed+ 5) (ww::defhandler move-by-face (ww::on-perframe (sprite) "When the sprite is walking, adjust its position." (when (walkingp sprite) (case (ww::frameset-key sprite) (:left (decf (ww::x sprite) +walking-speed+)) (:right (incf (ww::x sprite) +walking-speed+)) (:back (incf (ww::y sprite) +walking-speed+)) (:front (decf (ww::y sprite) +walking-speed+)))))) (ww::defhandler move-dude (ww::on-keydown (target scancode) "Set sprite to walking and set the frameset appropriate to its direction." (setf (walkingp target) t) (case scancode (:scancode-left (set-key-if-not target :left)) (:scancode-right (set-key-if-not target :right)) (:scancode-up (set-key-if-not target :back)) (:scancode-down (set-key-if-not target :front))))) (ww::defhandler stand (ww::on-keyup (target) "Stop the sprite from walking, and stop its current frameset from animating, setting its frame to the standing position." (setf (walkingp target) nil) (let ((current (ww::current-frameset target))) (setf (ww::runningp current) nil (ww::frameset-index current) 0)))) (defmethod ww::boot ((app sprite-example)) (let* ((front (ww::make-frameset '("dude/Front_Stand.png" ; this is the order in which frames will render "dude/Front_Left.png" "dude/Front_Stand.png" ; reusing assets does not add them twice "dude/Front_Right.png") :fps 3)) (back (ww::make-frameset '("dude/Back_Stand.png" "dude/Back_Left.png" "dude/Back_Stand.png" "dude/Back_Right.png") :fps 3)) (left (ww::make-frameset '("dude/Left_Stand.png" "dude/Left_Left.png" "dude/Left_Stand.png" "dude/Left_Right.png") :fps 3)) (right (ww::make-frameset '("dude/Right_Stand.png" "dude/Right_Left.png" "dude/Right_Stand.png" "dude/Right_Right.png") :fps 3)) (dude (make-instance 'dude :framesets (list :front front ; a sprite has many framesets :back back ; and are kept in a plist :left left :right right) :frameset-key :front))) ; initial frameset to use (setf (ww::runningp (ww::current-frameset dude)) nil) (ww::add-handler dude #'move-by-face ) (ww::add-handler dude #'move-dude) (ww::add-handler dude #'stand) (ww::refocus-on dude) (ww::add-unit app dude))) (defun start () (ww::start (make-instance 'sprite-example :fps 60 :width 800 :height 600 :title "Wheelwork Example: An Animated Sprite" :asset-root (merge-pathnames "examples/" (asdf:system-source-directory :wheelwork)))))