aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorColin Okay <colin@cicadas.surf>2022-07-01 10:53:47 -0500
committerColin Okay <colin@cicadas.surf>2022-07-01 10:53:47 -0500
commit59f5cb6c28399c84221b728daf4bd8461ab1e230 (patch)
treeee445c5158d680d3ae4f0892997ca9f0b2d1d86a
parent252d952205b4ab4c0c9a5209b18a42666db9fb6a (diff)
[add] sprite class and example
-rw-r--r--examples/05-frameset-animation.lisp5
-rw-r--r--examples/06-sprite.lisp96
-rw-r--r--src/interactive/sprite.lisp42
3 files changed, 141 insertions, 2 deletions
diff --git a/examples/05-frameset-animation.lisp b/examples/05-frameset-animation.lisp
index 4686ecc..12207f3 100644
--- a/examples/05-frameset-animation.lisp
+++ b/examples/05-frameset-animation.lisp
@@ -1,7 +1,8 @@
;;;; examples/05-frameset-animation.lisp
(defpackage #:ww.examples/5
- (:use #:cl))
+ (:use #:cl)
+ (:export #:start))
(in-package #:ww.examples/5)
@@ -35,7 +36,7 @@
:fps 30
:width 800
:height 600
- :title "Wheelwork Example: An Animated Sprite"
+ :title "Wheelwork Example: A framebased animation"
:asset-root (merge-pathnames
"examples/"
(asdf:system-source-directory :wheelwork)))))
diff --git a/examples/06-sprite.lisp b/examples/06-sprite.lisp
new file mode 100644
index 0000000..2d737e5
--- /dev/null
+++ b/examples/06-sprite.lisp
@@ -0,0 +1,96 @@
+;;;; examples/06-sprite.lisp
+
+(defpackage #:ww.examples/6
+ (:use #:cl)
+ (:export #:start))
+
+(in-package #:ww.examples/6)
+
+(defclass sprite-example (ww::application) ())
+
+(defun set-key-if-not (sprite key )
+ (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+ 10)
+
+(ww::defhandler move-dude
+ (ww::on-keydown (target scancode)
+ (case scancode
+ (:scancode-left
+ (set-key-if-not target :left)
+ (decf (ww::x target) +walking-speed+))
+ (:scancode-right
+ (set-key-if-not target :right)
+ (incf (ww::x target) +walking-speed+))
+ (:scancode-up
+ (set-key-if-not target :back)
+ (incf (ww::y target) +walking-speed+))
+ (:scancode-down
+ (set-key-if-not target :front)
+ (decf (ww::y target) +walking-speed+)))))
+
+(ww::defhandler stand
+ (ww::on-keyup (target)
+ (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"
+ "dude/Front_Left.png"
+ "dude/Front_Stand.png"
+ "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
+ 'ww::sprite
+ :framesets (list :front front
+ :back back
+ :left left
+ :right right)
+ :frameset-key :front)))
+
+ (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 30
+ :width 800
+ :height 600
+ :title "Wheelwork Example: An Animated Sprite"
+ :asset-root (merge-pathnames
+ "examples/"
+ (asdf:system-source-directory :wheelwork)))))
diff --git a/src/interactive/sprite.lisp b/src/interactive/sprite.lisp
new file mode 100644
index 0000000..81f5715
--- /dev/null
+++ b/src/interactive/sprite.lisp
@@ -0,0 +1,42 @@
+;;;; sprite.lisp
+
+(in-package #:wheelwork)
+
+(defclass/std sprite (unit interactive)
+ ((framesets :with :doc "A PLIST whose values are framesets.")
+ (frameset-key)))
+
+(defun current-frameset (sprite)
+ (getf (sprite-framesets sprite)
+ (frameset-key sprite)))
+
+(defmethod initialize-instance :after ((sprite sprite) &key)
+ (with-slots (framesets frameset-key) sprite
+ (loop for (name fs . more) on framesets by #'cddr
+ do (setf (unit-container fs) sprite))
+ (unless frameset-key
+ (setf frameset-key (first framesets)))))
+
+(defmethod cleanup ((sprite sprite))
+ (mapc #'cleanup (sprite-framesets sprite)))
+
+(defmethod render ((sprite sprite))
+ (when-let (fs (current-frameset sprite))
+ (render fs)))
+
+(macrolet
+ ((def-sprite-accessors (&rest accessor-names)
+ (let ((defs
+ (loop for accessor-name in accessor-names
+ collect
+ `(defmethod ,accessor-name ((sprite sprite))
+ (,accessor-name (current-frameset sprite)))
+
+ collect
+ `(defmethod (setf ,accessor-name) (newval (sprite sprite))
+ (loop for (key fs . more) on (sprite-framesets sprite) by #'cddr
+ do (setf (,accessor-name fs) newval))
+ newval))))
+ `(progn ,@defs))))
+
+ (def-sprite-accessors x y scale-x scale-y width height rotation))