namespace { typedef px::Rect ScreenArea; typedef px::Rect WorldArea; class DisplayLayer; struct Field2 { Field2() { updatep=redrawp=false; } bool updatep; bool redrawp; }; typedef px::Array2 Field2Array; class DisplayEngine { public: DisplayEngine (px::Screen *scr); ~DisplayEngine(); /* ** Class configuration */ void add_layer (DisplayLayer *l); void set_tilesize (int w, int h) { m_tilew=w; m_tileh=h; } void set_screen_area (const px::Rect & r); px::Rect get_area() const { return m_area; } int get_width() const { return m_width; } int get_height() const { return m_height; } /* ** Scrolling / page flipping */ void set_offset (const px::V2 &off); void move_offset (const px::V2 &off); px::V2 get_offset () const { return m_offset; } /* ** Game-related stuff */ void new_world (int w, int h); void tick (double dtime); /* ** Coordinate conversion */ void world_to_screen (const V3 & pos, int *x, int *y); void world_to_screen (const V2 & pos, int *x, int *y); WorldArea screen_to_world (const ScreenArea &a); V2 to_screen (const V2 &pos); V2 to_world (const V2 &pos); /* ** Screen upates */ void mark_redraw_screen(); void mark_redraw_area (const WorldArea &wa); void mark_update_world(); void mark_update_area (const WorldArea &wa); void redraw_screen_area (const ScreenArea &a); void redraw_world_area (const WorldArea &a); void update_screen(); void draw_all (px::GC &gc); Field2 &get_field (int x, int y) { return m_fields(x,y); } private: /* ** Variables */ std::vector m_layers; int m_tilew, m_tileh; px::Screen *m_screen; // Offset of screen px::V2 m_offset; // Area on the screen px::Rect m_area; // Width and height of the world in tiles int m_width, m_height; Field2Array m_fields; }; //---------------------------------------- // Display layer //---------------------------------------- class DisplayLayer { public: DisplayLayer() {} virtual ~DisplayLayer() {} /* ** Class configuration */ void set_engine (DisplayEngine *e) { m_engine = e; } DisplayEngine *get_engine() const { return m_engine; } /* ** DisplayLayer interface. */ virtual void draw (px::GC &gc, px::Rect &area, int x, int y) = 0; virtual void notify_expose (px::Rect &area) {} virtual void tick (double dtime) {} virtual void new_world (int w, int h) {} // Functions. void mark_redraw_area (const px::Rect &r); private: DisplayEngine *m_engine; }; //---------------------------------------- // Layer for grid-aligned models //---------------------------------------- class DL_GridModels : public DisplayLayer { public: DL_GridModels(); virtual void draw (px::GC &gc, px::Rect &area, int x, int y) { } private: // Variables. }; //---------------------------------------- // Sprite layer //---------------------------------------- class Sprite : public Nocopy { public: Model *model; V3 pos; SpriteLayer layer; bool visible; Sprite(const V3 & p, SpriteLayer l, Model *m) : model(m), pos(p), layer(l) {} ~Sprite() { delete model; } }; typedef vector SpriteList; class DL_Sprites : public DisplayLayer { public: DL_Sprites(); ~DL_Sprites(); void draw (px::GC &gc, px::Rect &area, int x, int y) { } void new_world (int, int); SpriteId add_sprite (Sprite *sprite); void kill_sprite (SpriteId id); void move_sprite (SpriteId, const px::V3& newpos); void replace_sprite (SpriteId id, Model *m); void redraw_sprite_region (SpriteId id); void draw_sprites (bool shades, GC &gc); SpriteList sprites; void set_maxsprites (unsigned m) { maxsprites = m; } private: // Variables. unsigned numsprites; // Current number of sprites unsigned maxsprites; // Maximum number of sprites }; //---------------------------------------- // Shadow layer //---------------------------------------- class ShadowLayer { public: virtual ~ShadowLayer() {} virtual void new_world(int w, int h) {} virtual void update (int x, int y) = 0; virtual void draw(GC &gc, int xpos, int ypos, int x, int y) = 0; }; class DL_Shadows : public DisplayLayer { public: DL_Shadows(); virtual void draw (px::GC &gc, px::Rect &area, int x, int y) { } private: // Variables. DL_GridModels m_grid; // stone shadows DL_Sprites m_sprites; // sprite shadows }; //---------------------------------------- // Lines / Rubber Bands //---------------------------------------- struct Line { V2 start,end; V2 oldstart, oldend; Line(const V2 &s, const V2 &e) :start(s), end(e) {} Line() {} }; typedef AssocList LineMap; class DL_Lines : public DisplayLayer { public: DL_Lines() : m_id(1) { } virtual void draw (px::GC &gc, px::Rect &area, int x, int y) { } void draw_lines (GC &gc); RubberHandle add_line (const V2 &p1, const V2 &p2); void set_startpoint (unsigned id, const V2 &p1); void set_endpoint (unsigned id, const V2 &p2); void kill_line (unsigned id); private: // Private methods. void mark_redraw_line (const Line &r); // Variables. unsigned m_id; LineMap m_rubbers; }; }