home *** CD-ROM | disk | FTP | other *** search
/ PC Format (South-Africa) 2001 June / PCFJune.iso / Xenon / XenonSource.exe / gamesystem / source / gs_map.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-07-21  |  7.6 KB  |  357 lines

  1. //-------------------------------------------------------------
  2. //
  3. // Class:    gsCMap
  4. //
  5. // Author:    John M Phillips
  6. //
  7. // Started:    12/03/00
  8. //
  9. // Base:    gsCObject
  10. //
  11. // Derived:    None
  12. //
  13. //-------------------------------------------------------------
  14.  
  15. #include "gamesystem.h"
  16.  
  17. //-------------------------------------------------------------
  18.  
  19. gsCMap::gsCMap()
  20. {
  21.     m_image = 0;
  22.     m_size = gsCPoint(0,0);
  23.     m_map_tiles = 0;
  24.     m_position = gsCPoint(0,0);
  25.     m_tile_size = gsCPoint(0,0);
  26.     m_total_size = gsCPoint(0,0);
  27. }
  28.  
  29. //-------------------------------------------------------------
  30.  
  31. gsCMap::~gsCMap()
  32. {
  33.     destroy();
  34. }
  35.  
  36. //-------------------------------------------------------------
  37.  
  38. void gsCMap::destroy()
  39. {
  40.     destroyMapTiles();
  41. }
  42.  
  43. //-------------------------------------------------------------
  44.  
  45. void gsCMap::createMapTiles()
  46. {
  47.     if (m_size.getX() == 0 ||
  48.         m_size.getY() == 0)
  49.         return;
  50.  
  51.     m_map_tiles = new gsCMapTile[m_size.getX() * m_size.getY()];
  52.  
  53.     clear(0,true);
  54. }
  55.  
  56. //-------------------------------------------------------------
  57.  
  58. void gsCMap::destroyMapTiles()
  59. {
  60.     if (m_map_tiles) {
  61.         delete [] m_map_tiles;
  62.         m_map_tiles = 0;
  63.         }
  64. }
  65.  
  66. //-------------------------------------------------------------
  67.  
  68. void gsCMap::clear(int tile,bool empty)
  69. {
  70.     for (int y = 0; y < m_size.getY(); y++) {
  71.         for (int x = 0; x < m_size.getX(); x++) {
  72.             setMapTile(gsCPoint(x,y),gsCMapTile(tile,empty));
  73.             }
  74.         }
  75. }
  76.  
  77. //-------------------------------------------------------------
  78.  
  79. void gsCMap::calculateTotalSize()
  80. {
  81.     if (!m_image || !m_map_tiles) {
  82.         m_tile_size = gsCPoint(0,0);
  83.         m_total_size = gsCPoint(0,0);
  84.         }
  85.     else {
  86.         m_tile_size = m_image->getTileSize();
  87.         m_total_size = m_tile_size * m_size;
  88.         }
  89. }
  90.  
  91. //-------------------------------------------------------------
  92.  
  93. void gsCMap::setImage(gsCTiledImage *image)
  94. {
  95.     m_image = image;
  96.  
  97.     calculateTotalSize();
  98. }
  99.  
  100. //-------------------------------------------------------------
  101.  
  102. void gsCMap::setSize(const gsCPoint& size)
  103. {
  104.     destroyMapTiles();
  105.  
  106.     m_size = size;
  107.  
  108.     createMapTiles();
  109.  
  110.     calculateTotalSize();
  111. }
  112.  
  113. //-------------------------------------------------------------
  114.  
  115. bool gsCMap::setMapTile(const gsCPoint& coords,const gsCMapTile& map_tile)
  116. {
  117.     gsCMapTile *p = getMapTile(coords);
  118.  
  119.     if (p == 0)
  120.         return false;
  121.  
  122.     *p = map_tile;
  123.  
  124.     return true;
  125. }
  126.  
  127. //-------------------------------------------------------------
  128.  
  129. void gsCMap::setPosition(const gsCPoint& position)
  130. {
  131.     m_position = position;
  132. }
  133.  
  134. //-------------------------------------------------------------
  135.  
  136. gsCTiledImage *gsCMap::getImage()
  137. {
  138.     return m_image;
  139. }
  140.  
  141. //-------------------------------------------------------------
  142.  
  143. gsCPoint gsCMap::getSize()
  144. {
  145.     return m_size;
  146. }
  147.  
  148. //-------------------------------------------------------------
  149.  
  150. gsCPoint gsCMap::getSizeInPixels()
  151. {
  152.     return m_total_size;
  153. }
  154.  
  155. //-------------------------------------------------------------
  156.  
  157. gsCMapTile *gsCMap::getMapTile(const gsCPoint& coords)
  158. {
  159.     if (coords.getX() < 0 ||
  160.         coords.getY() < 0 ||
  161.         coords.getX() >= m_size.getX() ||
  162.         coords.getY() >= m_size.getY())
  163.         return 0;
  164.     else
  165.         return &m_map_tiles[m_size.getX() * coords.getY() + coords.getX()];
  166. }
  167.  
  168. //-------------------------------------------------------------
  169.  
  170. gsCPoint gsCMap::getPosition()
  171. {
  172.     return m_position;
  173. }
  174.  
  175. //-------------------------------------------------------------
  176.  
  177. void gsCMap::move(const gsCPoint& offset)
  178. {
  179.     m_position += offset;
  180. }
  181.  
  182. //-------------------------------------------------------------
  183.  
  184. void gsCMap::draw()
  185. {
  186.     if (!m_image || !m_map_tiles)
  187.         return;
  188.  
  189.     gsCScreen *screen = gsCApplication::getScreen();
  190.  
  191.     if (!screen)
  192.         return;
  193.  
  194.     // clip map against screen
  195.  
  196.     gsCRect screen_rect = screen->getRect();
  197.  
  198.     // get map source and dest rects in pixel coords
  199.  
  200.     gsCRect source_rect(gsCPoint(0,0),m_size * m_tile_size);
  201.  
  202.     gsCRect dest_rect = source_rect;
  203.     dest_rect.move(m_position);
  204.  
  205.     screen_rect.clip(source_rect,dest_rect);
  206.  
  207.     if (!dest_rect.isEmpty()) {
  208.  
  209.         // convert back to tile coords
  210.  
  211.         int left = source_rect.getLeft() / m_tile_size.getX();
  212.         int top = source_rect.getTop() / m_tile_size.getY();
  213.         int right = (source_rect.getRight() - 1) / m_tile_size.getX();
  214.         int bottom = (source_rect.getBottom() - 1) / m_tile_size.getY();
  215.  
  216.         int x,y;
  217.         gsCMapTile *map_tile;
  218.         gsCPoint pos;
  219.         gsCPoint step;
  220.  
  221.         // top edge clipped
  222.  
  223.         map_tile = getMapTile(gsCPoint(left,top));
  224.         pos = m_position + gsCPoint(left,top) * m_tile_size;
  225.         step = gsCPoint(1,0) * m_tile_size;
  226.         for (x = left; x <= right; x++) {
  227.             if (map_tile->isDrawable())
  228.                 m_image->draw(map_tile->getTile(),pos);
  229.             map_tile++;
  230.             pos += step;
  231.             }
  232.  
  233.         // bottom edge clipped
  234.  
  235.         map_tile = getMapTile(gsCPoint(left,bottom));
  236.         pos = m_position + gsCPoint(left,bottom) * m_tile_size;
  237.         step = gsCPoint(1,0) * m_tile_size;
  238.         for (x = left; x <= right; x++) {
  239.             if (map_tile->isDrawable())
  240.                 m_image->draw(map_tile->getTile(),pos);
  241.             map_tile++;
  242.             pos += step;
  243.             }
  244.  
  245.         // left edge clipped
  246.  
  247.         map_tile = getMapTile(gsCPoint(left,top + 1));
  248.         pos = m_position + gsCPoint(left,top + 1) * m_tile_size;
  249.         step = gsCPoint(0,1) * m_tile_size;
  250.         for (y = top + 1; y < bottom; y++) {
  251.             if (map_tile->isDrawable())
  252.                 m_image->draw(map_tile->getTile(),pos);
  253.             map_tile += m_size.getX();
  254.             pos += step;
  255.             }
  256.  
  257.         // right edge clipped
  258.  
  259.         map_tile = getMapTile(gsCPoint(right,top + 1));
  260.         pos = m_position + gsCPoint(right,top + 1) * m_tile_size;
  261.         step = gsCPoint(0,1) * m_tile_size;
  262.         for (y = top + 1; y < bottom; y++) {
  263.             if (map_tile->isDrawable())
  264.                 m_image->draw(map_tile->getTile(),pos);
  265.             map_tile += m_size.getX();
  266.             pos += step;
  267.             }
  268.  
  269.         // middle not clipped
  270.         
  271.         for (y = top + 1; y < bottom; y++) {
  272.             map_tile = getMapTile(gsCPoint(left + 1,y));
  273.             pos = m_position + gsCPoint(left + 1,y) * m_tile_size;
  274.             step = gsCPoint(1,0) * m_tile_size;
  275.             for (x = left + 1; x < right; x++) {
  276.                 if (map_tile->isDrawable())        
  277.                     m_image->drawFast(map_tile->getTile(),pos);
  278.                 map_tile++;
  279.                 pos += step;
  280.                 }
  281.             }
  282.  
  283.         }
  284. }
  285.  
  286. //-------------------------------------------------------------
  287.  
  288. bool gsCMap::load(const char *filename,const gsCPoint& size)
  289. {
  290.     setSize(size);
  291.     
  292.     gsCFile file;
  293.  
  294.     if (!file.open(filename))
  295.         return false;
  296.     
  297.     for (int y = 0; y < m_size.getY(); y++) {
  298.         for (int x = 0; x < m_size.getX(); x++) {
  299.             gsUWORD tile;
  300.             if (file.read(&tile,2) != 2)
  301.                 break;
  302.             if (tile == 0)
  303.                 setMapTile(gsCPoint(x,y),gsCMapTile(0,true));
  304.             else
  305.                 setMapTile(gsCPoint(x,y),gsCMapTile(tile / 32)); // - 1));
  306.             }
  307.         }
  308.  
  309.     file.close();
  310.  
  311.     return true;
  312. }
  313.  
  314. //-------------------------------------------------------------
  315. // Find tiles which overlap rect
  316.  
  317. int gsCMap::hitBy(const gsCRect& rect,gsUBYTE collision_mask)
  318. {
  319.     gsCRect dest = rect;
  320.  
  321.     gsCRect source(gsCPoint(0,0),m_total_size);
  322.  
  323.     source.clip(dest);
  324.     
  325.     if (dest.isEmpty())
  326.         return 0;
  327.  
  328.     m_hit_list.clear();
  329.  
  330.     int x1 = dest.getLeft() / m_tile_size.getX();
  331.     int y1 = dest.getTop() / m_tile_size.getY();
  332.     int x2 = (dest.getRight() - 1) / m_tile_size.getX();
  333.     int y2 = (dest.getBottom() - 1) / m_tile_size.getY();
  334.  
  335.     for (int x = x1; x <= x2; x++) {
  336.         for (int y = y1; y <= y2; y++) {
  337.             gsCPoint pos(x,y);
  338.             gsCMapTile *mt = getMapTile(pos);
  339.             if (!mt->isEmpty() &&
  340.                 !mt->isHidden() &&
  341.                 (mt->getCollisionFlags() & collision_mask) != 0)
  342.                 m_hit_list.addItem(pos);
  343.             }
  344.         }
  345.  
  346.     return m_hit_list.getSize();
  347. }
  348.  
  349. //-------------------------------------------------------------
  350.  
  351. gsCPoint gsCMap::getHitPosition(int n)
  352. {
  353.     return m_hit_list[n];
  354. }
  355.  
  356. //-------------------------------------------------------------
  357.