/[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.14 by dheck, Wed Mar 5 22:05:02 2003 UTC revision 1.15 by dheck, Thu Mar 13 17:58:33 2003 UTC
# Line 19  Line 19 
19   */   */
20    
21  /*  /*
22   * This file contains the code renders the graphics during the game.   * This file contains the code renders the graphics during the game
23   * This includes displaying the current landscape with all its objects   * and in the editor.  This includes displaying the current landscape
24   * and the inventory at the bottom of the screen.   * with all its objects and the inventory at the bottom of the screen.
25   */   */
26    
27  #include "display.hh"  #include "display.hh"
# Line 31  Line 31 
31    
32  #include "px/sdl.hh"  #include "px/sdl.hh"
33  #include "px/px.hh"  #include "px/px.hh"
34    #include "px/tools.hh"
35    
36  #include <vector>  #include <vector>
37  #include <algorithm>  #include <algorithm>
# Line 45  using namespace display; Line 46  using namespace display;
46  using namespace enigma;  using namespace enigma;
47    
48  #include "d_engine.hh"  #include "d_engine.hh"
49    #include "d_models.hh"
50  #include "d_statusbar.hh"  #include "d_statusbar.hh"
51    
52  //----------------------------------------  //----------------------------------------
# Line 67  static int TileWidth = 32; Line 69  static int TileWidth = 32;
69  static int TileHeight = 32;  static int TileHeight = 32;
70    
71  static GameDisplay   *gamedpy = 0;  static GameDisplay   *gamedpy = 0;
 // static DisplayEngine *engine  = 0;  
   
 static DL_Lines   *line_layer    = 0;  
 static DL_Sprites *sprite_layer  = 0;  
 static DL_Shadows *shadow_layer  = 0;  
   
 namespace  
 {  
     const SpriteId  MAGIC_SPRITEID = 1000000;  
   
     // Do not change the order of the following two variables!  
     FieldArray      fields(0,0);  
   
     // Screen layout  
 }  
   
   
 //----------------------------------------------------------------------  
 // HELPER FUNCTIONS  
 //----------------------------------------------------------------------  
   
 void  
 ModelLayer::maybe_redraw_model(Model *m)  
 {  
     WorldArea wa;  
     if (m->has_changed(wa)) {  
         get_engine()->mark_update_area(wa);  
     }  
 }  
   
 void  
 ModelLayer::activate (Model *m)  
 {  
     list<Model*> &am = m_active_models;  
     if (find(am.begin(), am.end(), m) == am.end())  
         am.push_back(m);  
 }  
   
 void  
 ModelLayer::new_world (int, int)  
 {  
     m_active_models.clear();  
 }  
   
 void  
 ModelLayer::deactivate (Model *m)  
 {  
     m_active_models.remove(m);  
 }  
   
 void  
 ModelLayer::tick (double dtime)  
 {  
     ModelList &am = m_active_models;  
     am.remove_if(mem_fun(&Model::is_garbage));  
   
     /* for_each does not work; animation may remove itself during a  
        tick.  This may happen for example when a model callback  
        decides to replace the old model by another one.  */  
     for (ModelList::iterator i=am.begin(); i!=am.end(); ) {  
         ModelList::iterator n=next(i);  
         (*i)->tick(dtime);  
         i=n;  
     }  
     for (ModelList::iterator i=am.begin(); i!=am.end(); ++i) {  
         maybe_redraw_model (*i);  
     }  
 }  
72    
73    
74  //======================================================================  //======================================================================
# Line 222  DisplayEngine::new_world (int w, int h) Line 156  DisplayEngine::new_world (int w, int h)
156      m_width = w;      m_width = w;
157      m_height = h;      m_height = h;
158      m_offset = V2();      m_offset = V2();
159      m_fields = Field2Array(w, h);      m_fields.resize(w, h);
160            
161      for (unsigned i=0; i<m_layers.size(); ++i)      for (unsigned i=0; i<m_layers.size(); ++i)
162          m_layers[i]->new_world(w,h);          m_layers[i]->new_world(w,h);
# Line 239  DisplayEngine::tick (double dtime) Line 173  DisplayEngine::tick (double dtime)
173  }  }
174    
175  void  void
 DisplayEngine::world_to_screen (const V3 & pos, int *x, int *y)  
 {  
     *x = int((pos[0] - m_offset[0])*m_tilew);  
     *y = int((pos[1] - m_offset[1])*m_tileh);  
 }  
   
 void  
176  DisplayEngine::world_to_screen (const V2 & pos, int *x, int *y)  DisplayEngine::world_to_screen (const V2 & pos, int *x, int *y)
177  {  {
178      *x = int((pos[0] - m_offset[0])*m_tilew);      *x = int((pos[0] - m_offset[0])*m_tilew);
# Line 264  DisplayEngine::world_to_screen (const Wo Line 191  DisplayEngine::world_to_screen (const Wo
191  WorldArea  WorldArea
192  DisplayEngine::screen_to_world (const ScreenArea &a)  DisplayEngine::screen_to_world (const ScreenArea &a)
193  {  {
     int worldw = m_width;  
     int worldh = m_height;  
   
194      int sx = int(m_offset[0] * m_tilew);      int sx = int(m_offset[0] * m_tilew);
195      int sy = int(m_offset[1] * m_tileh);      int sy = int(m_offset[1] * m_tileh);
196    
197      int x1 = Max(0, (sx + a.x) / m_tilew);      int x1 = Max(0, (sx + a.x) / m_tilew);
198      int y1 = Max(0, (sy + a.y) / m_tileh);      int y1 = Max(0, (sy + a.y) / m_tileh);
199      int x2 = Min(worldw, (sx + a.x+a.w+m_tilew-1) / m_tilew);      int x2 = Min(m_width, (sx + a.x+a.w+m_tilew-1) / m_tilew);
200      int y2 = Min(worldh, (sy + a.y+a.h+m_tileh-1) / m_tileh);      int y2 = Min(m_height, (sy + a.y+a.h+m_tileh-1) / m_tileh);
201    
202      return WorldArea (x1, y1, x2-x1, y2-y1);      return WorldArea (x1, y1, x2-x1, y2-y1);
203  }  }
204    
205    V2
206    DisplayEngine::to_screen (const V2 &pos)
207    {
208        return V2 ((pos[0] - m_offset[0])*m_tilew,
209                   (pos[1] - m_offset[1])*m_tileh);
210    }
211    
212    V2
213    DisplayEngine::to_world (const V2 &pos)
214    {
215        return V2(pos[0]/m_tilew, pos[1]/m_tileh) + m_offset;
216    }
217    
218  void  void
219  DisplayEngine::mark_redraw_area (const WorldArea &wa)  DisplayEngine::mark_redraw_area (const WorldArea &wa)
220  {  {
# Line 333  DisplayEngine::draw_all (px::GC &gc) Line 270  DisplayEngine::draw_all (px::GC &gc)
270          for (int y=wa.y; y<y2; y++) {          for (int y=wa.y; y<y2; y++) {
271              Field2 &f2 = m_fields(x,y);              Field2 &f2 = m_fields(x,y);
272              if (f2.updatep) {              if (f2.updatep) {
273                  shadow_layer->update(x,y);  //                 shadow_layer->update(x,y);
274                  f2.redrawp = true;                  f2.redrawp = true;
275                  f2.updatep = false;                  f2.updatep = false;
276              }              }
# Line 346  DisplayEngine::draw_all (px::GC &gc) Line 283  DisplayEngine::draw_all (px::GC &gc)
283              draw_field(gc, x,y);              draw_field(gc, x,y);
284          }          }
285      }      }
     line_layer->draw_lines (gc);  
286  }  }
287    
288  void  void
# Line 358  DisplayEngine::update_screen() Line 294  DisplayEngine::update_screen()
294      clip(gc, area);      clip(gc, area);
295      WorldArea wa = screen_to_world (area);      WorldArea wa = screen_to_world (area);
296    
297      int x2 = wa.x+wa.w;      // Fill screen area not covered by world
298      int y2 = wa.y+wa.h;      {
299      for (int x=wa.x; x<x2; x++) {          RectList rl;
300          for (int y=wa.y; y<y2; y++) {          rl.push_back (get_area());
301            rl.sub (world_to_screen (WorldArea (0,0, m_width, m_height)));
302            set_color (gc, 200, 0, 200);
303            for (RectList::iterator i=rl.begin(); i!=rl.end(); ++i)
304            {
305                box (gc, *i);
306                m_screen->update_rect (*i);
307            }
308        }
309    
310    
311        int x2 = Min(m_width, wa.x+wa.w);
312        int y2 = Min(m_height, wa.y+wa.h);
313        for (int x=Max(0, wa.x); x<x2; x++) {
314            for (int y=Max(0,wa.y); y<y2; y++) {
315              Field2 &f2 = m_fields(x,y);              Field2 &f2 = m_fields(x,y);
316              if (f2.updatep) {              if (f2.updatep) {
317                  shadow_layer->update(x,y);  //                 shadow_layer->update(x,y);
318                  f2.redrawp = true;                  f2.redrawp = true;
319                  f2.updatep = false;                  f2.updatep = false;
320              }              }
# Line 381  DisplayEngine::update_screen() Line 331  DisplayEngine::update_screen()
331              }              }
332          }          }
333      }      }
     line_layer->draw_lines (gc);  
334  }  }
335    
336    
337  //----------------------------------------------------------------------  //----------------------------------------------------------------------
338    // Model layer
339    //----------------------------------------------------------------------
340    
341    void
342    ModelLayer::maybe_redraw_model(Model *m)
343    {
344        WorldArea wa;
345        if (m->has_changed(wa)) {
346            get_engine()->mark_update_area(wa);
347        }
348    }
349    
350    void
351    ModelLayer::activate (Model *m)
352    {
353        list<Model*> &am = m_active_models;
354        if (find(am.begin(), am.end(), m) == am.end())
355            am.push_back(m);
356    }
357    
358    void
359    ModelLayer::new_world (int, int)
360    {
361        m_active_models.clear();
362    }
363    
364    void
365    ModelLayer::deactivate (Model *m)
366    {
367        m_active_models.remove(m);
368    }
369    
370    void
371    ModelLayer::tick (double dtime)
372    {
373        ModelList &am = m_active_models;
374        am.remove_if(mem_fun(&Model::is_garbage));
375    
376        /* for_each does not work; animation may remove itself during a
377           tick.  This may happen for example when a model callback
378           decides to replace the old model by another one.  */
379        for (ModelList::iterator i=am.begin(); i!=am.end(); ) {
380            ModelList::iterator n=next(i);
381            (*i)->tick(dtime);
382            i=n;
383        }
384        for (ModelList::iterator i=am.begin(); i!=am.end(); ++i) {
385            maybe_redraw_model (*i);
386        }
387    }
388    
389    
390    //----------------------------------------------------------------------
391    // Grid Layer
392    //----------------------------------------------------------------------
393    
394    DL_Grid::DL_Grid()
395    : m_models (0, 0)
396    {
397    }
398    
399    DL_Grid::~DL_Grid()
400    {
401        delete_sequence (m_models.begin(), m_models.end());
402    }
403    
404    void
405    DL_Grid::new_world (int w, int h)
406    {
407        ModelLayer::new_world (w, h);
408        delete_sequence (m_models.begin(), m_models.end());
409        m_models.resize (w, h, 0);
410    }
411    
412    void
413    DL_Grid::mark_update (int x, int y)
414    {
415        get_engine()->mark_update_area (WorldArea (x, y, 2, 2));
416    }
417    
418    void
419    DL_Grid::set_model (int x, int y, Model *m)
420    {
421        if (!(x >= 0 && y >= 0 &&
422              (unsigned)x<m_models.width() &&
423              (unsigned)y<m_models.height()))
424        {
425            cout << "ouch, trying to set model somewhere it doesn't belong.\n";
426            delete m;
427            return;
428        }
429    
430        if (m_models(x,y) != m) {
431            if (Model *mm = m_models(x,y)) {
432                mm->remove(this);
433                delete mm;
434            }
435            m_models(x,y) = m;
436            mark_update(x,y);
437            if (m)
438                m->expose (this, V2(x, y));
439        }
440    }
441    
442    Model *
443    DL_Grid::get_model (int x, int y)
444    {
445        return m_models(x,y);
446    }
447    
448    Model *
449    DL_Grid::yield_model (int x, int y)
450    {
451        Model *m = get_model (x, y);
452        if (m)
453            m->remove (this);
454        m_models(x,y) = 0;
455        mark_update(x,y);
456        return m;
457    }
458    
459    
460    void
461    DL_Grid::draw (px::GC &gc, const WorldArea &a, int destx, int desty)
462    {
463        int x2 = a.x+a.w;
464        int y2 = a.y+a.h;
465        for (int x=a.x; x<x2; ++x)
466            for (int y=a.y; y<y2; ++y)
467                if (Model *m = m_models(x,y))
468                    m->draw(gc, destx, desty);
469    }
470    
471    
472    
473    //======================================================================
474  // SPRITES  // SPRITES
475    //======================================================================
476    
477    void
478    SpriteHandle::kill()
479    {
480        layer->kill_sprite (id);
481        layer = 0;
482        id = 0;
483    }
484    
485    void
486    SpriteHandle::move (const px::V2 &newpos) const
487    {
488        if (layer)
489            layer->move_sprite (id, newpos);
490    }
491    
492    void
493    SpriteHandle::replace_model (Model *m) const
494    {
495        if (layer)
496            layer->replace_sprite (id, m);
497        else
498            delete m;
499    }
500    
501    Model *
502    SpriteHandle::get_model () const
503    {
504        return layer ? layer->get_model (id) : 0;
505    }
506    
507    void
508    SpriteHandle::set_callback (ModelCallback *cb) const
509    {
510        if (Model *m = get_model())
511            m->set_callback(cb);
512    }
513    
514    //----------------------------------------------------------------------
515    // Sprite layer
516  //----------------------------------------------------------------------  //----------------------------------------------------------------------
517    
518  DL_Sprites::DL_Sprites()  DL_Sprites::DL_Sprites()
# Line 398  DL_Sprites::~DL_Sprites() Line 524  DL_Sprites::~DL_Sprites()
524      delete_sequence(sprites.begin(), sprites.end());      delete_sequence(sprites.begin(), sprites.end());
525  }  }
526    
   
527  void  void
528  DL_Sprites::new_world (int w, int h)  DL_Sprites::new_world (int w, int h)
529  {  {
530        ModelLayer::new_world (w,h);
531      delete_sequence (sprites.begin(), sprites.end());      delete_sequence (sprites.begin(), sprites.end());
532      sprites.clear();      sprites.clear();
533      numsprites = 0;      numsprites = 0;
     ModelLayer::new_world (w,h);  
534  }  }
535    
536  void  void
537  DL_Sprites::move_sprite (SpriteId id, const px::V3& newpos)  DL_Sprites::move_sprite (SpriteId id, const px::V2& newpos)
538  {  {
     if (id == MAGIC_SPRITEID)  
         return;  
539      Sprite *sprite = sprites[id];      Sprite *sprite = sprites[id];
540    
541      int oldx, oldy;      int oldx, oldy;
# Line 437  DL_Sprites::add_sprite (Sprite *sprite) Line 560  DL_Sprites::add_sprite (Sprite *sprite)
560      }      }
561    
562      SpriteList &sl = sprites;      SpriteList &sl = sprites;
563      SpriteId id = MAGIC_SPRITEID;      SpriteId id = 0;
564    
565      // Find the first empty slot      // Find the first empty slot
566      SpriteList::iterator i = find(sl.begin(), sl.end(), (Sprite*)0);      SpriteList::iterator i = find(sl.begin(), sl.end(), (Sprite*)0);
# Line 449  DL_Sprites::add_sprite (Sprite *sprite) Line 572  DL_Sprites::add_sprite (Sprite *sprite)
572          id = distance(sl.begin(), i);          id = distance(sl.begin(), i);
573          *i = sprite;          *i = sprite;
574      }      }
575      if (Model *m = sprite->model) {      if (Model *m = sprite->model)
576          m->expose (this, V2 (sprite->pos[0], sprite->pos[1]));          m->expose (this, V2 (sprite->pos[0], sprite->pos[1]));
     }  
577      redraw_sprite_region(id);      redraw_sprite_region(id);
578      numsprites += 1;      numsprites += 1;
579      return id;      return id;
# Line 460  DL_Sprites::add_sprite (Sprite *sprite) Line 582  DL_Sprites::add_sprite (Sprite *sprite)
582  void  void
583  DL_Sprites::replace_sprite (SpriteId id, Model *m)  DL_Sprites::replace_sprite (SpriteId id, Model *m)
584  {  {
     if (id == MAGIC_SPRITEID) {  
         delete m;  
         return;  
     }  
   
585      Sprite *sprite = sprites[id];      Sprite *sprite = sprites[id];
586    
587      if (Model *m = sprite->model) {      if (Model *m = sprite->model) {
# Line 481  DL_Sprites::replace_sprite (SpriteId id, Line 598  DL_Sprites::replace_sprite (SpriteId id,
598  void  void
599  DL_Sprites::kill_sprite (SpriteId id)  DL_Sprites::kill_sprite (SpriteId id)
600  {  {
     if (id == MAGIC_SPRITEID)  
         return;  
601      if (Sprite *sprite = sprites[id]) {      if (Sprite *sprite = sprites[id]) {
602          if (Model *m = sprite->model) {          if (Model *m = sprite->model) {
603              m->remove (this);              m->remove (this);
# Line 538  DL_Sprites::redraw_sprite_region (Sprite Line 653  DL_Sprites::redraw_sprite_region (Sprite
653    
654    
655  //----------------------------------------------------------------------  //----------------------------------------------------------------------
 // GRID LAYER  
 //----------------------------------------------------------------------  
   
 DL_Grid::DL_Grid()  
 {  
 }  
   
 void  
 DL_Grid::new_world (int w, int h)  
 {  
     m_models = ModelArray (w, h);  
     ModelLayer::new_world (w, h);  
 }  
   
 void  
 DL_Grid::mark_update (int x, int y)  
 {  
     get_engine()->mark_update_area (WorldArea (x, y, 2, 2));  
 }  
   
 void  
 DL_Grid::set_model (int x, int y, Model *m)  
 {  
     if (m_models(x,y) != m) {  
         if (Model *mm = m_models(x,y)) {  
             mm->remove(this);  
             delete mm;  
         }  
         m_models(x,y) = m;  
         mark_update(x,y);  
         if (m)  
             m->expose (this, V2(x, y));  
     }  
 }  
   
 Model *  
 DL_Grid::get_model (int x, int y)  
 {  
     return m_models(x,y);  
 }  
   
 Model *  
 DL_Grid::yield_model (int x, int y)  
 {  
     Model *m = m_models(x,y);  
     m_models(x,y) = 0;  
     mark_update(x,y);  
     return m;  
 }  
   
   
 void  
 DL_Grid::draw (px::GC &gc, const WorldArea &a, int destx, int desty)  
 {  
     int x2 = a.x+a.w;  
     int y2 = a.y+a.h;  
     for (int x=a.x; x<x2; ++x)  
         for (int y=a.y; y<y2; ++y)  
             if (Model *m = m_models(x,y))  
                 m->draw(gc, destx, desty);  
 }  
   
   
   
 //----------------------------------------------------------------------  
656  // RUBBER BANDS  // RUBBER BANDS
657  //----------------------------------------------------------------------  //----------------------------------------------------------------------
658    
# Line 691  DL_Lines::add_line (const V2 &p1, const Line 741  DL_Lines::add_line (const V2 &p1, const
741  {  {
742      m_rubbers[m_id] = Line(p1, p2);      m_rubbers[m_id] = Line(p1, p2);
743      mark_redraw_line (m_rubbers[m_id]);      mark_redraw_line (m_rubbers[m_id]);
744      return RubberHandle(m_id++);      return RubberHandle(this, m_id++);
745  }  }
746    
747  void  void
# Line 719  DL_Lines::kill_line (unsigned id) Line 769  DL_Lines::kill_line (unsigned id)
769          m_rubbers.erase(i);          m_rubbers.erase(i);
770  }  }
771    
772    RubberHandle::RubberHandle(DL_Lines *ll, unsigned id_)
773  RubberHandle  : line_layer (ll), id(id_)
 display::AddRubber (const V2 &p1, const V2 &p2)  
 {  
     return line_layer->add_line (p1, p2);  
 }  
   
   
 RubberHandle::RubberHandle(unsigned id_): id(id_)  
774  {  {
775  }  }
776    
# Line 751  void RubberHandle::kill() Line 794  void RubberHandle::kill()
794  // SHADOWS  // SHADOWS
795  //----------------------------------------------------------------------  //----------------------------------------------------------------------
796    
797  DL_Shadows::DL_Shadows(DL_Grid *grid, DL_Sprites *sprites)  /*
798  : m_grid(grid), m_sprites(sprites),  ** Drawing the shadows is a lot more difficult than drawing any of the
799    m_gridcache()  ** other layers.  There are a couple of reasons for this:
800    **
801    ** 1. Both Stones and actors cast a shadow.  Not a real problem, but
802    **    it makes the implementation more complex.
803    **
804    ** 2. Shadows can overlap.  Not only can the shadows of stones and
805    **    actors overlap, but also the shadows of two adjacent stones can.
806    **    Since we are using alpha blending for the shadows, this means
807    **    that we cannot blit the invidual shadows to the screen, but we
808    **    have to use a intermediate buffer.
809    **
810    ** 3. Performance is critical.  Drawing the shadows is time-consuming,
811    **    firstly because alpha blending is costly and secondly because of
812    **    the intermediate buffer.  So we should try to cache shadows *and*
813    **    avoid the buffer if possible.
814    **
815    ** So, how do we approach these problems? We handle stone and actor
816    ** shadows separately: The stone shadows do not change very often so
817    ** it's easy to cache them, one tile at a time.  If there is no actor
818    ** on this tile, we can blit the cached image directly to the screen,
819    ** otherwise we have no choice but to use buffer.
820    **
821    ** The remaining problem is the shadow cache.  The easiest solution
822    ** would be to use one huge image for the whole level and keep it in
823    ** memory all the time.  But then the cache would consume roughly 20mb
824    ** for a 100x100 landscape.  That is excessive, considering that there
825    ** are probably no more than 40 different shadow tiles in each
826    ** landscape.
827    */
828    
829    namespace display
830  {  {
831      SDL_Surface *ss = SDL_CreateRGBSurface(SDL_SWSURFACE,      struct ImageQuad {
832                                             TileWidth, TileHeight,          Image *images[4];
833                                             video::GetColorDepth(),  
834                                             0,0,0,0);          ImageQuad() { /* do not initialize fields. */ }
835      SDL_SetColorKey(ss, SDL_SRCCOLORKEY,  
836                      SDL_MapRGB(ss->format, 255,255,255));          ImageQuad (Image *i1, Image *i2, Image *i3, Image *i4) {
837      SDL_SetAlpha(ss, SDL_SRCALPHA, 128);              images[0] = i1;
838      buffer = new Surface(ss);              images[1] = i2;
839                images[2] = i3;
840                images[3] = i4;
841            }
842            bool operator == (const ImageQuad &q) {
843                return (images[0]==q.images[0] &&
844                        images[1]==q.images[1] &&
845                        images[2]==q.images[2] &&
846                        images[3]==q.images[3]);
847            }
848            Image *operator[] (int idx) { return images[idx]; }
849        };
850    
851        inline bool is_image (Model *m) {
852            return m==0 || dynamic_cast<ImageModel*>(m);
853        }
854    
855        inline bool only_images (Model *models[4], ImageQuad &q) {
856            int nimages=4;
857    
858            for (int i=0; i<4; ++i) {
859                if (models[i] == 0)
860                    q.images[i] = 0;
861                else if (ImageModel *im = dynamic_cast<ImageModel*>(models[i]))
862                    q.images[i] = im->get_image();
863                else
864                    nimages--;
865            }
866            return nimages==4;
867        }
868    
869    
870        struct StoneShadow {
871            ImageQuad  images;
872            Surface   *image;
873            bool       in_cache;
874    
875            StoneShadow (ImageQuad iq, bool cached)
876            : images(iq), image(0), in_cache(cached)
877            {}
878        };
879    
880        class StoneShadowCache : public px::Nocopy {
881        public:
882            StoneShadowCache(int tilew, int tileh);
883            ~StoneShadowCache();
884    
885            StoneShadow *retrieve (Model *models[4]);
886            void release (StoneShadow *s);
887            void clear();
888        private:
889            typedef std::list<StoneShadow*> CacheList;
890    
891            // Variables
892            size_t            m_max_size;
893            CacheList         m_cache;
894            int               m_tilew, m_tileh;
895            vector<Surface *> m_surface_avail;
896    
897            // Private methods.
898            Surface *new_surface ();
899            StoneShadow *find_in_cache (const ImageQuad &images);
900    
901            void fill_image (StoneShadow *s);
902            void fill_image (StoneShadow *sh, Model *models[4]);
903        };
904  }  }
905    
906  DL_Shadows::~DL_Shadows()  StoneShadowCache::StoneShadowCache(int tilew, int tileh)
907    : m_max_size(50), m_cache()
908    {
909        m_tilew=tilew; m_tileh=tileh;
910    }
911    
912    StoneShadowCache::~StoneShadowCache()
913  {  {
914      delete_sequence(m_gridcache.begin(), m_gridcache.end());      clear();
     delete_sequence(m_surface_avail.begin(), m_surface_avail.end());  
     delete buffer;  
915  }  }
916    
917  void  void
918  DL_Shadows::new_world(int w, int h)  StoneShadowCache::clear()
919  {  {
920      Array2<Surface*>::iterator i;      CacheList::iterator i=m_cache.begin();
921      for (i=m_gridcache.begin();i!=m_gridcache.end(); ++i)      for (; i!=m_cache.end(); ++i)
922          dispose_surface(*i);      {
923      m_gridcache.resize(w,h);          delete (*i)->image;
924      has_shadow.resize(w,h,false);      }
925        m_cache.clear();
926        delete_sequence (m_surface_avail.begin(), m_surface_avail.end());
927  }  }
928    
929  Surface *  void
930  DL_Shadows::new_surface()  StoneShadowCache::fill_image (StoneShadow *sh)
931    {
932        // Special case: no shadows at all:
933        if (sh->images[0] == 0 && sh->images[1] == 0 &&
934            sh->images[2] == 0 && sh->images[3] == 0)
935        {
936            sh->image = 0;
937            return;
938        }
939    
940        Surface *s = new_surface();
941        GC gc(s);
942        set_color (gc, 255,255,255);
943        box(gc, s->size());
944    
945        if (Image *i = sh->images[0])
946            i->draw (gc, -m_tilew, -m_tileh);
947        if (Image *i = sh->images[1])
948            i->draw (gc, 0, -m_tileh);
949        if (Image *i = sh->images[2])
950            i->draw (gc, -m_tilew, 0);
951        if (Image *i = sh->images[3])
952            i->draw (gc, 0, 0);
953        sh->image = s;
954    }
955    
956    void
957    StoneShadowCache::fill_image (StoneShadow *sh, Model *models[4])
958    {
959        Surface *s = new_surface();
960        GC gc(s);
961        set_color (gc, 255,255,255);
962        box(gc, s->size());
963        if (models[0]) models[0]->draw (gc, -m_tilew, -m_tileh);
964        if (models[1]) models[1]->draw (gc, 0, -m_tileh);
965        if (models[2]) models[2]->draw (gc, -m_tilew, 0);
966        if (models[3]) models[3]->draw (gc, 0,0);
967        sh->image = s;
968    }
969    
970    
971    StoneShadow *
972    StoneShadowCache::find_in_cache (const ImageQuad &images)
973    {
974        CacheList::iterator i=m_cache.begin();
975        for (; i!=m_cache.end(); ++i) {
976            if ((*i)->images == images) {
977                StoneShadow *sh = *i;
978                // Move entry to front of list
979                m_cache.splice (m_cache.begin(), m_cache, i);
980                return sh;
981            }
982        }
983        return 0;
984    }
985    
986    
987    StoneShadow *
988    StoneShadowCache::retrieve (Model *models[4])
989    {
990        StoneShadow *shadow = 0;
991    
992        ImageQuad images;
993        if (only_images (models, images)) {
994            shadow = find_in_cache(images);
995            if (shadow) {
996            } else {
997                shadow = new StoneShadow (images, true);
998                fill_image (shadow);
999                m_cache.push_front (shadow);
1000    //            cout << "new cache entry #" << m_cache.size() << endl;
1001            }
1002        }
1003        else {
1004            shadow = new StoneShadow (images, false);
1005            fill_image (shadow);
1006        }
1007        return shadow;
1008    }
1009    
1010    void
1011    StoneShadowCache::release (StoneShadow *s)
1012  {  {
1013        if (s->in_cache) {
1014        }
1015        else {
1016            m_surface_avail.push_back(s->image);
1017            delete s;
1018        }
1019    }
1020    
1021    
1022    Surface *
1023    StoneShadowCache::new_surface () {
1024      Surface *s = 0;      Surface *s = 0;
1025      if (m_surface_avail.empty()) {      if (m_surface_avail.empty()) {
1026          SDL_Surface *ss = SDL_CreateRGBSurface(SDL_SWSURFACE|SDL_RLEACCEL,          SDL_Surface *ss = SDL_CreateRGBSurface(SDL_SWSURFACE|SDL_RLEACCEL,
1027                                                 TileWidth, TileHeight,                                                 m_tilew, m_tileh, 16,
                                                video::GetColorDepth(),  
1028                                                 0,0,0,0);                                                 0,0,0,0);
1029          s = new Surface(SDL_DisplayFormat(ss));          s = new Surface(SDL_DisplayFormat(ss));
1030          SDL_FreeSurface(ss);          SDL_FreeSurface(ss);
# Line 797  DL_Shadows::new_surface() Line 1032  DL_Shadows::new_surface()
1032          s = m_surface_avail.back();          s = m_surface_avail.back();
1033          m_surface_avail.pop_back();          m_surface_avail.pop_back();
1034      }      }
1035      return s;      return s;
1036  }  }
1037    
1038  void  
1039  DL_Shadows::dispose_surface(Surface *s)  //----------------------------------------
1040    // DL_Shadows
1041    //----------------------------------------
1042    
1043    DL_Shadows::DL_Shadows (DL_Grid *grid, DL_Sprites *sprites)
1044    : m_grid(grid), m_sprites(sprites)
1045  {  {
1046      if (s)      int tilew=32, tileh=32;
1047          m_surface_avail.push_back(s);      m_cache = new StoneShadowCache(tilew, tileh);
1048        SDL_Surface *ss = SDL_CreateRGBSurface(SDL_SWSURFACE,
1049                                               tilew, tileh,
1050                                               video::GetColorDepth(),
1051                                               0,0,0,0);
1052        SDL_SetColorKey(ss, SDL_SRCCOLORKEY,
1053                        SDL_MapRGB(ss->format, 255,255,255));
1054        SDL_SetAlpha(ss, SDL_SRCALPHA, 128);
1055        buffer = new Surface(ss);
1056  }  }
1057    
1058    DL_Shadows::~DL_Shadows()
1059    {
1060        delete m_cache;
1061        delete buffer;
1062    }
1063    
1064  Surface *  void
1065  DL_Shadows::get_cache(int x, int y)  DL_Shadows::new_world(int w, int h)
1066  {  {
1067      Surface *s= m_gridcache(x,y);      m_cache->clear();
     if (!s)  
         m_gridcache(x,y) = s = new_surface();  
     return s;  
1068  }  }
1069    
1070  bool  void
1071  DL_Shadows::draw_stone_shade(GC &gc, int x, int y, Field &f)  DL_Shadows::set_model (int x, int y, Model *m)
1072  {  {
1073      Model *m=f.layers[enigma::GRID_STONES];  //     FieldInfo &f = m_fieldinfo(x,y);
1074      if (m)  //     if (m != f.model) {
1075          m->draw_shade(gc, x, y);  //         f.model = m;
1076      return m!=0;  //         clear_flags (f.flags, HAS_SHADOW);
1077    //         set_flags (f.flags, MUST_UPDATE | (m ? HAS_SHADOW : 0));
1078    //     }
1079  }  }
1080    
1081  void  void
1082  DL_Shadows::update (int x, int y)  DL_Shadows::update (int x, int y)
1083  {  {
1084      int has_sh = false;  //     set_flags (m_fieldinfo(x,y).flags, MUST_UPDATE);
   
     Surface *s=get_cache(x,y);  
   
     GC gc(s);  
     set_color (gc, 255,255,255);  
     box(gc, s->size());  
   
     if (x>0&&y>0)  
         has_sh |= draw_stone_shade(gc, -TileWidth, -TileHeight,  
                                    fields(x-1,y-1));  
     if (x>0)  
         has_sh |= draw_stone_shade(gc, -TileWidth, 0, fields(x-1,y));  
     if (y>0)  
         has_sh |= draw_stone_shade(gc, 0, -TileHeight, fields(x,y-1));  
     has_sh |= draw_stone_shade(gc, 0, 0, fields(x,y));  
     has_shadow (x,y) = has_sh;  
   
     if (!has_sh) {  
 //        m_gridcache(x,y) = 0;  
 //        dispose(s);  
     }  
1085  }  }
1086    
1087  void  void
1088  DL_Shadows::draw (px::GC &gc, const WorldArea &a, int x, int y)  DL_Shadows::draw (px::GC &gc, const WorldArea &a, int x, int y)
1089  {  {
1090      draw (gc, x, y, a.x, a. y);      draw (gc, x, y, a.x, a.y);
1091  }  }
1092    
1093    bool
1094  void  DL_Shadows::has_actor (int x, int y)
 DL_Shadows::draw(GC &gc, int xpos, int ypos, int x, int y)  
1095  {  {
1096      bool has_actor = false;      // Is any actor at least partially inside this field?
1097        for (unsigned i=0; i<m_sprites->sprites.size(); ++i) {
1098      // Is there an actor that is partially inside this field?          Sprite *s = m_sprites->sprites[i];
     for (unsigned i=0; i<sprite_layer->sprites.size(); ++i) {  
         Sprite *s = sprite_layer->sprites[i];  
1099          if (s && s->layer == SPRITE_ACTOR) {          if (s && s->layer == SPRITE_ACTOR) {
1100              Rect r(int(s->pos[0]-0.3), int(s->pos[1]-0.3),2,2);              Rect r(int(s->pos[0]-0.3), int(s->pos[1]-0.3),2,2);
1101              if (r.contains(x,y)) {              if (r.contains(x,y)) {
1102                  has_actor = true;                  return true;
                 break;  
1103              }              }
1104          }          }
1105      }      }
1106        return false;
1107    }
1108    
1109      if (has_actor || has_shadow(x,y)) {  Model *
1110          Surface *s=get_cache(x,y);  DL_Shadows::get_shadow_model(int x, int y)
1111            {
1112          if (!has_actor) {      if (x >= 0 && y >= 0) {
1113            Model *m = m_grid->get_model(x,y);
1114            if (ShadedModel *sm = dynamic_cast<ShadedModel*>(m))
1115                return sm->get_shadow();
1116        }
1117        return 0;
1118    }
1119    
1120    
1121    void
1122    DL_Shadows::draw(GC &gc, int xpos, int ypos, int x, int y)
1123    {
1124        Model *models[4];
1125        models[0] = get_shadow_model (x-1, y-1);
1126        models[1] = get_shadow_model (x, y-1);
1127        models[2] = get_shadow_model (x-1, y);
1128        models[3] = get_shadow_model (x, y);
1129    
1130        StoneShadow *sh = m_cache->retrieve (models);
1131    
1132        bool has_actor = this->has_actor (x, y);
1133        if (has_actor || sh->image)
1134        {
1135            Surface *s = sh->image;
1136            if (has_actor) {
1137                GC gc2(buffer);
1138                if (s)
1139                    blit (gc2, 0,0,s);
1140                else {
1141                    set_color (gc2, 255, 255, 255);
1142                    box (gc2, buffer->size());
1143                }
1144                for (unsigned i=0; i<m_sprites->sprites.size(); ++i) {
1145                    if (Sprite *s = m_sprites->sprites[i]) {
1146                        int sx = int(s->pos[0]*32) - x*32;
1147                        int sy = int(s->pos[1]*32) - y*32;
1148                        s->model->draw_shade(gc2, sx, sy);
1149                    }
1150                }
1151                blit(gc, xpos, ypos, buffer);
1152            }
1153            else {
1154              SDL_Surface *ss = s->get_surface();              SDL_Surface *ss = s->get_surface();
1155              SDL_SetColorKey(ss, SDL_SRCCOLORKEY,              SDL_SetColorKey(ss, SDL_SRCCOLORKEY,
1156                              SDL_MapRGB(ss->format, 255,255,255));                              SDL_MapRGB(ss->format, 255,255,255));
1157              SDL_SetAlpha (ss, SDL_SRCALPHA, 128);              SDL_SetAlpha (ss, SDL_SRCALPHA, 128);
1158              blit (gc, xpos,ypos,s);              blit (gc, xpos,ypos,s);
1159              SDL_SetAlpha (ss, 0, 0);              SDL_SetAlpha (ss, 0, 0);
1160              SDL_SetColorKey(ss, 0,0);              SDL_SetColorKey (ss, 0,0);
         }  
         else {  
             GC gc2(buffer);  
             blit (gc2, 0,0,s);  
             for (unsigned i=0; i<sprite_layer->sprites.size(); ++i) {  
                 Sprite *s = sprite_layer->sprites[i];  
                 if (s && s->layer == SPRITE_ACTOR){  
                     int sx = int(s->pos[0]*TileWidth) - x*TileWidth;  
                     int sy = int(s->pos[1]*TileWidth) - y*TileHeight;  
                     s->model->draw_shade(gc2, sx, sy);  
                 }  
             }  
             blit(gc, xpos, ypos, buffer);  
1161          }          }
1162      }      }
1163    
1164        m_cache->release (sh);
1165  }  }
1166    
1167  void  void
1168  DL_Shadows::shadow_blit (px::Surface *scr, int x, int y,  DL_Shadows::shadow_blit (px::Surface *scr, int x, int y,
1169                           px::Surface *shadows, px::Rect r)                           px::Surface *shadows, px::Rect r)
1170  {  {
1171      r.intersect(scr->size());  //     r.intersect(scr->size());
1172      x=r.x;  //     x=r.x;
1173      y=r.y;  //     y=r.y;
1174    
1175      SDL_Surface *s = shadows->get_surface(); // source  //     SDL_Surface *s = shadows->get_surface(); // source
1176      SDL_Surface *d = scr->get_surface();  //     SDL_Surface *d = scr->get_surface();
1177    
1178      SDL_LockSurface(s);  //     SDL_LockSurface(s);
1179      SDL_LockSurface(d);  //     SDL_LockSurface(d);
1180            
1181      assert (s->format->BytesPerPixel==2 &&  //     assert (s->format->BytesPerPixel==2 &&
1182              d->format->BytesPerPixel==2);  //             d->format->BytesPerPixel==2);
   
   
     /* This bitmask is used to erase the highest bit in every color  
        field.  Every color value can be effectively halved by (a)  
        shifting everything one bit to the right, and (b) applying the  
        mask to the resulting value. */  
     Uint32 mask;  
     mask  = (d->format->Rmask >> d->format->Rshift+1) << d->format->Rshift;  
     mask |= (d->format->Gmask >> d->format->Gshift+1) << d->format->Gshift;  
     mask |= (d->format->Bmask >> d->format->Bshift+1) << d->format->Bshift;  
   
     register Uint16 skey = (Uint16)shadow_ckey;  
     for (int h=r.h; h; --h)  
     {  
         Uint16 *sp = static_cast<Uint16*>(shadows->pixel_pointer(r.x, r.y));  
         Uint16 *dp = static_cast<Uint16*>(scr->pixel_pointer(x, y));  
         for (int w=r.w; w; --w)  
         {  
             if (*sp != skey)  
                 *dp = (*dp >> 1) & mask;  
             dp++;  
             sp++;  
         }  
         y++;  
         r.y++;  
     }  
   
     SDL_UnlockSurface(s);  
     SDL_UnlockSurface(d);  
 }  
   
 Model *  
 DL_Shadows::get_shadow_model (Model *stone_models[4])  
 {  
     return 0;  
 }  
   
   
   
 //----------------------------------------------------------------------  
 // GLOBAL FUNCTIONS  
 //----------------------------------------------------------------------  
   
 void  
 display::Init()  
 {  
     InitModels();  
1183    
     ScreenArea gamearea(0,0,640, 480-64);  
     gamedpy = new GameDisplay (gamearea);  
 }  
   
 void  
 display::Shutdown()  
 {  
     delete gamedpy;  
     ShutdownModels();  
 }  
1184    
1185  void display::Tick (double dtime) {  //     /* This bitmask is used to erase the highest bit in every color
1186      gamedpy->tick(dtime);  //        field.  Every color value can be effectively halved by (a)
1187  }  //        shifting everything one bit to the right, and (b) applying the
1188    //        mask to the resulting value. */
1189    //     Uint32 mask;
1190    //     mask  = (d->format->Rmask >> d->format->Rshift+1) << d->format->Rshift;
1191    //     mask |= (d->format->Gmask >> d->format->Gshift+1) << d->format->Gshift;
1192    //     mask |= (d->format->Bmask >> d->format->Bshift+1) << d->format->Bshift;
1193    
1194    //     register Uint16 skey = (Uint16)shadow_ckey;
1195    //     for (int h=r.h; h; --h)
1196    //     {
1197    //         Uint16 *sp = static_cast<Uint16*>(shadows->pixel_pointer(r.x, r.y));
1198    //         Uint16 *dp = static_cast<Uint16*>(scr->pixel_pointer(x, y));
1199    //         for (int w=r.w; w; --w)
1200    //         {
1201    //             if (*sp != skey)
1202    //                 *dp = (*dp >> 1) & mask;
1203    //             dp++;
1204    //             sp++;
1205    //         }
1206    //         y++;
1207    //         r.y++;
1208    //     }
1209    
1210  StatusBar * display::GetStatusBar() {  //     SDL_UnlockSurface(s);
1211      return gamedpy->get_status_bar();  //     SDL_UnlockSurface(d);
 }  
   
 void display::NewWorld(int w, int h) {  
     gamedpy->new_world (w, h);  
1212  }  }
1213    
1214    
# Line 1100  Follower_Scrolling::tick(double dtime, c Line 1319  Follower_Scrolling::tick(double dtime, c
1319      }      }
1320  }  }
1321    
 void display::FollowSprite(SpriteId id) {  
     gamedpy->set_follow_sprite (id);  
 }  
   
 FollowMode display::SetFollowMode(FollowMode m) {  
     return gamedpy->set_follow_mode(m);  
 }  
   
 Model *display::SetModel (const GridLoc &l, Model *m) {  
     return gamedpy->set_model (l, m);  
 }  
   
 Model *display::SetModel (const GridLoc &l, const string &modelname) {  
     return SetModel(l, MakeModel(modelname));  
 }  
   
 void display::KillModel(const GridLoc & l) {  
     delete YieldModel(l);  
 }  
   
 Model *display::GetModel(const GridLoc &l) {  
     return gamedpy->get_model (l);  
 }  
   
 Model *display::YieldModel(const GridLoc &l) {  
     return gamedpy->yield_model (l);  
 }  
   
 void display::AddEffect (const V3& pos, const char *modelname) {  
     gamedpy->add_effect (pos, MakeModel(modelname));  
 }  
   
 SpriteId  
 display::AddSprite (const V3& pos, const char *modelname)  
 {  
     Model *m = modelname ? MakeModel(modelname) : 0;  
     return sprite_layer->add_sprite(new Sprite (pos, SPRITE_ACTOR, m));  
 }  
   
 void  
 display::MoveSprite(SpriteId id, const px::V3& newpos)  
 {  
     sprite_layer->move_sprite (id, newpos);  
 }  
   
 void  
 display::ReplaceSprite (SpriteId id, const char *modelname)  
 {  
     sprite_layer->replace_sprite (id, MakeModel(modelname));  
 }  
   
 void  
 display::KillSprite(SpriteId id)  
 {  
     sprite_layer->kill_sprite(id);  
 }  
   
 void  
 display::SetCallback(SpriteId id, ModelCallback *cb)  
 {  
     if (Model *m = GetModel(id))  
         m->set_callback(cb);  
 }  
   
 Model *  
 display::GetModel(SpriteId id)  
 {  
     if (id == MAGIC_SPRITEID)  
         return 0;  
     return sprite_layer->sprites[id]->model;  
 }  
   
 void  
 display::SetTileSize(int w, int h)  
 {  
     TileWidth = w;  
     TileHeight = h;  
 //    engine->set_tilesize(w,h);  
 }  
   
 void  
 display::ToggleFlag(DisplayFlags flag)  
 {  
     display_flags = DisplayFlags(display_flags ^ flag);  
 }  
   
 void display::DrawAll (GC &gc) {  
     gamedpy->draw_all(gc);  
 }  
   
 void display::RedrawAll(Screen *screen) {  
     gamedpy->redraw_all(screen);  
 }  
   
 void display::Redraw(Screen *screen) {  
     gamedpy->redraw(screen);  
 }  
1322    
1323    
1324  //----------------------------------------------------------------------  //----------------------------------------------------------------------
# Line 1209  CommonDisplay::CommonDisplay (const Scre Line 1331  CommonDisplay::CommonDisplay (const Scre
1331    
1332      engine->add_layer (floor_layer = new DL_Grid);      engine->add_layer (floor_layer = new DL_Grid);
1333      engine->add_layer (item_layer = new DL_Grid);      engine->add_layer (item_layer = new DL_Grid);
1334      engine->add_layer (shadow_layer = new DL_Shadows(0,0));      sprite_layer = new DL_Sprites;
1335      engine->add_layer (sprite_layer = new DL_Sprites);      stone_layer = new DL_Grid;
1336      engine->add_layer (stone_layer = new DL_Grid);      shadow_layer = new DL_Shadows(stone_layer, sprite_layer);
1337        engine->add_layer (shadow_layer);
1338        engine->add_layer (sprite_layer);
1339        engine->add_layer (stone_layer);
1340      engine->add_layer (line_layer = new DL_Lines);      engine->add_layer (line_layer = new DL_Lines);
1341      engine->add_layer (effects_layer = new DL_Sprites);      engine->add_layer (effects_layer = new DL_Sprites);
1342      effects_layer->set_maxsprites(10);      effects_layer->set_maxsprites(10);
# Line 1236  CommonDisplay::set_model (const GridLoc Line 1361  CommonDisplay::set_model (const GridLoc
1361      case GRID_STONES:      case GRID_STONES:
1362          stone_layer->set_model (x, y, m);          stone_layer->set_model (x, y, m);
1363  //        shadow_layer->set_model (x, y, m);  //        shadow_layer->set_model (x, y, m);
1364            shadow_layer->update (x, y);
1365          break;          break;
1366      case GRID_COUNT: break;      case GRID_COUNT: break;
1367      }      }
     Field& f = fields(x, y);  
     f.layers[l.layer] = m;  
1368      return m;      return m;
1369  }  }
1370    
# Line 1261  Model * Line 1385  Model *
1385  CommonDisplay::yield_model (const GridLoc &l)  CommonDisplay::yield_model (const GridLoc &l)
1386  {  {
1387      int x = l.pos.x, y=l.pos.y;      int x = l.pos.x, y=l.pos.y;
     fields(x, y).layers[l.layer] = 0;  
1388      switch (l.layer) {      switch (l.layer) {
1389      case GRID_FLOOR: return floor_layer->yield_model (x, y);      case GRID_FLOOR: return floor_layer->yield_model (x, y);
1390      case GRID_ITEMS: return item_layer->yield_model (x, y);      case GRID_ITEMS: return item_layer->yield_model (x, y);
# Line 1271  CommonDisplay::yield_model (const GridLo Line 1394  CommonDisplay::yield_model (const GridLo
1394      return 0;      return 0;
1395  }  }
1396    
1397    
1398    RubberHandle
1399    CommonDisplay::add_line (V2 p1, V2 p2)
1400    {
1401        return line_layer->add_line (p1, p2);
1402    }
1403    
1404  SpriteHandle  SpriteHandle
1405  CommonDisplay::add_effect (const V3& pos, Model *m)  CommonDisplay::add_effect (const V2& pos, Model *m)
1406  {  {
1407      Sprite *spr = new Sprite (pos, SPRITE_EFFECT, m);      Sprite *spr = new Sprite (pos, SPRITE_EFFECT, m);
1408      return SpriteHandle (effects_layer, effects_layer->add_sprite(spr));      return SpriteHandle (effects_layer, effects_layer->add_sprite(spr));
1409  }  }
1410    
1411    SpriteHandle
1412    CommonDisplay::add_sprite (const V2 &pos, Model *m)
1413    {
1414        Sprite *spr = new Sprite (pos, SPRITE_ACTOR, m);
1415        return SpriteHandle (sprite_layer, sprite_layer->add_sprite(spr));
1416    }
1417    
1418  void  void
1419  CommonDisplay::new_world (int w, int h)  CommonDisplay::new_world (int w, int h)
1420  {  {
1421      fields = FieldArray(w, h);  //     fields.resize(w, h);
1422      get_engine()->new_world (w, h);      get_engine()->new_world (w, h);
1423  }  }
1424    
# Line 1308  GameDisplay::GameDisplay(const ScreenAre Line 1445  GameDisplay::GameDisplay(const ScreenAre
1445  : CommonDisplay(a),  : CommonDisplay(a),
1446    last_frame_time (0),    last_frame_time (0),
1447    redraw_everything(false),    redraw_everything(false),
1448    follow_sprite (MAGIC_SPRITEID),    m_reference_point (),
1449    follow_mode (FOLLOW_NONE),    m_follower (0),
   follower (0),  
1450    inventoryarea(0, 480-64, 640, 64)    inventoryarea(0, 480-64, 640, 64)
1451  {  {
1452      status_bar = new StatusBarImpl (inventoryarea);      status_bar = new StatusBarImpl (inventoryarea);
# Line 1327  GameDisplay::tick(double dtime) Line 1463  GameDisplay::tick(double dtime)
1463      get_engine()->tick (dtime);      get_engine()->tick (dtime);
1464      status_bar->tick (dtime);      status_bar->tick (dtime);
1465    
1466      if (follow_sprite != MAGIC_SPRITEID) {      if (m_follower)
1467          V3 point = sprite_layer->sprites[follow_sprite]->pos;          m_follower->tick (dtime, m_reference_point);
         follower->tick(dtime, V2(point[0], point[1]));  
     }  
1468  }  }
1469    
1470  void  void
# Line 1338  GameDisplay::new_world (int w, int h) Line 1472  GameDisplay::new_world (int w, int h)
1472  {  {
1473      CommonDisplay::new_world (w, h);      CommonDisplay::new_world (w, h);
1474      status_bar->new_world();      status_bar->new_world();
1475      SetFollowMode(FOLLOW_NONE);      set_follow_mode (FOLLOW_NONE);
1476    
1477  //     shadow_layer->new_world(w,h);  //     shadow_layer->new_world(w,h);
1478      ScrollX = ScrollY = 0;      ScrollX = ScrollY = 0;
# Line 1354  GameDisplay::get_status_bar() const Line 1488  GameDisplay::get_status_bar() const
1488  // Scrolling  // Scrolling
1489  //----------------------------------------  //----------------------------------------
1490    
1491    void
 FollowMode  
1492  GameDisplay::set_follow_mode (FollowMode m)  GameDisplay::set_follow_mode (FollowMode m)
1493  {  {
1494      FollowMode old=follow_mode;      switch (m) {
1495      if (m != follow_mode)      case FOLLOW_NONE: set_follower(0); break;
1496      {      case FOLLOW_SCROLLING: set_follower (new Follower_Scrolling); break;
1497          follow_mode = m;      case FOLLOW_SCREEN: set_follower (new Follower_Screen); break;
1498          switch (follow_mode) {      };
         case FOLLOW_NONE:        
             set_follower(0);  
             break;  
         case FOLLOW_SCROLLING:  
             set_follower (new Follower_Scrolling);  
             break;  
         case FOLLOW_SCREEN:      
             set_follower (new Follower_Screen);  
             break;  
         };  
     }  
     return old;  
1499  }  }
1500    
1501  void  void
1502  GameDisplay::set_follower (Follower *f)  GameDisplay::set_follower (Follower *f)
1503  {  {
1504      delete follower;      delete m_follower;
1505      follower = f;      if ((m_follower = f)) {
1506      if (follower) {          m_follower->set_engine (get_engine());
1507          follower->set_engine (get_engine());          follow_center();
1508      }      }
1509  }  }
1510    
1511  void  void
1512  GameDisplay::follow_center()  GameDisplay::follow_center()
1513  {  {
1514      if (follow_mode == FOLLOW_NONE)      if (m_follower)
1515          set_follow_mode (FOLLOW_SCREEN);          m_follower->center (m_reference_point);
     if (follow_sprite != MAGIC_SPRITEID) {  
         V3 point = sprite_layer->sprites[follow_sprite]->pos;  
         follower->center (V2(point[0], point[1]));  
     }  
1516  }  }
1517    
1518  void  void
1519  GameDisplay::set_follow_sprite(SpriteId id)  GameDisplay::set_reference_point (const V2 &point)
1520  {  {
1521      follow_sprite = id;      m_reference_point = point;
     follow_center();  
1522  }  }
1523    
1524  //----------------------------------------  //----------------------------------------
# Line 1410  GameDisplay::set_follow_sprite(SpriteId Line 1526  GameDisplay::set_follow_sprite(SpriteId
1526  //----------------------------------------  //----------------------------------------
1527    
1528  void  void
1529  GameDisplay::redraw_all(Screen *scr)  GameDisplay::redraw_all (Screen *scr)
1530  {  {
1531      get_engine()->mark_redraw_screen();      get_engine()->mark_redraw_screen();
1532      redraw_everything = true;      redraw_everything = true;
# Line 1451  GameDisplay::draw_all (GC &gc) Line 1567  GameDisplay::draw_all (GC &gc)
1567      status_bar->redraw (gc, inventoryarea);      status_bar->redraw (gc, inventoryarea);
1568  }  }
1569    
1570    
1571    //----------------------------------------------------------------------
1572    // GLOBAL FUNCTIONS
1573    //----------------------------------------------------------------------
1574    
1575    void
1576    display::Init()
1577    {
1578        InitModels();
1579    
1580        ScreenArea gamearea(0,0,640, 480-64);
1581        gamedpy = new GameDisplay (gamearea);
1582    }
1583    
1584    void
1585    display::Shutdown()
1586    {
1587        delete gamedpy;
1588        ShutdownModels();
1589    }
1590    
1591    void display::Tick (double dtime) {
1592        gamedpy->tick(dtime);
1593    }
1594    
1595    StatusBar * display::GetStatusBar() {
1596        return gamedpy->get_status_bar();
1597    }
1598    
1599    void display::NewWorld(int w, int h) {
1600        gamedpy->new_world (w, h);
1601    }
1602    
1603    void display::FocusReferencePoint() {
1604        gamedpy->follow_center();
1605    }
1606    
1607    void display::SetReferencePoint (const px::V2 &point) {
1608        gamedpy->set_reference_point (point);
1609    }
1610    
1611    void display::SetFollowMode(FollowMode m) {
1612        gamedpy->set_follow_mode(m);
1613    }
1614    
1615    Model *display::SetModel (const GridLoc &l, Model *m) {
1616        return gamedpy->set_model (l, m);
1617    }
1618    
1619    Model *display::SetModel (const GridLoc &l, const string &modelname) {
1620        return SetModel(l, MakeModel(modelname));
1621    }
1622    
1623    void display::KillModel(const GridLoc & l) {
1624        delete YieldModel(l);
1625    }
1626    
1627    Model *display::GetModel(const GridLoc &l) {
1628        return gamedpy->get_model (l);
1629    }
1630    
1631    Model *display::YieldModel(const GridLoc &l) {
1632        return gamedpy->yield_model (l);
1633    }
1634    
1635    void display::AddEffect (const V2& pos, const char *modelname) {
1636        gamedpy->add_effect (pos, MakeModel(modelname));
1637    }
1638    
1639    SpriteHandle
1640    display::AddSprite (const V2& pos, const char *modelname)
1641    {
1642        Model *m = modelname ? MakeModel(modelname) : 0;
1643        return gamedpy->add_sprite (pos, m);
1644    }
1645    
1646    
1647    void
1648    display::SetTileSize(int w, int h)
1649    {
1650        TileWidth = w;
1651        TileHeight = h;
1652    //    engine->set_tilesize(w,h);
1653    }
1654    
1655    void
1656    display::ToggleFlag(DisplayFlags flag)
1657    {
1658        toggle_flags (display_flags, flag);
1659    }
1660    
1661    void display::DrawAll (GC &gc) {
1662        gamedpy->draw_all(gc);
1663    }
1664    
1665    void display::RedrawAll(Screen *screen) {
1666        gamedpy->redraw_all(screen);
1667    }
1668    
1669    void display::Redraw(Screen *screen) {
1670        gamedpy->redraw(screen);
1671    }
1672    
1673    RubberHandle
1674    display::AddRubber (const V2 &p1, const V2 &p2)
1675    {
1676        return gamedpy->add_line (p1, p2);
1677    }

Legend:
Removed from v.1.14  
changed lines
  Added in v.1.15

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