aboutsummaryrefslogtreecommitdiffhomepage
path: root/examples/06-sprite.lisp
blob: 2addfd7fbb851a791d9962fb669277aed28ffb43 (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
130
;;;; 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::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."
      (with-slots (walkingp walking-speed) sprite 
        (when walkingp
          (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 (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 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)))))