Added reload of levels on F7 (Update levelpack) to ease the test of changes.
[enigmagame.git] / src / d_engine.hh
blob302e831d63e5dfe153b7b0c124c8e8a66a0ab1b6
1 /*
2 * Copyright (C) 2003 Daniel Heck
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 #ifndef D_ENGINE_HH
20 #define D_ENGINE_HH
22 #include "ecl_geom.hh"
23 #include "ecl_array2.hh"
24 #include "ecl_alist.hh"
25 #include "ecl_fwd.hh"
27 namespace display
30 /* -------------------- DisplayEngine -------------------- */
32 class DisplayEngine {
33 public:
34 DisplayEngine (int tilew=32, int tileh=32);
35 ~DisplayEngine();
37 /* ---------- Class configuration ---------- */
38 void add_layer (DisplayLayer *l);
39 void set_screen_area (const ecl::Rect & r);
40 void set_tilesize (int w, int h);
42 int get_tilew () const { return m_tilew; }
43 int get_tileh () const { return m_tileh; }
44 int get_width() const { return m_width; }
45 int get_height() const { return m_height; }
46 const ecl::Rect &get_area() const { return m_area; }
48 /* ---------- Scrolling / page flipping ---------- */
49 void set_offset (const ecl::V2 &off);
50 void move_offset (const ecl::V2 &off);
51 ecl::V2 get_offset () const { return m_offset; }
53 /* ---------- Game-related stuff ---------- */
54 void new_world (int w, int h);
55 void tick (double dtime);
57 /* ---------- Coordinate conversion ---------- */
58 void world_to_screen (const ecl::V2 & pos, int *x, int *y);
59 WorldArea screen_to_world (const ScreenArea &a);
60 ScreenArea world_to_screen (const WorldArea &a);
62 /* "Video" coordinates are like screen coordinates, except the
63 origin coincides with the world origin, not the current
64 scrolling position. */
65 void world_to_video (const ecl::V2 &pos, int *x, int *y);
66 void video_to_screen (int x, int y, int *xx, int *yy);
67 void video_to_world (const ecl::Rect &r, ecl::Rect &s);
69 V2 to_world (const V2 &pos);
71 /* ---------- Screen upates ---------- */
73 void mark_redraw_screen();
74 void mark_redraw_area (const WorldArea &wa, int delay=0);
76 void redraw_screen_area (const ScreenArea &a);
77 void redraw_world_area (const WorldArea &a);
79 void update_screen();
80 void draw_all (ecl::GC &gc);
81 void update_offset();
83 private:
84 void update_layer (DisplayLayer *l, WorldArea wa);
86 /* ---------- Variables ---------- */
88 std::vector<DisplayLayer *> m_layers;
89 int m_tilew, m_tileh;
91 // Offset of screen
92 ecl::V2 m_offset; // Offset in world units
93 ecl::V2 m_new_offset; // New offset in world units
94 int m_screenoffset[2]; // Offset in screen units
97 // Screen area occupied by level display
98 ecl::Rect m_area;
100 // Width and height of the world in tiles
101 int m_width, m_height;
103 ecl::Array2<char> m_redrawp;
107 /* -------------------- DisplayLayer -------------------- */
109 class DisplayLayer {
110 public:
111 DisplayLayer() {}
112 virtual ~DisplayLayer() {}
114 /* ---------- Class configuration ---------- */
115 void set_engine (DisplayEngine *e) { m_engine = e; }
116 DisplayEngine *get_engine() const { return m_engine; }
118 /* ---------- DisplayLayer interface ---------- */
119 virtual void prepare_draw (const WorldArea &) {}
120 virtual void draw (ecl::GC &gc, const WorldArea &a, int x, int y) = 0;
121 virtual void draw_onepass (ecl::GC &/*gc*/) {}
122 virtual void tick (double /*dtime*/) {}
123 virtual void new_world (int /*w*/, int /*h*/) {}
125 // Functions.
126 void mark_redraw_area (const ecl::Rect &r)
128 get_engine()->mark_redraw_area(r);
130 private:
131 DisplayEngine *m_engine;
135 /* -------------------- ModelLayer -------------------- */
137 /*! The base class for all layers that contains Models. */
138 class ModelLayer : public DisplayLayer {
139 public:
140 ModelLayer() {}
142 // DisplayLayer interface
143 void tick (double dtime);
144 void new_world (int, int);
146 // Member functions
147 void activate (Model *m);
148 void deactivate (Model *m);
149 void maybe_redraw_model(Model *m, bool immediately=false);
151 virtual int redraw_size () const { return 2; }
152 private:
154 // Variables
155 ModelList m_active_models;
156 ModelList m_active_models_new;
160 /* -------------------- DL_Grid -------------------- */
162 /*! Layer for grid-aligned models (stones, floor tiles, items). */
164 class DL_Grid : public ModelLayer {
165 public:
166 DL_Grid(int redrawsize = 1);
167 ~DL_Grid();
169 void set_model (int x, int y, Model *m);
170 Model *get_model (int x, int y);
171 Model *yield_model (int x, int y);
173 private:
174 // DL_Grid interface.
175 void mark_redraw (int x, int y);
177 // DisplayLayer interface.
178 void new_world (int w, int h);
179 void draw (ecl::GC &gc, const WorldArea &a, int x, int y);
181 // ModelLayer interface
182 virtual int redraw_size () const { return m_redrawsize; }
184 // Variables.
185 typedef ecl::Array2<Model*> ModelArray;
186 ModelArray m_models;
187 int m_redrawsize;
191 /* -------------------- Sprites -------------------- */
193 class Sprite : public ecl::Nocopy {
194 public:
195 Model *model;
196 V2 pos;
197 int screenpos[2];
198 SpriteLayer layer;
199 bool visible;
200 Sprite * above[3];
201 Sprite * beneath[3];
203 Sprite (const V2 & p, SpriteLayer l, Model *m)
204 : model(m), pos(p), layer(l), visible(true)
206 screenpos[0] = screenpos[1] = 0;
207 above[0] = above[1] = above[2] = NULL;
208 beneath[0] = beneath[1] = beneath[2] = NULL;
210 ~Sprite() { delete model; }
213 typedef std::vector<Sprite*> SpriteList;
215 class DL_Sprites : public ModelLayer {
216 public:
217 DL_Sprites();
218 ~DL_Sprites();
220 /* ---------- DisplayLayer interface ---------- */
221 void draw (ecl::GC &gc, const WorldArea &a, int x, int y);
222 void draw_onepass (ecl::GC &gc);
223 void new_world (int, int);
225 /* ---------- Member functions ---------- */
226 SpriteId add_sprite (Sprite *sprite, bool isDispensible = false);
227 void kill_sprite (SpriteId id);
228 void move_sprite (SpriteId, const ecl::V2& newpos);
229 void replace_sprite (SpriteId id, Model *m);
231 void redraw_sprite_region (SpriteId id);
232 void draw_sprites (bool shades, ecl::GC &gc, const WorldArea &a);
234 Model *get_model (SpriteId id) { return sprites[id]->model; }
236 void set_maxsprites (unsigned m, unsigned c) { maxsprites = m; dispensiblesprites = c;}
238 Sprite *get_sprite(SpriteId id);
240 static const SpriteId MAGIC_SPRITEID = 1000000;
241 SpriteList sprites;
242 SpriteList bottomSprites; // bottom sprite for each x
244 private:
245 void update_sprite_region (Sprite * s, bool is_add, bool is_redraw_only = false);
247 // ModelLayer interface
248 virtual void tick (double /*dtime*/);
250 // Variables.
251 unsigned numsprites; // Current number of sprites
252 unsigned maxsprites; // Maximum number of sprites
253 unsigned dispensiblesprites; // Threshold above which just critical sprites are accepted
257 /* -------------------- Shadows -------------------- */
259 struct StoneShadowCache;
261 class DL_Shadows : public DisplayLayer {
262 public:
263 DL_Shadows(DL_Grid *grid, DL_Sprites *sprites);
264 ~DL_Shadows();
266 void new_world(int w, int h);
267 void draw (ecl::GC &gc, int xpos, int ypos, int x, int y);
269 void draw (ecl::GC &gc, const WorldArea &a, int x, int y);
270 private:
271 /* ---------- Private functions ---------- */
272 void shadow_blit (ecl::Surface *scr, int x, int y,
273 ecl::Surface *shadows, ecl::Rect r);
275 bool has_actor (int x, int y);
276 virtual void prepare_draw (const WorldArea &);
278 Model * get_shadow_model(int x, int y);
280 /* ---------- Variables ---------- */
281 DL_Grid *m_grid; // Stone models
282 DL_Sprites *m_sprites; // Sprite models
284 StoneShadowCache *m_cache;
286 Uint32 shadow_ckey; // Color key
287 ecl::Surface *buffer;
289 ecl::Array2<bool> m_hasactor;
293 /* -------------------- Lines -------------------- */
295 struct Line {
296 V2 start, end;
297 V2 oldstart, oldend;
298 unsigned short r,g,b;
299 bool thick;
301 Line(const V2 &s, const V2 &e, unsigned short rc, unsigned short gc, unsigned short bc, bool isThick) :
302 start (s), end (e), r (rc), g (gc), b (bc), thick (isThick) {
304 Line() {}
308 typedef ecl::AssocList<unsigned, Line> LineMap;
310 class DL_Lines : public DisplayLayer {
311 public:
312 DL_Lines() : m_id(1)
316 void draw (ecl::GC &/*gc*/, const WorldArea &/*a*/, int /*x*/, int /*y*/)
318 void draw_onepass (ecl::GC &gc);
320 RubberHandle add_line (const V2 &p1, const V2 &p2, unsigned short rc, unsigned short gc, unsigned short bc, bool isThick);
321 void set_startpoint (unsigned id, const V2 &p1);
322 void set_endpoint (unsigned id, const V2 &p2);
323 void kill_line (unsigned id);
324 void new_world (int w, int h);
326 private:
327 // Private methods.
328 void mark_redraw_line (const Line &r);
330 // Variables.
331 unsigned m_id;
332 LineMap m_rubbers;
336 /* -------------------- CommonDisplay -------------------- */
338 /*! Parts of the display engine that are common to the game and
339 the editor. */
340 class CommonDisplay {
341 public:
342 CommonDisplay (const ScreenArea &a = ScreenArea (0, 0, 10, 10));
343 ~CommonDisplay();
345 Model *set_model (const GridLoc &l, Model *m);
346 Model *get_model (const GridLoc &l);
347 Model *yield_model (const GridLoc &l);
349 void set_floor (int x, int y, Model *m);
350 void set_item (int x, int y, Model *m);
351 void set_stone (int x, int y, Model *m);
353 DisplayEngine *get_engine() const { return m_engine; }
355 SpriteHandle add_effect (const V2& pos, Model *m, bool isDispensible = false);
356 SpriteHandle add_sprite (const V2 &pos, Model *m);
358 RubberHandle add_line (V2 p1, V2 p2, unsigned short rc, unsigned short gc, unsigned short bc, bool isThick);
360 void new_world (int w, int h);
361 void redraw();
363 protected:
364 DL_Grid *floor_layer;
365 DL_Grid *item_layer;
366 DL_Grid *stone_layer;
368 DL_Sprites *effects_layer;
370 DL_Lines *line_layer;
371 DL_Sprites *sprite_layer;
372 DL_Shadows *shadow_layer;
374 private:
376 DisplayEngine *m_engine;
380 /* -------------------- Scrolling -------------------- */
383 class Follower {
384 public:
385 Follower (DisplayEngine *e);
386 virtual ~Follower() {}
387 virtual void tick(double dtime, const ecl::V2 &point) = 0;
388 virtual void center(const ecl::V2 &point);
390 void set_boundary (double b) {
391 m_boundary_x = b;
392 m_boundary_y = b;
395 protected:
396 DisplayEngine *get_engine() const { return m_engine; }
397 bool set_offset (V2 offs);
398 double get_hoff() const;
399 double get_voff() const;
400 ecl::V2 get_scrollpos(const ecl::V2 &point);
402 double m_boundary_x;
403 double m_boundary_y;
405 private:
406 DisplayEngine *m_engine;
409 /*! Follows a sprite by flipping to the next screen as soon as the
410 sprite reaches the border of the current screen. */
411 class Follower_Screen : public Follower {
412 public:
413 Follower_Screen(DisplayEngine *e, double borderx = 0.5, double bordery = 0.5);
414 void tick(double dtime, const ecl::V2 &point);
417 /*! Follows a sprite by softly scrolling the visible area of the
418 screen as soon as the sprite reaches the border of the current
419 screen. */
420 class Follower_Scrolling : public Follower {
421 public:
422 Follower_Scrolling (DisplayEngine *e, bool screenwise, double borderx = 0.5, double bordery = 0.5);
423 void tick(double dtime, const ecl::V2 &point);
424 void center(const ecl::V2 &point);
425 private:
426 bool currently_scrolling;
427 V2 curpos, destpos;
428 V2 dir;
429 double scrollspeed;
430 double resttime;
431 bool screenwise;
434 class Follower_Smooth : public Follower {
435 public:
436 Follower_Smooth (DisplayEngine *e);
437 void tick (double time, const ecl::V2 &point);
438 void center (const ecl::V2 &point);
439 virtual void set_boundary (double b) {}
441 ecl::V2 calc_offset (const ecl::V2 &point);
445 /* -------------------- GameDisplay -------------------- */
447 class GameDisplay : public CommonDisplay {
448 public:
449 GameDisplay (const ScreenArea &gamearea,
450 const ScreenArea &inventoryarea);
451 ~GameDisplay();
453 StatusBar * get_status_bar() const;
455 void tick(double dtime);
456 void new_world (int w, int h);
458 void resize_game_area (int w, int h);
460 /* ---------- Scrolling ---------- */
461 void set_follow_mode (FollowMode m);
462 void updateFollowMode();
463 void follow_center();
464 void set_follow_sprite(SpriteId id);
465 void set_reference_point (const ecl::V2 &point);
466 void set_scroll_boundary (double d);
468 // current screen coordinates of reference point
469 void get_reference_point_coordinates(int *x, int *y);
471 /* ---------- Screen updates ---------- */
472 void redraw (ecl::Screen *scr);
473 void redraw_all (ecl::Screen *scr);
474 void draw_all (ecl::GC &gc);
476 private:
477 void set_follower (Follower *f);
478 void draw_borders (ecl::GC &gc);
480 /* ---------- Variables ---------- */
481 Uint32 last_frame_time;
482 bool redraw_everything;
483 StatusBarImpl *status_bar;
485 V2 m_reference_point;
486 Follower *m_follower;
488 ScreenArea inventoryarea;
491 class ModelHandle {
492 public:
493 ModelHandle ();
497 #endif