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

  1. //-------------------------------------------------------------
  2. //
  3. // Class:    CLevel
  4. //
  5. // Author:    John M Phillips
  6. //
  7. // Started:    06/05/00
  8. //
  9. // Base:    None
  10. //
  11. // Derived:    None
  12. //
  13. //-------------------------------------------------------------
  14.  
  15. #include "demo4.h"
  16.  
  17. //-------------------------------------------------------------
  18.  
  19. CLevel::CLevel()
  20. {
  21.     m_blocks = 0;
  22. }
  23.  
  24. //-------------------------------------------------------------
  25.  
  26. CLevel::~CLevel()
  27. {
  28.     destroy();
  29. }
  30.  
  31. //-------------------------------------------------------------
  32.  
  33. void CLevel::destroy()
  34. {
  35.     m_back_layer.destroy();
  36.     m_front_layer.destroy();
  37.     m_image.destroy();
  38. }
  39.  
  40. //-------------------------------------------------------------
  41.  
  42. bool CLevel::readUDWORD(gsUDWORD& d)
  43. {
  44.     gsUBYTE b[4];
  45.  
  46.     if (m_file.read(b,4) != 4)
  47.         return false;
  48.  
  49.     d = (((gsUDWORD) b[0]) << 24) +
  50.         (((gsUDWORD) b[1]) << 16) + 
  51.         (((gsUDWORD) b[2]) << 8) + 
  52.         ((gsUDWORD) b[3]);
  53.  
  54.     return true;
  55. }
  56.  
  57. //-------------------------------------------------------------
  58.  
  59. bool CLevel::readUWORD(gsUWORD& w)
  60. {
  61.     gsUBYTE b[2];
  62.  
  63.     if (m_file.read(b,2) != 2)
  64.         return false;
  65.  
  66.     w =    (((gsUWORD) b[0]) << 8) + 
  67.         ((gsUWORD) b[1]);
  68.  
  69.     return true;
  70. }
  71.  
  72. //-------------------------------------------------------------
  73.  
  74. bool CLevel::error()
  75. {
  76.     m_file.close();
  77.     return false;
  78. }
  79.  
  80. //-------------------------------------------------------------
  81.     
  82. #define CHUNK4(a,b,c,d) ((gsUDWORD(a) << 24) + (gsUDWORD(b) << 16) + \
  83.                         (gsUDWORD(c) << 8) + gsUDWORD(d))
  84.  
  85. const gsUDWORD CHUNK_FORM = CHUNK4('F','O','R','M');
  86. const gsUDWORD CHUNK_FMAP = CHUNK4('F','M','A','P');
  87. const gsUDWORD CHUNK_MPHD = CHUNK4('M','P','H','D');
  88. const gsUDWORD CHUNK_BKDT = CHUNK4('B','K','D','T');
  89. const gsUDWORD CHUNK_BGFX = CHUNK4('B','G','F','X');
  90. const gsUDWORD CHUNK_BODY = CHUNK4('B','O','D','Y');
  91. const gsUDWORD CHUNK_LYR1 = CHUNK4('L','Y','R','1');
  92.  
  93. bool CLevel::load(const char *filename,const char *graphics_directory)
  94. {
  95.     destroy();
  96.  
  97.     gsCFile::setDirectory(DIRECTORY_LEVELS);
  98.  
  99.     if (!m_file.open(filename,gsFILE_READ))
  100.         return false;
  101.  
  102.     gsUDWORD id = 0;
  103.  
  104.     if (!readUDWORD(id) ||
  105.         id != CHUNK_FORM)
  106.         return error();
  107.  
  108.     if (!readUDWORD(id))
  109.         return error();
  110.  
  111.     if (!readUDWORD(id) ||
  112.         id != CHUNK_FMAP)
  113.         return error();
  114.  
  115.     bool loaded_back_layer = false;
  116.     bool loaded_front_layer = false;
  117.     bool loaded_tiles = false;
  118.  
  119.     for (;;) {
  120.         if (!readUDWORD(id))
  121.             return error();
  122.  
  123.         gsUDWORD chunk_length = 0;
  124.         
  125.         if (!readUDWORD(chunk_length))
  126.             return error();
  127.  
  128.         gsUDWORD chunk_end = m_file.getPosition() + chunk_length;
  129.  
  130.         switch (id) {
  131.             case CHUNK_MPHD:
  132.                 if (m_file.read(&m_header,sizeof(MPHD)) != sizeof(MPHD))
  133.                     return error();
  134.  
  135.                 if (m_header.blockdepth != 24)
  136.                     return error();
  137.  
  138.                 m_back_layer.setSize(gsCPoint(m_header.mapwidth,m_header.mapheight));
  139.                 m_front_layer.setSize(gsCPoint(m_header.mapwidth,m_header.mapheight));
  140.             
  141.                 break;
  142.  
  143.             case CHUNK_BKDT:
  144.                 {
  145.                     m_blocks = new BLKSTR[m_header.numblockstr];
  146.  
  147.                     for (int i = 0; i < m_header.numblockstr; i++) {
  148.                         gsUDWORD size = (gsUDWORD) m_header.blockstrsize;
  149.                         if (m_file.read(&m_blocks[i],size) != size)
  150.                             return error();
  151.                         }
  152.                 }
  153.                 break;
  154.  
  155.             case CHUNK_BGFX:
  156.  
  157.                 gsCFile::setDirectory(graphics_directory);
  158.  
  159.                 if (!m_image.load("blocks.bmp"))
  160.                     return error();
  161.  
  162.                 m_image.setTileSize(gsCPoint(32,32));
  163.                 m_image.enableColourKey(gsCColour(gsMAGENTA));
  164.  
  165.                 m_back_layer.setImage(&m_image);
  166.                 m_front_layer.setImage(&m_image);
  167.  
  168.                 loaded_tiles = true;
  169.                 break;
  170.             
  171.             case CHUNK_BODY:
  172.             case CHUNK_LYR1:
  173.                 {
  174.                     gsUWORD tile;
  175.  
  176.                     for (int y = 0; y < m_header.mapheight; y++) {
  177.                         for (int x = 0; x < m_header.mapwidth; x++) {
  178.                             if (m_file.read(&tile,2) != 2)
  179.                                 return error();
  180.  
  181.                             gsCMapTile mt;
  182.  
  183.                             BLKSTR *block = &m_blocks[tile / sizeof(BLKSTR)];
  184.                             int tilesize = m_header.blockheight * m_header.blockwidth * m_header.blockdepth / 8;
  185.                             tile = (gsUWORD) (block->bgoff / tilesize);
  186.                             
  187.                             mt.setTile(tile);
  188.  
  189.                             if (tile == 0) {
  190.                                 mt.setEmpty(true);
  191.                                 mt.setHidden(true);
  192.                                 }
  193.                             else {
  194.                                 mt.setEmpty(false);
  195.                                 mt.setUserData(0,(gsUBYTE) (block->user1 & 0xFF));
  196.                                 mt.setUserData(1,(gsUBYTE) (block->user2 & 0xFF));
  197.                                 mt.setUserData(2,(gsUBYTE) (block->user3 & 0xFF));
  198.                                 mt.setUserData(3,(gsUBYTE) (block->user4 & 0xFF));
  199.  
  200.                                 gsUBYTE cflags = 0;
  201.                                 if (block->tl != 0)
  202.                                     cflags |= COLLIDE_WITH_SHIP;
  203.                                 if (block->tr != 0)
  204.                                     cflags |= COLLIDE_WITH_BULLETS;
  205.  
  206.                                 mt.setCollisionFlags(cflags);
  207.                                 }
  208.  
  209.                             if (id == CHUNK_BODY)
  210.                                 m_back_layer.setMapTile(gsCPoint(x,y),mt);
  211.                             else
  212.                                 m_front_layer.setMapTile(gsCPoint(x,y),mt);
  213.                             }
  214.                         }
  215.                 }
  216.  
  217.                 if (id == CHUNK_BODY)
  218.                     loaded_back_layer = true;
  219.                 else
  220.                     loaded_front_layer = true;
  221.                 break;
  222.  
  223.             // ignored chunks
  224.  
  225.             default:
  226.                 break;
  227.             }
  228.  
  229.         if (loaded_back_layer &&
  230.             loaded_front_layer &&
  231.             loaded_tiles)
  232.             break;
  233.  
  234.         if (!m_file.setPosition(chunk_end))
  235.             return error();
  236.         }
  237.  
  238.     if (m_blocks) {
  239.         delete [] m_blocks;
  240.         m_blocks = 0;
  241.         }
  242.  
  243.     m_file.close();
  244.  
  245.     return true;
  246. }
  247.  
  248. //-------------------------------------------------------------
  249.  
  250. void CLevel::reset()
  251. {
  252.     m_boss_active = false;
  253.  
  254.     m_scan_y = (-m_front_layer.getPosition().getY() - 1 + 480) / m_image.getTileSize().getY();    //TEMP
  255.  
  256.     // hide special tiles
  257.     // unhide everything else
  258.  
  259.     for (int x = 0; x < m_front_layer.getSize().getX(); x++) {
  260.         for (int y = 0; y < m_front_layer.getSize().getY(); y++) {
  261.             gsCMapTile *mt = m_front_layer.getMapTile(gsCPoint(x,y));
  262.             switch (mt->getUserData(0)) {
  263.                 case ID_PICKUP:
  264.                 case ID_ALIEN:
  265.                 case ID_CHECKPOINT:
  266.                 case ID_WARP_START:
  267.                 case ID_WARP_END:
  268.                 case ID_BOSS_CONTROL:
  269.                     mt->setHidden(true);
  270.                     break;
  271.                 case ID_DESTROYABLE_TILE:
  272.                     mt->setHidden(false);
  273.                     mt->setUserData(3,0);    // reset hit count
  274.                     break;
  275.                 default:
  276.                     mt->setHidden(false);
  277.                     break;
  278.                 }
  279.             }
  280.         }
  281. }
  282.  
  283. //-------------------------------------------------------------
  284.  
  285. void CLevel::scanForNewActors(CScene *scene)
  286. {
  287.     gsCScreen *screen = gsCApplication::getScreen();
  288.  
  289.     if (!screen)
  290.         return;
  291.  
  292.     gsCRect screen_rect = screen->getRect();
  293.     gsCRect source_rect(gsCPoint(0,0),m_front_layer.getSizeInPixels());
  294.     gsCRect dest_rect = source_rect;
  295.     dest_rect.move(m_front_layer.getPosition());
  296.     screen_rect.clip(source_rect,dest_rect);
  297.  
  298.     if (dest_rect.isEmpty())
  299.         return;
  300.     
  301.     // convert back to tile coords
  302.  
  303.     int top = source_rect.getTop() / m_image.getTileSize().getY();
  304.  
  305.     // get row above screen
  306.  
  307.     top--;
  308.  
  309.     if (top < 0)
  310.         return;
  311.  
  312.     while (m_scan_y >= top) {
  313.  
  314.         for (int x = 0; x < m_front_layer.getSize().getX(); x++) {
  315.  
  316.             gsCMapTile *mt = m_front_layer.getMapTile(gsCPoint(x,m_scan_y));
  317.  
  318.             if (!mt->isEmpty()) {
  319.                 gsUBYTE id = mt->getUserData(0);
  320.                 gsUBYTE type = mt->getUserData(1);
  321.                 gsUBYTE grade = mt->getUserData(2);
  322.                 gsUBYTE size = mt->getUserData(3);
  323.  
  324.                 gsCVector pos((float) x * m_image.getTileSize().getX(),
  325.                               (float) m_scan_y * m_image.getTileSize().getY());
  326.  
  327.                 pos += gsCVector((float) m_image.getTileSize().getX() / 2.f,
  328.                                  (float) m_image.getTileSize().getY() / 2.f);
  329.  
  330.                 switch (id) {
  331.                     case ID_PICKUP:
  332.                         break;
  333.  
  334.                     case ID_ALIEN:
  335.                         // aliens
  336.                         
  337.                         switch (type) {
  338.                             case RUSHER:
  339.                                 {
  340.                                     CRusher *r = new CRusher();
  341.                                     scene->addActor(r);
  342.                                     r->setPosition(pos);
  343.                                     r->setVelocity(gsCVector(0.f,2.f));
  344.                                     r->activate();
  345.                                 }
  346.                                 break;
  347.  
  348.                             default:
  349.  
  350.                                 CBigExplosion *x = new CBigExplosion();
  351.                                 scene->addActor(x);
  352.                                 x->setPosition(pos);
  353.                                 x->activate();
  354.                                 break;
  355.                             }
  356.                         break;
  357.  
  358.                     case ID_CHECKPOINT:
  359.                     case ID_WARP_START:
  360.                     case ID_WARP_END:
  361.                     case ID_BOSS_MOUTH:
  362.                     case ID_BOSS_EYE:
  363.                     case ID_BOSS_CONTROL:
  364.                         break;
  365.                     }
  366.                 }
  367.             }
  368.  
  369.         m_scan_y--;
  370.         }
  371. }
  372.  
  373. //-------------------------------------------------------------
  374.