aboutsummaryrefslogtreecommitdiffhomepage
path: root/examples/06-sprite.lisp
blob: 256ee950d27afe1f1e7085799b6ab74ce0d2e9a3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
;;;; 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)
   (walking-speed :accessor walking-speed :initform 5)))

(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::sprite-frameset-key sprite))
    (setf (ww::runningp (ww::current-frameset sprite)) nil)
    (setf (ww::sprite-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."
      (with-slots (walkingp walking-speed) sprite 
        (when walkingp
          (case (ww::sprite-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 (sprite scancode)
      "Set sprite to walking and set the frameset appropriate to its direction."
      (case scancode
        (:scancode-left
         (set-key-if-not sprite :left)
         (setf (walkingp sprite) t))
        (:scancode-right
         (set-key-if-not sprite :right)
         (setf (walkingp sprite) t))
        (:scancode-up
         (set-key-if-not sprite :back)
         (setf (walkingp sprite) t))
        (:scancode-down
         (set-key-if-not sprite :front)
         (setf (walkingp sprite) t)))))

(ww::defhandler speed-control
    (ww::on-keydown (sprite scancode)
      "A second keydown handler, for controlling walking speed. "
      (case scancode
        (:scancode-u (incf (walking-speed sprite)))
        (:scancode-d (decf (walking-speed sprite))))))

(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::add-handler dude #'speed-control)
    (ww::refocus-on dude)
    (ww::add-unit 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)))))