1 /**
2  ** Animate.h - Animated game objects.
3  **
4  ** Written: 7/27/2000 - JSF
5  **/
6 
7 /*
8 Copyright (C) 2000  Jeffrey S. Freedman
9 
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License
12 as published by the Free Software Foundation; either version 2
13 of the License, or (at your option) any later version.
14 
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 GNU General Public License for more details.
19 
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23 */
24 
25 #ifndef INCL_ANIMATE
26 #define INCL_ANIMATE    1
27 
28 #include "iregobjs.h"
29 #include "miscinf.h"
30 
31 /*
32  *  A class for playing sound effects that get updated by position
33  *  and distance. Adds itself to time-queue, deletes itself when done.
34  */
35 class Object_sfx : public Time_sensitive, public Game_singletons {
36 	Game_object_weak obj;   // Object that caused the sound.
37 	Tile_coord last_pos;
38 	int sfx;            // ID of sound effect being played.
39 	int channel;        // Channel of sfx being played.
40 	void stop_playing();
41 	Object_sfx(Game_object *o, int sfx);
42 protected:
43 	void dequeue() override;
44 public:
45 	static void Play(Game_object *o, int sfx, int delay = 20);
46 	void stop();
get_sfxnum()47 	int get_sfxnum() {
48 		return sfx;
49 	}
50 	void handle_event(unsigned long time, uintptr udata) override;
51 };
52 
53 /*
54  *  A class for playing sound effects when certain objects are nearby.
55  */
56 class Shape_sfx : public Game_singletons {
57 	const Game_object *obj;       // Object that caused the sound.
58 	const SFX_info *sfxinf;
59 	int channel[2];         // ID of sound effect being played.
60 	int distance;           // Distance in tiles from Avatar.
61 	int dir;            // Direction (0-15) from Avatar.
62 	int last_sfx;       // For playing sequential sfx ranges.
63 	bool looping;       // If the SFX should loop until stopped.
64 public:
65 	// Create & start playing sound.
Shape_sfx(Game_object * o)66 	Shape_sfx(Game_object *o)
67 		: obj(o), distance(0), last_sfx(-1) {
68 		channel[0] = channel[1] = -1;
69 		sfxinf = obj->get_info().get_sfx_info();
70 		if (sfxinf)
71 			last_sfx = 0;
72 		set_looping();  // To avoid including sfxinf.h.
73 	}
get_sfxnum()74 	int get_sfxnum() {
75 		return last_sfx;
76 	}
get_distance()77 	int get_distance() {
78 		return distance;
79 	}
80 	void update(bool play); // Set to new object.
81 	void set_looping();
82 	void stop();
83 };
84 
85 /*
86  *  An animator:
87  */
88 class Animator : public Time_sensitive, public Game_singletons {
89 protected:
90 	Game_object *obj;       // Object we're controlling.
91 	unsigned char deltax, deltay;   // If wiggling, deltas from
92 	//   original position.
93 	bool animating;         // 1 if animation turned on.
94 	Shape_sfx *objsfx;
95 	void start_animation();
96 public:
Animator(Game_object * o)97 	Animator(Game_object *o)
98 		: obj(o), deltax(0), deltay(0), animating(false) {
99 		objsfx = new Shape_sfx(obj);
100 	}
101 	static Animator *create(Game_object *ob);
102 	~Animator() override;
want_animation()103 	void want_animation() {     // Want animation on.
104 		if (!animating)
105 			start_animation();
106 	}
stop_animation()107 	void stop_animation() {
108 		animating = false;
109 	}
get_deltax()110 	int get_deltax() {
111 		return deltax;
112 	}
get_deltay()113 	int get_deltay() {
114 		return deltay;
115 	}
116 	virtual int get_framenum();
activate_animator()117 	virtual void activate_animator() {
118 	}
deactivate_animator()119 	virtual void deactivate_animator() {
120 	}
121 };
122 
123 /*
124  *  Animate by going through frames.
125  */
126 class Frame_animator : public Animator {
127 	const Animation_info *aniinf;
128 	unsigned short first_frame; // Initial frame of animation cycle
129 	unsigned short currpos;         // Current position in the animation.
130 	unsigned short nframes;     // Number of frames in cycle.
131 	unsigned short frame_counter;       // When to increase frame.
132 	unsigned int created;       // Time created
133 	unsigned short last_shape;  // To check if we need to re init
134 	unsigned short last_frame;  // To check if we need to re init
135 	void Initialize();
136 public:
137 	Frame_animator(Game_object *o);
138 	int get_next_frame();
139 	// For Time_sensitive:
140 	void handle_event(unsigned long time, uintptr udata) override;
get_framenum()141 	int get_framenum() override {
142 		return obj->get_framenum();
143 	}
144 };
145 
146 /*
147  *  Just play SFX.
148  */
149 class Sfx_animator : public Animator {
150 public:
151 	Sfx_animator(Game_object *o);
152 	// For Time_sensitive:
153 	void handle_event(unsigned long time, uintptr udata) override;
154 };
155 
156 /*
157  *  Animate by going through frames, but only do the lower frames once.
158  */
159 class Field_frame_animator : public Frame_animator {
160 	bool activated;         // Time to check for damage.
161 public:
162 	friend class Field_object;
163 	Field_frame_animator(Game_object *o);
164 	// For Time_sensitive:
165 	void handle_event(unsigned long time, uintptr udata) override;
activate_animator()166 	void activate_animator() override {
167 		activated = true;
168 	}
deactivate_animator()169 	void deactivate_animator() override {
170 		activated = false;
171 	}
172 };
173 
174 /*
175  *  Animate by wiggling.
176  */
177 class Wiggle_animator : public Animator {
178 public:
Wiggle_animator(Game_object * o)179 	Wiggle_animator(Game_object *o) : Animator(o)
180 	{  }
181 	// For Time_sensitive:
182 	void handle_event(unsigned long time, uintptr udata) override;
183 };
184 
185 /*
186  *  An object that cycles through its frames, or wiggles if just one
187  *  frame.  The base class is for those in U7chunks.
188  */
189 class Animated_object : public Terrain_game_object {
190 	Animator *animator;     // Controls animation.
191 public:
192 	Animated_object(int shapenum, int framenum, unsigned int tilex,
193 	                unsigned int tiley, unsigned int lft = 0);
194 	~Animated_object() override;
195 	// Render.
196 	void paint() override;
197 	// +++++Needed on this one:
198 	// Get coord. where this was placed.
get_original_tile_coord()199 	Tile_coord get_original_tile_coord() const override {
200 		return get_tile() +
201 		       Tile_coord(-animator->get_deltax(),
202 		                  -animator->get_deltay(), 0);
203 	}
204 };
205 
206 /*
207  *  An object that cycles through its frames, or wiggles if just one
208  *  frame.  This is the IREG version.
209  */
210 class Animated_ireg_object : public Ireg_game_object {
211 	Animator *animator;     // Controls animation.
212 public:
213 	Animated_ireg_object(int shapenum, int framenum, unsigned int tilex,
214 	                     unsigned int tiley, unsigned int lft = 0);
215 	~Animated_ireg_object() override;
216 	// Render.
217 	void paint() override;
218 	// Get coord. where this was placed.
get_original_tile_coord()219 	Tile_coord get_original_tile_coord() const override {
220 		return get_tile() +
221 		       Tile_coord(-animator->get_deltax(),
222 		                  -animator->get_deltay(), 0);
223 	}
224 
225 	// Write out to IREG file.
226 	void write_ireg(ODataSource *out) override;
227 };
228 
229 /*
230  *  An object that cycles through its frames, or wiggles if just one
231  *  frame.  This is the IFIX version.
232  */
233 class Animated_ifix_object : public Ifix_game_object {
234 	Animator *animator;     // Controls animation.
235 public:
236 	Animated_ifix_object(int shapenum, int framenum, unsigned int tilex,
237 	                     unsigned int tiley, unsigned int lft = 0);
238 	~Animated_ifix_object() override;
239 	// Render.
240 	void paint() override;
241 	// Get coord. where this was placed.
get_original_tile_coord()242 	Tile_coord get_original_tile_coord() const override {
243 		return get_tile() +
244 		       Tile_coord(-animator->get_deltax(),
245 		                  -animator->get_deltay(), 0);
246 	}
247 
248 	void write_ifix(ODataSource *ifix, bool v2) override;
249 };
250 #endif
251 
252 
253