Ported to OpenGL
[uxul-world.git] / animation.lisp
1 ;;; Copyright 2009-2011 Christoph Senjak
2
3 ;; Basic definitions for animations.
4
5 (in-package :uxul-world)
6
7 (defparameter *zoom-ash* -1)
8 (defmacro zoom-trans (x) `(ash ,x *zoom-ash*))
9
10 (defparameter *graphics-table* nil)
11
12 ;; the functions may assume that the contents of a graphics-file -
13 ;; once read - will not change at any time - so it wont reload
14 ;; graphics with an equivalent path any time you load an image.
15
16 (defclass animation (xy-coordinates)
17   (
18 ;;   (images :initarg :images
19 ;;                   :initform (make-array (list 0) :element-type 'sdl:surface)
20 ;;                   :accessor images
21 ;; ;                 :type (simple-array 'sdl:surface (*))
22 ;;                   :documentation "Array with the images")
23    (full-widths :initarg :full-widths
24                 :initform (make-array (list 0))
25                 :accessor full-widths
26                 :documentation "Widths of images-1x")
27    (full-heights :initarg :full-heights
28                 :initform (make-array (list 0))
29                 :accessor full-heights
30                 :documentation "Heights of images-1x")
31    (images-2x :initarg :images-2x
32               :initform (make-array (list 0))
33               :accessor images-2x
34               :documentation "Array of double-sized images")
35    (images-1x :initarg :images-1x
36               :initform (make-array (list 0))
37               :accessor images-1x
38               :documentation "Array of normal-sized images")
39    (images-.5x :initarg :images-.5x
40                :initform (make-array (list 0))
41                :accessor images-.5x
42                :documentation "Array of half-sized images")
43    (images-.25x :initarg :images-.25x
44                 :initform (make-array (list 0))
45                 :accessor images-.25x
46                 :documentation "Array of quarter-sized images")       
47    (sprite-image-number :initform 0
48                         :initarg :sprite-image-number
49                         :accessor sprite-image-number
50 ;                       :type xy-struct
51                         :documentation "The Element-Number of the
52                        current image. This slot should not be set
53                        directly.")
54    (sprite-delay :initarg :sprite-delay
55                  :initform 0
56                  :accessor sprite-delay
57 ;                :type integer
58                  :documentation "How much frames to overjump on the
59 whole until changing to the next image of the animation.")
60    (already-jumped :initform 0
61                    :initarg :already-jumped
62                    :accessor already-jumped
63 ;                  :type integer
64                    :documentation "How much frames have been already
65    drawn until the last jump? If this equals to <sprite-delay>, the
66    next image is selected. Dont set this variable yourself." )
67    (visible :initarg :visible
68             :initform T
69             :accessor visible
70 ;           :type boolean
71             :documentation "Should this Animation be visible (i.e. be
72             drawn when the draw-method is called)? Anyway, the
73             draw-method will - even if set to false - \"animate\" the
74             animation, i.e. rotate the image currently drawn, if not
75             paused. It simply wont draw the graphics to the
76             screen.")
77    (reference-to-original :initarg :reference-to-original
78                           :accessor reference-to-original
79                           :initform nil
80                           :documentation "DO NOT SET THIS MANUALLY! DO
81 NOT USE IT! This may not stay in later versions of this Program. It
82 will be used to minimize the number of file-accesses for loading
83 animations. For any animation created from a file by the api from
84 below, this will refer to an animation in the *graphics-table*." )))
85
86 (defmethod images ((obj animation))
87   (cond
88     ((= *zoom-ash* 0)
89      (images-2x obj))
90     ((= *zoom-ash* -1)
91      (images-1x obj))
92     ((= *zoom-ash* -2)
93      (images-.5x obj))
94     ((= *zoom-ash* -3)
95      (images-.25x obj))))
96
97
98 (defmethod draw ((obj animation))
99   (when (not (<= (sprite-delay obj) 0)) ;<=, because -a means "paused,
100                                         ;but a is the delay when
101                                         ;playing again", and 0 means
102                                         ;"no playing"
103     (incf (already-jumped obj))
104     (when (= (sprite-delay obj) (already-jumped obj))
105       (setf (already-jumped obj) 0)
106       (setf (sprite-image-number obj) (mod (+ 1 (sprite-image-number obj)) (length (images obj))))))
107   (when (visible obj)
108     (make-quad (elt (images obj) (sprite-image-number obj))
109                (zoom-trans (round (x obj)))
110                (zoom-trans (round (y obj)))
111                
112                (ash (elt (full-widths obj)
113                                 (sprite-image-number obj)) (+ 2 *zoom-ash*))
114                (ash (elt (full-heights obj)
115                                 (sprite-image-number obj)) (+ 2 *zoom-ash*))
116
117 )))
118
119 ;additional methods to make life easier
120 (defmethod pause ((obj animation))
121   "toggle the playing-flag (sgn sprite-delay), see documentation of draw-method."
122   (setf (sprite-delay obj) (- (sprite-delay obj))))
123
124 (defmethod is-paused ((obj animation))
125   "is animation paused?"
126   (< (sprite-delay obj) 0))
127
128 (defmethod is-playing ((obj animation))
129   "is animation playing?"
130   (< 0 (sprite-delay obj)))
131
132 (defmethod ensure-pause ((obj animation))
133   "ensures that the animation is paused if playing, otherwise, nothing is done."
134   (when (is-playing obj) (pause obj)))
135
136 (defmethod ensure-playing ((obj animation))
137   "ensures that the animation is playing if paused, otherwise, nothing is done."
138   (when (is-paused obj) (pause obj)))
139
140 (defmethod rewind ((obj animation))
141   "rewind the animation"
142   (setf (slot-value obj 'sprite-image-number) 0))
143
144 (defun make-animation (frame-skip &rest image-list)
145   "Create an animation from the list of animation-names given in the
146 images-variable."
147   ;(format t "make-animation is being called~%")
148   (make-instance 'animation
149                  :full-widths (mapcar
150                                #'(lambda (x) (bmp-width (cadr x))) image-list)
151                  :full-heights (mapcar
152                                 #'(lambda (x) (bmp-height (cadr x))) image-list)
153                  :images-2x (mapcar
154                              #'(lambda (x) (load-bmp-blob-into-texture (car x)))
155                              image-list)
156                  :images-1x (mapcar
157                              #'(lambda (x) (load-bmp-blob-into-texture (cadr x)))
158                              image-list)
159                  :images-.5x (mapcar
160                              #'(lambda (x) (load-bmp-blob-into-texture (caddr x)))
161                              image-list)
162                  :images-.25x (mapcar
163                              #'(lambda (x) (load-bmp-blob-into-texture (cadddr x)))
164                              image-list)
165                  :sprite-delay frame-skip))