/[enigma]/enigma/src/display.cc
ViewVC logotype

Diff of /enigma/src/display.cc

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.12 by dheck, Wed Feb 26 21:08:55 2003 UTC revision 1.13 by dheck, Fri Feb 28 15:02:52 2003 UTC
# Line 42  Line 42 
42  using namespace std;  using namespace std;
43  using namespace px;  using namespace px;
44  using namespace display;  using namespace display;
45    using namespace enigma;
46    
47  #include "d_engine.hh"  #include "d_engine.hh"
48  #include "d_statusbar.hh"  #include "d_statusbar.hh"
49    
 /*  
  * Function prototypes  
  */  
 static void follow_center();  
 static void follow_doit(double dtime);  
   
 namespace  
 {  
     struct Field {  
         static const int NUM_LAYERS = 3;  
       
         Field() {  
             fill_n(layers, NUM_LAYERS, (Model*)0);  
             redrawp = updatep = false;  
         }  
         ~Field() { delete_sequence(layers, layers+NUM_LAYERS); }  
   
         Model* layers[NUM_LAYERS];  
         bool redrawp;  
         bool updatep;  
     };  
   
     typedef Array2<Field>   FieldArray;  
     typedef list<Model*>   ModelList;  
 }  
   
50  //----------------------------------------  //----------------------------------------
51  // Local variables  // Local variables
52  //----------------------------------------  //----------------------------------------
# Line 91  static double ScrollY = 0; Line 66  static double ScrollY = 0;
66  static int TileWidth = 32;  static int TileWidth = 32;
67  static int TileHeight = 32;  static int TileHeight = 32;
68    
69  static bool RedrawEverything=false;  static GameDisplay   *gamedpy = 0;
70    static DisplayEngine *engine  = 0;
71    
72  static DisplayEngine *engine        = 0;  static DL_Lines   *line_layer    = 0;
73  static DL_Lines      *line_layer    = 0;  static DL_Sprites *sprite_layer  = 0;
74  static DL_Sprites    *sprite_layer  = 0;  static DL_Shadows *shadow_layer  = 0;
 static DL_Sprites    *effects_layer = 0;  
 static ShadowLayer   *shadow_layer  = 0;  
75    
76  namespace  namespace
77  {  {
# Line 107  namespace Line 81  namespace
81      ModelList       active_models;      ModelList       active_models;
82      FieldArray      fields(0,0);      FieldArray      fields(0,0);
83    
     StatusBarImpl   *status_bar = 0;  
   
84      // Screen layout      // Screen layout
85      ScreenArea gamearea(0,0,640, 480-64);      ScreenArea gamearea(0,0,640, 480-64);
     ScreenArea inventoryarea(0, 480-64, 640, 64);  
86  }  }
87    
88    
# Line 145  void maybe_redraw_model(Model *m) Line 116  void maybe_redraw_model(Model *m)
116      }      }
117  }  }
118    
119  static void  void
120  mark_change(const GridLoc &l)  ModelLayer::activate (Model *m)
121  {  {
122      if (l.layer == enigma::GRID_STONES)      list<Model*> &am = m_active_models;
123          engine->mark_update_area (Rect(l.pos.x, l.pos.y, 2,2));      if (find(am.begin(), am.end(), m) == am.end())
124      else          am.push_back(m);
         engine->mark_redraw_area (Rect(l.pos.x,l.pos.y, 1,1));  
125  }  }
126    
127    void
128  static inline void  ModelLayer::deactivate (Model *m)
 draw_model(GC &gc, int x, int y, Model *m)  
129  {  {
130      if (m)      m_active_models.remove(m);
         m->draw(gc, x, y);  
131  }  }
132    
133  static void  void
134  draw_field(GC &gc, Field &f, int x, int y)  ModelLayer::tick (double dtime)
135  {  {
136      int xpos, ypos;      ModelList &am = m_active_models;
137      engine->world_to_screen (V2(x, y), &xpos, &ypos);      am.remove_if(mem_fun(&Model::is_garbage));
   
     using namespace enigma;  
138    
139      if (display_flags & SHOW_FLOOR) draw_model(gc, xpos, ypos, f.layers[GRID_FLOOR]);      /* for_each does not work; animation may remove itself during a
140      if (display_flags & SHOW_ITEMS) draw_model(gc, xpos, ypos, f.layers[GRID_ITEMS]);         tick.  This may happen for example when a model callback
141      if (display_flags & SHOW_SPRITES) sprite_layer->draw_sprites (false, gc);         decides to replace the old model by another one.  */
142      if (display_flags & SHOW_SHADES) shadow_layer->draw(gc, xpos, ypos, x, y);      for (ModelList::iterator i=am.begin(); i!=am.end(); ) {
143      if (display_flags & SHOW_SPRITES) sprite_layer->draw_sprites (false, gc);          ModelList::iterator n=next(i);
144      if (display_flags & SHOW_STONES) draw_model(gc, xpos, ypos, f.layers[GRID_STONES]);          (*i)->tick(dtime);
145      if (display_flags & SHOW_SPRITES) effects_layer->draw_sprites (false, gc);          i=n;
146        }
147        for_each(am.begin(), am.end(), &maybe_redraw_model);
148  }  }
149    
150    
151    
152    
153  //======================================================================  //======================================================================
154  // DISPLAY ENGINE  // DISPLAY ENGINE
155  //======================================================================  //======================================================================
156    
157  DisplayEngine::DisplayEngine (px::Screen *scr)  DisplayEngine::DisplayEngine (px::Screen *scr)
158  : m_tilew(32), m_tileh(32), m_screen (scr)  : m_tilew(32), m_tileh(32), m_screen (scr),
159  , m_offset()    m_offset(),
160  , m_area (scr->size())    m_area (scr->size()),
161  , m_width(0), m_height(0)    m_width(0), m_height(0),
162  , m_fields(0,0)    m_fields(0,0)
163  {  {
164  }  }
165    
# Line 219  DisplayEngine::move_offset (const px::V2 Line 189  DisplayEngine::move_offset (const px::V2
189      int newx = int(off[0] * m_tilew);      int newx = int(off[0] * m_tilew);
190      int newy = int(off[1] * m_tileh);      int newy = int(off[1] * m_tileh);
191    
192    
193    
194      if (newx != oldx || newy != oldy)      if (newx != oldx || newy != oldy)
195      {      {
196          Rect newarea(newx, newy, gamearea.w, gamearea.h);          Rect newarea(newx, newy, m_area.w, m_area.h);
197          Rect oldarea(oldx, oldy, gamearea.w, gamearea.h);          Rect oldarea(oldx, oldy, m_area.w, m_area.h);
198          Rect common = intersect(newarea, oldarea);          Rect common = intersect(newarea, oldarea);
199    
200          Rect blitrect(common.x-oldx+gamearea.x,          Rect blitrect(common.x-oldx+m_area.x,
201                        common.y-oldy+gamearea.y,                        common.y-oldy+m_area.y,
202                        common.w, common.h);                        common.w, common.h);
203          m_screen->blit(common.x-newx+gamearea.x,          m_screen->blit(common.x-newx+m_area.x,
204                         common.y-newy+gamearea.y,                         common.y-newy+m_area.y,
205                         m_screen,                         m_screen,
206                         blitrect);                         blitrect);
207          blitrect.x = common.x-newx+gamearea.x;          blitrect.x = common.x-newx+m_area.x;
208          blitrect.y = common.y-newy+gamearea.y;          blitrect.y = common.y-newy+m_area.y;
209          m_screen->update_rect(blitrect);          m_screen->update_rect(blitrect);
210    
211          ScrollX = newx/double(TileWidth);          ScrollX = newx/double(m_tilew);
212          ScrollY = newy/double(TileHeight);          ScrollY = newy/double(m_tileh);
213    
214          m_offset = V2(ScrollX, ScrollY);          m_offset = V2(ScrollX, ScrollY);
215    
# Line 293  DisplayEngine::world_to_screen (const V2 Line 265  DisplayEngine::world_to_screen (const V2
265      *y = int((pos[1] - m_offset[1])*m_tileh);      *y = int((pos[1] - m_offset[1])*m_tileh);
266  }  }
267    
268    ScreenArea
269    DisplayEngine::world_to_screen (const WorldArea &a)
270    {
271        int x, y;
272        world_to_screen (V2(a.x, a.y), &x, &y);
273        return ScreenArea (x, y, a.w*m_tilew, a.h*m_tileh);
274    }
275    
276    
277  WorldArea  WorldArea
278  DisplayEngine::screen_to_world (const ScreenArea &a)  DisplayEngine::screen_to_world (const ScreenArea &a)
279  {  {
# Line 317  DisplayEngine::mark_redraw_area (const W Line 298  DisplayEngine::mark_redraw_area (const W
298      int y2 = Min(m_height, wa.y+wa.h);      int y2 = Min(m_height, wa.y+wa.h);
299      for (int x=Max(0,wa.x); x <x2; x++)      for (int x=Max(0,wa.x); x <x2; x++)
300          for (int y=Max(0,wa.y); y<y2; y++)          for (int y=Max(0,wa.y); y<y2; y++)
301              fields(x,y).redrawp = true;              m_fields(x,y).redrawp = true;
302  }  }
303    
304  void  void
# Line 327  DisplayEngine::mark_update_area (const W Line 308  DisplayEngine::mark_update_area (const W
308      int y2 = Min(m_height, wa.y+wa.h);      int y2 = Min(m_height, wa.y+wa.h);
309      for (int x=Max(0,wa.x); x <x2; x++)      for (int x=Max(0,wa.x); x <x2; x++)
310          for (int y=Max(0,wa.y); y<y2; y++)          for (int y=Max(0,wa.y); y<y2; y++)
311              fields(x,y).updatep = true;              m_fields(x,y).updatep = true;
312  }  }
313    
314  void  void
# Line 342  DisplayEngine::mark_redraw_screen() Line 323  DisplayEngine::mark_redraw_screen()
323      mark_redraw_area(screen_to_world(m_area));      mark_redraw_area(screen_to_world(m_area));
324  }  }
325    
326    
327    void
328    DisplayEngine::draw_field (GC &gc, int x, int y)
329    {
330        int xpos, ypos;
331        world_to_screen (V2(x, y), &xpos, &ypos);
332    
333        for (unsigned i=0; i<m_layers.size(); ++i) {
334            m_layers[i]->draw (gc, WorldArea(x,y,1,1), xpos, ypos);
335        }
336    }
337    
338    
339  void  void
340  DisplayEngine::draw_all (px::GC &gc)  DisplayEngine::draw_all (px::GC &gc)
341  {  {
342      WorldArea wa = screen_to_world (gamearea);      WorldArea wa = screen_to_world (m_area);
343    
344      int x2 = wa.x+wa.w;      int x2 = wa.x+wa.w;
345      int y2 = wa.y+wa.h;      int y2 = wa.y+wa.h;
346      for (int x=wa.x; x<x2; x++) {      for (int x=wa.x; x<x2; x++) {
347          for (int y=wa.y; y<y2; y++) {          for (int y=wa.y; y<y2; y++) {
348              Field &f = fields(x,y);              Field2 &f2 = m_fields(x,y);
349              if (f.updatep) {              if (f2.updatep) {
350                  shadow_layer->update(x,y);                  shadow_layer->update(x,y);
351                  f.redrawp = true;                  f2.redrawp = true;
352                  f.updatep = false;                  f2.updatep = false;
353              }              }
354              ScreenArea sa(int((x-m_offset[0])*m_tilew),              ScreenArea sa(int((x-m_offset[0])*m_tilew),
355                            int((y-m_offset[1])*m_tileh),                            int((y-m_offset[1])*m_tileh),
356                            m_tilew,                            m_tilew,
357                            m_tileh);                            m_tileh);
358              sa.intersect(gamearea);              sa.intersect (m_area);
359              clip(gc, sa);              clip(gc, sa);
360              draw_field(gc, f, x,y);              draw_field(gc, x,y);
361          }          }
362      }      }
363      line_layer->draw_lines (gc);      line_layer->draw_lines (gc);
# Line 382  DisplayEngine::update_screen() Line 376  DisplayEngine::update_screen()
376      int y2 = wa.y+wa.h;      int y2 = wa.y+wa.h;
377      for (int x=wa.x; x<x2; x++) {      for (int x=wa.x; x<x2; x++) {
378          for (int y=wa.y; y<y2; y++) {          for (int y=wa.y; y<y2; y++) {
379              Field &f = fields(x,y);              Field2 &f2 = m_fields(x,y);
380              if (f.updatep) {              if (f2.updatep) {
381                  shadow_layer->update(x,y);                  shadow_layer->update(x,y);
382                  f.redrawp = true;                  f2.redrawp = true;
383                  f.updatep = false;                  f2.updatep = false;
384              }              }
385              if (f.redrawp) {              if (f2.redrawp) {
386                  ScreenArea sa(int((x-m_offset[0])*m_tilew),                  ScreenArea sa(int((x-m_offset[0])*m_tilew),
387                                int((y-m_offset[1])*m_tileh),                                int((y-m_offset[1])*m_tileh),
388                                m_tilew,                                m_tilew,
389                                m_tileh);                                m_tileh);
390                  sa.intersect(area);                  sa.intersect(area);
391                  clip(gc, sa);                  clip(gc, sa);
392                  draw_field(gc, f, x,y);                  draw_field(gc, x,y);
393                  f.redrawp = false;                  f2.redrawp = false;
394                  m_screen->update_rect(sa);                  m_screen->update_rect(sa);
395              }              }
396          }          }
# Line 433  DL_Sprites::move_sprite (SpriteId id, co Line 427  DL_Sprites::move_sprite (SpriteId id, co
427      if (id == magic_spriteid)      if (id == magic_spriteid)
428          return;          return;
429      Sprite *sprite = sprites[id];      Sprite *sprite = sprites[id];
430      if ((fabs(newpos[0]-sprite->pos[0]) > 1.0/TileWidth) ||  
431          (fabs(newpos[1]-sprite->pos[1]) > 1.0/TileHeight))      int oldx, oldy;
432      {      int newx, newy;
433        engine->world_to_screen (newpos, &newx, &newy);
434        engine->world_to_screen (sprite->pos, &oldx, &oldy);
435    
436        if (oldx != newx || oldy != newy) {
437          redraw_sprite_region(id);          redraw_sprite_region(id);
438          sprite->pos = newpos;          sprite->pos = newpos;
439          redraw_sprite_region(id);          redraw_sprite_region(id);
# Line 499  DL_Sprites::kill_sprite (SpriteId id) Line 497  DL_Sprites::kill_sprite (SpriteId id)
497      }      }
498  }  }
499    
500    void
501    DL_Sprites::draw (px::GC &gc, const WorldArea &a, int x, int y)
502    {
503        clip (gc, get_engine()->world_to_screen(a));
504        draw_sprites (false, gc);
505    }
506    
507  void  void
508  DL_Sprites::draw_sprites (bool shades, GC &gc)  DL_Sprites::draw_sprites (bool shades, GC &gc)
509  {  {
# Line 532  DL_Sprites::redraw_sprite_region (Sprite Line 537  DL_Sprites::redraw_sprite_region (Sprite
537      Sprite *s = sprites[id];      Sprite *s = sprites[id];
538      int x = int(s->pos[0]-0.5);      int x = int(s->pos[0]-0.5);
539      int y = int(s->pos[1]-0.5);      int y = int(s->pos[1]-0.5);
540      engine->mark_redraw_area (Rect(x, y, 3, 3));      get_engine()->mark_redraw_area (Rect(x, y, 3, 3));
541  }  }
542    
543    
544  //----------------------------------------------------------------------  //----------------------------------------------------------------------
545  // GRID MODELS  // GRID LAYER
546  //----------------------------------------------------------------------  //----------------------------------------------------------------------
547    
548    DL_Grid::DL_Grid()
549    {
550    }
551    
552    void
553    DL_Grid::new_world (int w, int h)
554    {
555        m_models = ModelArray (w, h);
556    }
557    
558    void
559    DL_Grid::mark_update (int x, int y)
560    {
561        get_engine()->mark_update_area (WorldArea (x, y, 2, 2));
562    }
563    
564    void
565    DL_Grid::set_model (int x, int y, Model *m)
566    {
567        if (m_models(x,y) != m) {
568            delete m_models(x,y);
569            m_models(x,y) = m;
570            mark_update(x,y);
571        }
572    }
573    
574    Model *
575    DL_Grid::get_model (int x, int y)
576    {
577        return m_models(x,y);
578    }
579    
580    Model *
581    DL_Grid::yield_model (int x, int y)
582    {
583        Model *m = m_models(x,y);
584        m_models(x,y) = 0;
585        mark_update(x,y);
586        return m;
587    }
588    
589    
590    void
591    DL_Grid::draw (px::GC &gc, const WorldArea &a, int destx, int desty)
592    {
593        int x2 = a.x+a.w;
594        int y2 = a.y+a.h;
595        for (int x=a.x; x<x2; ++x)
596            for (int y=a.y; y<y2; ++y)
597                if (Model *m = m_models(x,y))
598                    m->draw(gc, destx, desty);
599    }
600    
601    
602    
603  //----------------------------------------------------------------------  //----------------------------------------------------------------------
# Line 548  DL_Sprites::redraw_sprite_region (Sprite Line 606  DL_Sprites::redraw_sprite_region (Sprite
606    
607  #include "SDL_gfxPrimitives.h"  #include "SDL_gfxPrimitives.h"
608    
609    void
610    DL_Lines::draw (px::GC &gc, const WorldArea &a, int x, int y)
611    {
612        clip (gc, get_engine()->world_to_screen(a));
613        draw_lines(gc);
614    }
615    
616    
617  void  void
618  DL_Lines::draw_lines (GC &gc)  DL_Lines::draw_lines (GC &gc)
619  {  {
# Line 680  void RubberHandle::kill() Line 746  void RubberHandle::kill()
746      line_layer->kill_line(id);      line_layer->kill_line(id);
747  }  }
748    
749    
750  //----------------------------------------------------------------------  //----------------------------------------------------------------------
751  // SHADOWS  // SHADOWS
752  //----------------------------------------------------------------------  //----------------------------------------------------------------------
753    
754  namespace  DL_Shadows::DL_Shadows(DL_Grid *grid, DL_Sprites *sprites)
755  {  : m_grid(grid), m_sprites(sprites),
756      class ShadowLayer_Alpha : public ShadowLayer {    m_gridcache()
     public:  
         ShadowLayer_Alpha();  
         ~ShadowLayer_Alpha();  
   
         void new_world(int w, int h);  
         void update (int x, int y);  
         void draw(GC &gc, int xpos, int ypos, int x, int y);  
     private:  
         void shadow_blit (px::Surface *scr, int x, int y,  
                           px::Surface *shadows, px::Rect r);  
   
         Surface *new_surface();  
         void     dispose_surface(Surface *s);  
         Surface *get_cache(int x, int y);  
         bool     draw_stone_shade(GC &gc, int x, int y, Field &f);  
   
         // Variables.  
         Surface           *shadow_surface;  
         Uint32             shadow_ckey; // Color key  
         Array2<Surface *>  m_gridcache;  
         Array2<bool>       has_shadow;  
         vector<Surface *>  m_surface_avail;  
         Surface           *buffer;  
     };  
   
     class ShadowLayer_Stippled : public ShadowLayer {  
     public:  
         ShadowLayer_Stippled() {}  
         void update (int x, int y) {}  
         void draw(GC &gc, int xpos, int ypos, int x, int y)  
         {}  
     private:  
   
     };  
 }  
   
 ShadowLayer_Alpha::ShadowLayer_Alpha()  
     : m_gridcache()  
757  {  {
758      SDL_Surface *ss = SDL_CreateRGBSurface(SDL_SWSURFACE,      SDL_Surface *ss = SDL_CreateRGBSurface(SDL_SWSURFACE,
759                                             TileWidth, TileHeight,                                             TileWidth, TileHeight,
# Line 736  ShadowLayer_Alpha::ShadowLayer_Alpha() Line 765  ShadowLayer_Alpha::ShadowLayer_Alpha()
765      buffer = new Surface(ss);      buffer = new Surface(ss);
766  }  }
767    
768  ShadowLayer_Alpha::~ShadowLayer_Alpha()  DL_Shadows::~DL_Shadows()
769  {  {
770      delete_sequence(m_gridcache.begin(), m_gridcache.end());      delete_sequence(m_gridcache.begin(), m_gridcache.end());
771      delete_sequence(m_surface_avail.begin(), m_surface_avail.end());      delete_sequence(m_surface_avail.begin(), m_surface_avail.end());
# Line 744  ShadowLayer_Alpha::~ShadowLayer_Alpha() Line 773  ShadowLayer_Alpha::~ShadowLayer_Alpha()
773  }  }
774    
775  void  void
776  ShadowLayer_Alpha::new_world(int w, int h)  DL_Shadows::new_world(int w, int h)
777  {  {
778      Array2<Surface*>::iterator i;      Array2<Surface*>::iterator i;
779      for (i=m_gridcache.begin();i!=m_gridcache.end(); ++i)      for (i=m_gridcache.begin();i!=m_gridcache.end(); ++i)
# Line 754  ShadowLayer_Alpha::new_world(int w, int Line 783  ShadowLayer_Alpha::new_world(int w, int
783  }  }
784    
785  Surface *  Surface *
786  ShadowLayer_Alpha::new_surface()  DL_Shadows::new_surface()
787  {  {
788      Surface *s = 0;      Surface *s = 0;
789      if (m_surface_avail.empty()) {      if (m_surface_avail.empty()) {
# Line 772  ShadowLayer_Alpha::new_surface() Line 801  ShadowLayer_Alpha::new_surface()
801  }  }
802    
803  void  void
804  ShadowLayer_Alpha::dispose_surface(Surface *s)  DL_Shadows::dispose_surface(Surface *s)
805  {  {
806      if (s)      if (s)
807          m_surface_avail.push_back(s);          m_surface_avail.push_back(s);
# Line 780  ShadowLayer_Alpha::dispose_surface(Surfa Line 809  ShadowLayer_Alpha::dispose_surface(Surfa
809    
810    
811  Surface *  Surface *
812  ShadowLayer_Alpha::get_cache(int x, int y)  DL_Shadows::get_cache(int x, int y)
813  {  {
814      Surface *s= m_gridcache(x,y);      Surface *s= m_gridcache(x,y);
815      if (!s)      if (!s)
# Line 789  ShadowLayer_Alpha::get_cache(int x, int Line 818  ShadowLayer_Alpha::get_cache(int x, int
818  }  }
819    
820  bool  bool
821  ShadowLayer_Alpha::draw_stone_shade(GC &gc, int x, int y, Field &f)  DL_Shadows::draw_stone_shade(GC &gc, int x, int y, Field &f)
822  {  {
823      Model *m=f.layers[enigma::GRID_STONES];      Model *m=f.layers[enigma::GRID_STONES];
824      if (m)      if (m)
# Line 798  ShadowLayer_Alpha::draw_stone_shade(GC & Line 827  ShadowLayer_Alpha::draw_stone_shade(GC &
827  }  }
828    
829  void  void
830  ShadowLayer_Alpha::update (int x, int y)  DL_Shadows::update (int x, int y)
831  {  {
832      int has_sh = false;      int has_sh = false;
833    
# Line 825  ShadowLayer_Alpha::update (int x, int y) Line 854  ShadowLayer_Alpha::update (int x, int y)
854  }  }
855    
856  void  void
857  ShadowLayer_Alpha::draw(GC &gc, int xpos, int ypos, int x, int y)  DL_Shadows::draw (px::GC &gc, const WorldArea &a, int x, int y)
858    {
859        draw (gc, x, y, a.x, a. y);
860    }
861    
862    
863    void
864    DL_Shadows::draw(GC &gc, int xpos, int ypos, int x, int y)
865  {  {
866      bool has_actor = false;      bool has_actor = false;
867    
# Line 870  ShadowLayer_Alpha::draw(GC &gc, int xpos Line 906  ShadowLayer_Alpha::draw(GC &gc, int xpos
906  }  }
907    
908  void  void
909  ShadowLayer_Alpha::shadow_blit (px::Surface *scr, int x, int y,  DL_Shadows::shadow_blit (px::Surface *scr, int x, int y,
910                                  px::Surface *shadows, px::Rect r)                                  px::Surface *shadows, px::Rect r)
911  {  {
912      r.intersect(scr->size());      r.intersect(scr->size());
# Line 925  void Line 961  void
961  display::Init()  display::Init()
962  {  {
963      InitModels();      InitModels();
964      status_bar = new StatusBarImpl (inventoryarea);      gamedpy = new GameDisplay;
   
     // Initialize display engine  
     engine = new DisplayEngine (video::GetScreen());  
     engine->set_screen_area (gamearea);  
     engine->add_layer (sprite_layer = new DL_Sprites);  
     engine->add_layer (line_layer = new DL_Lines);  
     engine->add_layer (effects_layer = new DL_Sprites);  
     effects_layer->set_maxsprites(10);  
   
     SetShadowType(SHADOW_ALPHA);  
965  }  }
966    
967  void  void
968  display::Shutdown()  display::Shutdown()
969  {  {
970      active_models.clear();      active_models.clear();
971      delete status_bar;      delete gamedpy;
     delete shadow_layer;  
     delete engine;  
972    
973      ShutdownModels();      ShutdownModels();
974  }  }
975    
976  void  void display::Tick (double dtime) {
977  display::NewWorld(int w, int h)      gamedpy->tick(dtime);
 {  
     SetFollowMode(FOLLOW_NONE);  
   
     engine->new_world (w, h);  
   
     active_models.clear();  
   
     fields = FieldArray(w, h);  
     ScrollX = ScrollY = 0;  
   
     status_bar->new_world();  
     shadow_layer->new_world(w,h);  
     engine->mark_update_world();  
978  }  }
979    
980  void  StatusBar * display::GetStatusBar() {
981  display::Tick (double dtime)      return gamedpy->get_status_bar();
 {  
     engine->tick (dtime);  
   
     ModelList &am = active_models;  
     am.remove_if(mem_fun(&Model::is_garbage));  
   
     /* for_each does not work; animation may remove itself during  
        tick() */  
     for (ModelList::iterator i=am.begin(); i!=am.end(); ) {  
         ModelList::iterator n=next(i);  
         (*i)->tick(dtime);  
         i=n;  
     }  
     for_each(am.begin(), am.end(), &maybe_redraw_model);  
   
     follow_doit(dtime);  
       
     status_bar->tick (dtime);  
982  }  }
983    
984  StatusBar *  void display::NewWorld(int w, int h) {
985  display::GetStatusBar()      gamedpy->new_world (w, h);
 {  
     return status_bar;  
 }  
   
 void  
 display::SetShadowType(ShadowType st)  
 {  
     delete shadow_layer;  
     if (options::BitsPerPixel == 16)  
         shadow_layer = new ShadowLayer_Alpha;  
     else  
         shadow_layer = new ShadowLayer_Stippled;  
986  }  }
987    
988    
989  //----------------------------------------------------------------------  //----------------------------------------------------------------------
990  // Sprite following code  // Sprite following code
991  //----------------------------------------------------------------------  //----------------------------------------------------------------------
992    
 namespace  
 {  
     class Follow {  
     public:  
         virtual ~Follow() {}  
         virtual void tick(double dtime) = 0;  
         virtual void center() =0;  
     };  
   
     class Follow_Screen : public Follow {  
     public:  
         void tick(double dtime);  
         void center();  
     };  
   
     class Follow_Scrolling : public Follow {  
     public:  
         Follow_Scrolling();  
         void tick(double dtime);  
         void center();  
     private:  
         bool   currently_scrolling;  
         V2     curpos, destpos;  
         V2     dir;  
         double scrollspeed;  
         double resttime;  
     };  
 }  
   
 namespace  
 {  
     SpriteId        follow_sprite  = magic_spriteid;  
     FollowMode      follow_mode    = FOLLOW_NONE;  
     Follow         *follower       = 0;  
 }  
   
993  void  void
994  Follow_Screen::center()  Follower_Screen::center(const px::V2 &point)
995  {  {
996      tick(0);      tick(0, point);
997  }  }
998    
999  /* Determine whether the screen must be scrolled or not, and change  /* Determine whether the screen must be scrolled or not, and change
1000     the coordinate origin of the screen accordingly. */     the coordinate origin of the screen accordingly. */
1001  void  void
1002  Follow_Screen::tick(double)  Follower_Screen::tick(double, const px::V2 &point)
1003  {  {
     assert(follow_sprite != magic_spriteid);  
     Sprite *s = sprite_layer->sprites[follow_sprite];  
   
1004      for (;;) {      for (;;) {
1005          int sx, sy;          int sx, sy;
1006          engine->world_to_screen(s->pos, &sx, &sy);          engine->world_to_screen(point, &sx, &sy);
1007    
1008          V2 screenoff = engine->get_offset();          V2 screenoff = engine->get_offset();
1009    
# Line 1085  Follow_Screen::tick(double) Line 1028  Follow_Screen::tick(double)
1028    
1029    
1030    
1031  Follow_Scrolling::Follow_Scrolling()  Follower_Scrolling::Follower_Scrolling()
1032      : currently_scrolling(false),  : currently_scrolling(false),
1033        scrollspeed(0), resttime(0)    scrollspeed(0), resttime(0)
1034  {}  {}
1035    
1036  void  void
1037  Follow_Scrolling::center()  Follower_Scrolling::center(const px::V2 &point)
1038  {  {
1039      tick(1000);      tick(1000, point);
1040      tick(1000);      tick(1000, point);
1041  }  }
1042    
1043  void  void
1044  Follow_Scrolling::tick(double dtime)  Follower_Scrolling::tick(double dtime, const px::V2 &point)
1045  {  {
     assert(follow_sprite != magic_spriteid);  
     Sprite *s = sprite_layer->sprites[follow_sprite];  
   
     V2 spritepos (s->pos[0], s->pos[1]);  
   
1046      int sx, sy;      int sx, sy;
1047      engine->world_to_screen(s->pos, &sx, &sy);      engine->world_to_screen(point, &sx, &sy);
1048    
1049      if (currently_scrolling) {      if (currently_scrolling) {
1050          resttime -= dtime;          resttime -= dtime;
# Line 1129  Follow_Scrolling::tick(double dtime) Line 1067  Follow_Scrolling::tick(double dtime)
1067          {          {
1068              currently_scrolling = true;              currently_scrolling = true;
1069              curpos = V2(ScrollX, ScrollY);              curpos = V2(ScrollX, ScrollY);
1070              destpos = curpos + spritepos - V2(ScrollX+gamearea.w/TileWidth/2,              destpos = curpos + point - V2(ScrollX+gamearea.w/TileWidth/2,
1071                                                ScrollY+gamearea.h/TileHeight/2);                                            ScrollY+gamearea.h/TileHeight/2);
1072              destpos[0] = int(destpos[0]*TileWidth)/TileWidth;              destpos[0] = int(destpos[0]*TileWidth)/TileWidth;
1073              destpos[1] = int(destpos[1]*TileHeight)/TileHeight;              destpos[1] = int(destpos[1]*TileHeight)/TileHeight;
1074              destpos[0] = max(0, min((int) destpos[0],              destpos[0] = max(0, min((int) destpos[0],
# Line 1149  Follow_Scrolling::tick(double dtime) Line 1087  Follow_Scrolling::tick(double dtime)
1087      }      }
1088  }  }
1089    
1090  static void  void display::FollowSprite(SpriteId id) {
1091  follow_doit(double dtime)      gamedpy->set_follow_sprite (id);
 {  
     if (follow_sprite != magic_spriteid) {  
         follower->tick(dtime);  
     }  
 }  
   
 static void  
 follow_center()  
 {  
     if (follow_mode == FOLLOW_NONE)  
         SetFollowMode(FOLLOW_SCREEN);  
     if (follow_sprite != magic_spriteid) {  
         follower->center();  
     }  
 }  
   
 static void  
 set_follower (Follow *f)  
 {  
     delete follower;  
     follower = f;  
 }  
   
   
 void  
 display::FollowSprite(SpriteId id)  
 {  
     follow_sprite = id;  
     follow_center();  
1092  }  }
1093    
1094    FollowMode display::SetFollowMode(FollowMode m) {
1095  FollowMode      return gamedpy->set_follow_mode(m);
 display::SetFollowMode(FollowMode m)  
 {  
     FollowMode old=follow_mode;  
     if (m != follow_mode)  
     {  
         follow_mode = m;  
         switch (follow_mode) {  
         case FOLLOW_NONE:        
             set_follower(0);  
             break;  
         case FOLLOW_SCROLLING:  
             set_follower (new Follow_Scrolling);  
             break;  
         case FOLLOW_SCREEN:      
             set_follower (new Follow_Screen);  
             break;  
         };  
     }  
     return old;  
1096  }  }
1097    
1098  //----------------------------------------  //----------------------------------------
1099  // Handling active models  // Handling active models
1100  //----------------------------------------  //----------------------------------------
1101    
1102  Model*  Model *
1103  display::SetModel(const GridLoc &l, Model *m)  CommonDisplay::set_model (const GridLoc &l, Model *m)
1104  {  {
1105      int x = l.pos.x, y=l.pos.y;      int x = l.pos.x, y=l.pos.y;
1106    
1107        switch (l.layer) {
1108        case GRID_FLOOR: floor_layer->set_model (x, y, m); break;
1109        case GRID_ITEMS: item_layer->set_model (x, y, m); break;
1110        case GRID_STONES:
1111            stone_layer->set_model (x, y, m);
1112    //        shadow_layer->set_model (x, y, m);
1113            break;
1114        case GRID_COUNT: break;
1115        }
1116      Field& f = fields(x, y);      Field& f = fields(x, y);
     delete f.layers[l.layer];  
1117      f.layers[l.layer] = m;      f.layers[l.layer] = m;
1118      if (m)      if (m)
1119          m->activate(double(x), double(y), false);          m->activate(double(x), double(y), false);
1120      mark_change(l);  //    mark_change(l);
1121      return m;      return m;
1122  }  }
1123    
1124  Model *  Model *
1125  display::SetModel(const GridLoc &l, const string &modelname)  CommonDisplay::get_model (const GridLoc &l)
1126  {  {
1127      return SetModel(l, MakeModel(modelname));      int x = l.pos.x, y=l.pos.y;
1128        switch (l.layer) {
1129        case GRID_FLOOR: return floor_layer->get_model (x, y);
1130        case GRID_ITEMS: return item_layer->get_model (x, y);
1131        case GRID_STONES: return stone_layer->get_model (x, y);
1132        case GRID_COUNT: return 0;
1133        }
1134        return 0;
1135  }  }
1136    
1137  void  Model *
1138  display::KillModel(const GridLoc & l)  CommonDisplay::yield_model (const GridLoc &l)
1139  {  {
1140        int x = l.pos.x, y=l.pos.y;
1141        fields(x, y).layers[l.layer] = 0;
1142        switch (l.layer) {
1143        case GRID_FLOOR: return floor_layer->yield_model (x, y);
1144        case GRID_ITEMS: return item_layer->yield_model (x, y);
1145        case GRID_STONES: return stone_layer->yield_model (x, y);
1146        case GRID_COUNT: return 0;
1147        }
1148        return 0;
1149    }
1150    
1151    Model *display::SetModel (const GridLoc &l, Model *m) {
1152        return gamedpy->set_model (l, m);
1153    }
1154    
1155    Model *display::SetModel (const GridLoc &l, const string &modelname) {
1156        return SetModel(l, MakeModel(modelname));
1157    }
1158    
1159    void display::KillModel(const GridLoc & l) {
1160      delete YieldModel(l);      delete YieldModel(l);
1161  }  }
1162    
1163  Model *  Model *display::GetModel(const GridLoc &l) {
1164  display::GetModel(const GridLoc &l)      return gamedpy->get_model (l);
 {  
     Field& f = fields(l.pos.x, l.pos.y);  
     return f.layers[l.layer];  
1165  }  }
1166    
1167  Model *  Model *display::YieldModel(const GridLoc &l) {
1168  display::YieldModel(const GridLoc &l)      return gamedpy->yield_model (l);
 {  
     Field& f = fields(l.pos.x, l.pos.y);  
     Model *m = f.layers[l.layer];  
     f.layers[l.layer] = 0;  
     mark_change(l);  
     return m;  
1169  }  }
1170    
1171  void  void
1172  display::AddEffect (const V3& pos, const char *modelname)  display::AddEffect (const V3& pos, const char *modelname)
1173  {  {
1174      Model *m = modelname ? MakeModel(modelname) : 0;      gamedpy->add_effect (pos, MakeModel(modelname));
     effects_layer->add_sprite(new Sprite (pos, SPRITE_EFFECT, m));  
1175  }  }
1176    
1177  SpriteId  SpriteId
# Line 1312  display::ToggleFlag(DisplayFlags flag) Line 1228  display::ToggleFlag(DisplayFlags flag)
1228      display_flags = DisplayFlags(display_flags ^ flag);      display_flags = DisplayFlags(display_flags ^ flag);
1229  }  }
1230    
1231  static Uint32 last_frame_time = 0;  void display::DrawAll (GC &gc) {
1232        gamedpy->draw_all(gc);
1233    }
1234    
1235    void display::RedrawAll(Screen *screen) {
1236        gamedpy->redraw_all(screen);
1237    }
1238    
1239    void display::Redraw(Screen *screen) {
1240        gamedpy->redraw(screen);
1241    }
1242    
1243    
1244    
1245    //----------------------------------------------------------------------
1246    // Game Display Engine
1247    //----------------------------------------------------------------------
1248    
1249    GameDisplay::GameDisplay()
1250    : last_frame_time (0),
1251      redraw_everything(false),
1252      follow_sprite (magic_spriteid),
1253      follow_mode (FOLLOW_NONE),
1254      follower (0),
1255      inventoryarea(0, 480-64, 640, 64)
1256    {
1257        status_bar = new StatusBarImpl (inventoryarea);
1258    
1259        // Initialize display engine
1260        engine = new DisplayEngine (video::GetScreen());
1261        engine->set_screen_area (gamearea);
1262    
1263        engine->add_layer (floor_layer = new DL_Grid);
1264        engine->add_layer (item_layer = new DL_Grid);
1265        engine->add_layer (shadow_layer = new DL_Shadows(0,0));
1266        engine->add_layer (sprite_layer = new DL_Sprites);
1267        engine->add_layer (stone_layer = new DL_Grid);
1268        engine->add_layer (line_layer = new DL_Lines);
1269        engine->add_layer (effects_layer = new DL_Sprites);
1270        effects_layer->set_maxsprites(10);
1271    }
1272    
1273    GameDisplay::~GameDisplay()
1274    {
1275        delete status_bar;
1276        delete engine;
1277    }
1278    
1279    void
1280    GameDisplay::tick(double dtime)
1281    {
1282        engine->tick (dtime);
1283        status_bar->tick (dtime);
1284    
1285        ModelList &am = active_models;
1286        am.remove_if(mem_fun(&Model::is_garbage));
1287    
1288        /* for_each does not work; animation may remove itself during
1289           tick() */
1290        for (ModelList::iterator i=am.begin(); i!=am.end(); ) {
1291            ModelList::iterator n=next(i);
1292            (*i)->tick(dtime);
1293            i=n;
1294        }
1295        for_each(am.begin(), am.end(), &maybe_redraw_model);
1296    
1297    
1298        if (follow_sprite != magic_spriteid) {
1299            V3 point = sprite_layer->sprites[follow_sprite]->pos;
1300            follower->tick(dtime, V2(point[0], point[1]));
1301        }
1302    }
1303    
1304    void
1305    GameDisplay::new_world (int w, int h)
1306    {
1307        active_models.clear();
1308    
1309        status_bar->new_world();
1310        SetFollowMode(FOLLOW_NONE);
1311    
1312        fields = FieldArray(w, h);
1313        engine->new_world (w, h);
1314        shadow_layer->new_world(w,h);
1315        engine->mark_update_world();
1316    
1317    
1318        ScrollX = ScrollY = 0;
1319    }
1320    
1321    StatusBar *
1322    GameDisplay::get_status_bar() const
1323    {
1324        return status_bar;
1325    }
1326    
1327    //----------------------------------------
1328    // Scrolling
1329    //----------------------------------------
1330    
1331    
1332    FollowMode
1333    GameDisplay::set_follow_mode (FollowMode m)
1334    {
1335        FollowMode old=follow_mode;
1336        if (m != follow_mode)
1337        {
1338            follow_mode = m;
1339            switch (follow_mode) {
1340            case FOLLOW_NONE:      
1341                set_follower(0);
1342                break;
1343            case FOLLOW_SCROLLING:
1344                set_follower (new Follower_Scrolling);
1345                break;
1346            case FOLLOW_SCREEN:    
1347                set_follower (new Follower_Screen);
1348                break;
1349            };
1350        }
1351        return old;
1352    }
1353    
1354  void  void
1355  display::DrawAll (GC &gc)  GameDisplay::set_follower (Follower *f)
1356  {  {
1357      engine->draw_all(gc);      delete follower;
1358      status_bar->redraw (gc, inventoryarea);      follower = f;
1359  }  }
1360    
1361  void  void
1362  display::RedrawAll(Screen *scr)  GameDisplay::follow_center()
1363  {  {
1364      engine->mark_redraw_screen();      if (follow_mode == FOLLOW_NONE)
1365      RedrawEverything = true;          set_follow_mode (FOLLOW_SCREEN);
1366      Redraw(scr);      if (follow_sprite != magic_spriteid) {
1367            V3 point = sprite_layer->sprites[follow_sprite]->pos;
1368            follower->center (V2(point[0], point[1]));
1369        }
1370  }  }
1371    
1372  void  void
1373  display::Redraw(Screen *screen)  GameDisplay::set_follow_sprite(SpriteId id)
1374    {
1375        follow_sprite = id;
1376        follow_center();
1377    }
1378    
1379    //----------------------------------------
1380    // Screen updates
1381    //----------------------------------------
1382    
1383    void
1384    GameDisplay::redraw_all(Screen *scr)
1385    {
1386        engine->mark_redraw_screen();
1387        redraw_everything = true;
1388        redraw (scr);
1389    }
1390    
1391    void
1392    GameDisplay::redraw(px::Screen *screen)
1393  {  {
1394      GC gc(screen);      GC gc(screen);
1395    
1396      engine->update_screen();      engine->update_screen();
1397      if (status_bar->has_changed() || RedrawEverything) {      if (status_bar->has_changed() || redraw_everything) {
1398          status_bar->redraw (gc, inventoryarea);          status_bar->redraw (gc, inventoryarea);
1399          screen->update_rect(inventoryarea);          screen->update_rect(inventoryarea);
1400      }      }
# Line 1354  display::Redraw(Screen *screen) Line 1413  display::Redraw(Screen *screen)
1413          screen->update_rect(area);          screen->update_rect(area);
1414      }      }
1415      screen->flush_updates();      screen->flush_updates();
1416      RedrawEverything = false;      redraw_everything = false;
1417    }
1418    
1419    void
1420    GameDisplay::draw_all (GC &gc)
1421    {
1422        engine->draw_all(gc);
1423        status_bar->redraw (gc, inventoryarea);
1424  }  }
1425    

Legend:
Removed from v.1.12  
changed lines
  Added in v.1.13

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26