home *** CD-ROM | disk | FTP | other *** search
/ PC Format (South-Africa) 2001 June / PCFJune.iso / Xenon / XenonSource.exe / demo3 / level.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-09-11  |  6.2 KB  |  282 lines

  1. //-------------------------------------------------------------
  2. //
  3. // Class:    CLevel
  4. //
  5. // Author:    John M Phillips
  6. //
  7. // Started:    06/05/00
  8. //
  9. // Remarks:    This is a cut-down version of the level loader
  10. //            used in Xenon2000
  11. //
  12. //-------------------------------------------------------------
  13.  
  14. #include "level.h"
  15.  
  16. //-------------------------------------------------------------
  17.  
  18. CLevel::CLevel()
  19. {
  20.     m_blocks = 0;
  21. }
  22.  
  23. //-------------------------------------------------------------
  24.  
  25. CLevel::~CLevel()
  26. {
  27.     destroy();
  28. }
  29.  
  30. //-------------------------------------------------------------
  31.  
  32. void CLevel::destroy()
  33. {
  34.     m_back_layer.destroy();
  35.     m_front_layer.destroy();
  36.     m_image.destroy();
  37. }
  38.  
  39. //-------------------------------------------------------------
  40.  
  41. bool CLevel::readUDWORD(gsUDWORD& d)
  42. {
  43.     gsUBYTE b[4];
  44.  
  45.     if (m_file.read(b,4) != 4)
  46.         return false;
  47.  
  48.     d = (((gsUDWORD) b[0]) << 24) +
  49.         (((gsUDWORD) b[1]) << 16) + 
  50.         (((gsUDWORD) b[2]) << 8) + 
  51.         ((gsUDWORD) b[3]);
  52.  
  53.     return true;
  54. }
  55.  
  56. //-------------------------------------------------------------
  57.  
  58. bool CLevel::readUWORD(gsUWORD& w)
  59. {
  60.     gsUBYTE b[2];
  61.  
  62.     if (m_file.read(b,2) != 2)
  63.         return false;
  64.  
  65.     w =    (((gsUWORD) b[0]) << 8) + 
  66.         ((gsUWORD) b[1]);
  67.  
  68.     return true;
  69. }
  70.  
  71. //-------------------------------------------------------------
  72.  
  73. bool CLevel::error()
  74. {
  75.     m_file.close();
  76.     return false;
  77. }
  78.  
  79. //-------------------------------------------------------------
  80.     
  81. #define CHUNK4(a,b,c,d) ((gsUDWORD(a) << 24) + (gsUDWORD(b) << 16) + \
  82.                         (gsUDWORD(c) << 8) + gsUDWORD(d))
  83.  
  84. const gsUDWORD CHUNK_FORM = CHUNK4('F','O','R','M');
  85. const gsUDWORD CHUNK_FMAP = CHUNK4('F','M','A','P');
  86. const gsUDWORD CHUNK_MPHD = CHUNK4('M','P','H','D');
  87. const gsUDWORD CHUNK_BKDT = CHUNK4('B','K','D','T');
  88. const gsUDWORD CHUNK_BGFX = CHUNK4('B','G','F','X');
  89. const gsUDWORD CHUNK_BODY = CHUNK4('B','O','D','Y');
  90. const gsUDWORD CHUNK_LYR1 = CHUNK4('L','Y','R','1');
  91.  
  92. bool CLevel::load(const char *filename,const char *levels_directory,const char *graphics_directory)
  93. {
  94.     destroy();
  95.  
  96.     gsCFile::setDirectory(levels_directory);
  97.  
  98.     if (!m_file.open(filename,gsFILE_READ))
  99.         return false;
  100.  
  101.     gsUDWORD id = 0;
  102.  
  103.     if (!readUDWORD(id) ||
  104.         id != CHUNK_FORM)
  105.         return error();
  106.  
  107.     if (!readUDWORD(id))
  108.         return error();
  109.  
  110.     if (!readUDWORD(id) ||
  111.         id != CHUNK_FMAP)
  112.         return error();
  113.  
  114.     bool loaded_back_layer = false;
  115.     bool loaded_front_layer = false;
  116.     bool loaded_tiles = false;
  117.  
  118.     for (;;) {
  119.         if (!readUDWORD(id))
  120.             return error();
  121.  
  122.         gsUDWORD chunk_length = 0;
  123.         
  124.         if (!readUDWORD(chunk_length))
  125.             return error();
  126.  
  127.         gsUDWORD chunk_end = m_file.getPosition() + chunk_length;
  128.  
  129.         switch (id) {
  130.             case CHUNK_MPHD:
  131.                 if (m_file.read(&m_header,sizeof(MPHD)) != sizeof(MPHD))
  132.                     return error();
  133.  
  134.                 if (m_header.blockdepth != 24)
  135.                     return error();
  136.  
  137.                 m_back_layer.setSize(gsCPoint(m_header.mapwidth,m_header.mapheight));
  138.                 m_front_layer.setSize(gsCPoint(m_header.mapwidth,m_header.mapheight));
  139.             
  140.                 break;
  141.  
  142.             case CHUNK_BKDT:
  143.                 {
  144.                     m_blocks = new BLKSTR[m_header.numblockstr];
  145.  
  146.                     for (int i = 0; i < m_header.numblockstr; i++) {
  147.                         gsUDWORD size = (gsUDWORD) m_header.blockstrsize;
  148.                         if (m_file.read(&m_blocks[i],size) != size)
  149.                             return error();
  150.                         }
  151.                 }
  152.                 break;
  153.  
  154.             case CHUNK_BGFX:
  155.  
  156.                 gsCFile::setDirectory(graphics_directory);
  157.  
  158.                 if (!m_image.load("blocks.bmp"))
  159.                     return error();
  160.  
  161.                 m_image.setTileSize(gsCPoint(32,32));
  162.                 m_image.enableColourKey(gsCColour(gsMAGENTA));
  163.  
  164.                 m_back_layer.setImage(&m_image);
  165.                 m_front_layer.setImage(&m_image);
  166.  
  167.                 loaded_tiles = true;
  168.                 break;
  169.             
  170.             case CHUNK_BODY:
  171.             case CHUNK_LYR1:
  172.                 {
  173.                     gsUWORD tile;
  174.  
  175.                     for (int y = 0; y < m_header.mapheight; y++) {
  176.                         for (int x = 0; x < m_header.mapwidth; x++) {
  177.                             if (m_file.read(&tile,2) != 2)
  178.                                 return error();
  179.  
  180.                             gsCMapTile mt;
  181.  
  182.                             BLKSTR *block = &m_blocks[tile / sizeof(BLKSTR)];
  183.                             int tilesize = m_header.blockheight * m_header.blockwidth * m_header.blockdepth / 8;
  184.                             tile = (gsUWORD) (block->bgoff / tilesize);
  185.                             
  186.                             mt.setTile(tile);
  187.  
  188.                             if (tile == 0) {
  189.                                 mt.setEmpty(true);
  190.                                 mt.setHidden(true);
  191.                                 }
  192.                             else {
  193.                                 mt.setEmpty(false);
  194.                                 mt.setUserData(0,(gsUBYTE) (block->user1 & 0xFF));
  195.                                 mt.setUserData(1,(gsUBYTE) (block->user2 & 0xFF));
  196.                                 mt.setUserData(2,(gsUBYTE) (block->user3 & 0xFF));
  197.                                 mt.setUserData(3,(gsUBYTE) (block->user4 & 0xFF));
  198.  
  199.                                 gsUBYTE cflags = 0;
  200.                                 if (block->tl != 0)
  201.                                     cflags |= COLLIDE_WITH_SHIP;
  202.                                 if (block->tr != 0)
  203.                                     cflags |= COLLIDE_WITH_BULLETS;
  204.  
  205.                                 mt.setCollisionFlags(cflags);
  206.                                 }
  207.  
  208.                             if (id == CHUNK_BODY)
  209.                                 m_back_layer.setMapTile(gsCPoint(x,y),mt);
  210.                             else
  211.                                 m_front_layer.setMapTile(gsCPoint(x,y),mt);
  212.                             }
  213.                         }
  214.                 }
  215.  
  216.                 if (id == CHUNK_BODY)
  217.                     loaded_back_layer = true;
  218.                 else
  219.                     loaded_front_layer = true;
  220.                 break;
  221.  
  222.             // ignored chunks
  223.  
  224.             default:
  225.                 break;
  226.             }
  227.  
  228.         if (loaded_back_layer &&
  229.             loaded_front_layer &&
  230.             loaded_tiles)
  231.             break;
  232.  
  233.         if (!m_file.setPosition(chunk_end))
  234.             return error();
  235.         }
  236.  
  237.     if (m_blocks) {
  238.         delete [] m_blocks;
  239.         m_blocks = 0;
  240.         }
  241.  
  242.     m_file.close();
  243.  
  244.     return true;
  245. }
  246.  
  247. //-------------------------------------------------------------
  248.  
  249. void CLevel::reset()
  250. {
  251.     m_scan_y = (-m_front_layer.getPosition().getY() - 1 + 480) / m_image.getTileSize().getY();    //TEMP
  252.  
  253.     // hide special tiles
  254.     // unhide everything else
  255.  
  256.     for (int x = 0; x < m_front_layer.getSize().getX(); x++) {
  257.         for (int y = 0; y < m_front_layer.getSize().getY(); y++) {
  258.             gsCMapTile *mt = m_front_layer.getMapTile(gsCPoint(x,y));
  259.             switch (mt->getUserData(0)) {
  260.                 case ID_PICKUP:
  261.                 case ID_ALIEN:
  262.                 case ID_CHECKPOINT:
  263.                 case ID_WARP_START:
  264.                 case ID_WARP_END:
  265.                 case ID_BOSS_CONTROL:
  266.                     mt->setHidden(true);
  267.                     break;
  268.                 case ID_DESTROYABLE_TILE:
  269.                     mt->setHidden(false);
  270.                     mt->setUserData(3,0);    // reset hit count
  271.                     break;
  272.                 default:
  273.                     mt->setHidden(false);
  274.                     break;
  275.                 }
  276.             }
  277.         }
  278. }
  279.  
  280. //-------------------------------------------------------------
  281.  
  282.