home *** CD-ROM | disk | FTP | other *** search
/ Stars of Shareware: Programmierung / SOURCE.mdf / programm / msdos / pascal / rehack / graphics / dungeon2.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-26  |  15.1 KB  |  447 lines

  1. //---------------------------------------------------------------------------
  2. //
  3. //      File:           DUNGEON2.CPP
  4. //      Path:           ...\REHACK\graphics
  5. //      Version:                1.2
  6. //      Author:         Written by Chris Lampton, 5/26/91
  7. //                      modified from 6/26/93 on by Dave Boynton
  8. //                      All art by Mike Barrs
  9. //      CIS Id:            (Dave Boynton) 71043,317
  10. //      Created On:     6/26/93
  11. //      Modified On:    7/25/93
  12. //      Description:    Demonstrates tile scrolling through a dungeon and
  13. //                        the use of the display, bitmap, and pcx256 classes.
  14. //      requires:       duntiles.pcx, rehack.pcx, and rehack.pal.
  15. //                        (in the current directory)
  16. //
  17. //      Tabs:           4
  18. //
  19. //---------------------------------------------------------------------------
  20. // copyright (c) 1991,1993 by the GAMERS Forum, Rehack project team.
  21. // All rights reserved.
  22.  
  23. // A brief note on data structures:
  24. //   This program is oriented around two arrays that contain two
  25. // different forms of a 48 by 48 tile dungeon map. The first array,
  26. // dungeon[], contains a description of the dungeon in terms of
  27. // "quadTiles," each of which is constructed out of four of the
  28. // small tiles contained in the file DUNTIL4B.GRF, arranged in a
  29. // square. See the #defines below for a list of the 18 types of big
  30. // tile. During initialization, this array is translated into a
  31. // second array, dungeon2[], which contains a description of the
  32. // dungeon in terms of the actual small tiles used on the screen.
  33. // This system, which may or may not be used in the final version
  34. // of REHACK, facilitates dungeon design while allowing more versa-
  35. // tile use of the tile set.
  36.  
  37. //6/28/93 dgb: this quadTile approach has not been modified in this C++
  38. //              version, however, the underlying tiles are now Bitmaps.
  39. //7/21/93 dgb: converted data files to pcx, and implemented pcx/vga/img
  40. //                support.
  41. //
  42.  
  43. #include <alloc.h>
  44. #include <conio.h>
  45. #include <dos.h>
  46. #include <stdio.h>
  47. #include <stdlib.h>
  48. #include <string.h>
  49. #include <malloc.h>
  50. #include "..\general\types.hpp"
  51. #include "..\graphics\display.hpp"
  52. #include "..\graphics\bitmap.hpp"
  53. #include "..\graphics\pcx.hpp"
  54.  
  55. // this data is depend on the images in duntiles.pcx
  56. const word
  57.     tileNum=40,                    // Number of small tiles
  58.     tileHeight=21,                 // Height of small tile in pixels
  59.     tileWidth=21,                  // Width of small tile in pixels
  60.     blankTile=39;
  61. const Point tileSize={tileWidth,tileHeight};
  62. const word scrollRate=tileWidth;    // should be set to something that can be
  63.                         // evenly divided into both tileWidth & tileHeight
  64.  
  65. // the code in this file is flexible enough so you can move the window
  66. // around just be changing the constants here.
  67. const Point windowStart={8,6};
  68. const Point windowEnd={ 159, 157 };
  69. const Rect windowRect( windowStart, windowEnd );
  70. const word windWidth= ((windowEnd.x - windowStart.x - 1)/tileWidth) + 1;
  71. const word windHeight= ((windowEnd.y - windowStart.y - 1)/tileHeight) + 1;
  72.  
  73. // the "quad tile" approach is useful for "architecture", unnecessary for
  74. // anything else.
  75. #define  quadTileNum 18               // Number of quadTiles
  76. #define  quadTileWidth tileWidth*2   // Width of quadTile in pixels
  77. #define  quadTileHeight tileHeight*2 // Height of quadTile in pixels
  78. #define  DUNGEON_WIDTH 48               // Width of dungeon map in small tiles
  79. #define  DUNGEON_HEIGHT 48              // Height of dungeon map in small tiles
  80.  
  81. // The following #defines represent the 18 types of "quadTiles," each
  82. // constructed out of four small tiles, that are the basic building blocks
  83. // of the dungeon in this program.
  84. #define  UL 0        // Upper left corner
  85. #define  UR 1        // Upper right corner
  86. #define  FL 2        // Floor
  87. #define  LL 3        // Lower left corner
  88. #define  LR 4        // Lower right corner
  89. #define  HO 5        // Horizontal wall
  90. #define  VE 6        // Vertical wall
  91. #define  NT 7        // North 't' intersection
  92. #define  ST 8        // South 't' intersection
  93. #define  WT 9        // West 't' intersection
  94. #define  ET 10       // East 't' intersection
  95. #define  NE 11       // North wall end
  96. #define  SE 12       // South wall end
  97. #define  WE 13       // West wall end
  98. #define  EE 14       // East wall end
  99. #define  CC 15       // Central cross
  100. #define  HD 16       // Horizontal door
  101. #define  VD 17       // Vertical door
  102. char quadTile[quadTileNum][4]={       // Array of quadTile definitions for translate()
  103.     {0,10,3,4},
  104.     {1,2,6,7},
  105.     {5,5,5,5},
  106.     {8,9,13,14},
  107.     {11,12,15,16},
  108.     {10,10,15,15},
  109.     {3,12,3,12},
  110.     {26,10,6,4},
  111.     {17,9,15,15},
  112.     {19,9,3,4},
  113.     {24,12,6,12},
  114.     {18,2,3,7},
  115.     {25,12,13,27},
  116.     {20,10,13,14},
  117.     {22,2,15,23},
  118.     {21,9,6,4},
  119.     {10,10,29,30},
  120.     {3,32,3,33}
  121. };
  122. // Dungeon map defined in terms of quadTiles (see above):
  123. char dungeon[DUNGEON_HEIGHT/2][DUNGEON_WIDTH/2]={
  124.     {UL,HO,HO,HO,HO,HO,HO,HO,HO,HO,HO,HO,HO,HO,HO,HO,HO,HO,HO,NT,HO,HO,HO,UR},
  125.     {VD,FL,FL,FL,FL,FL,FL,FL,FL,FL,FL,FL,FL,FL,FL,FL,FL,FL,FL,VE,FL,FL,FL,VE},
  126.     {VE,FL,UL,HO,HO,HO,HO,UR,FL,FL,FL,FL,FL,FL,FL,FL,FL,FL,FL,WT,HO,UR,FL,VE},
  127.     {VE,FL,VE,FL,FL,FL,FL,VE,FL,FL,UL,HO,HO,HO,HO,HO,HO,UR,FL,VE,FL,VE,FL,VE},
  128.     {VE,FL,VD,FL,FL,FL,FL,VE,FL,FL,VE,FL,FL,FL,FL,FL,FL,VE,FL,VE,FL,SE,FL,VE},
  129.     {VE,FL,VE,FL,FL,FL,FL,VE,FL,FL,VE,FL,FL,FL,FL,FL,FL,VE,FL,VE,FL,FL,FL,VE},
  130.     {VE,FL,LL,HO,HO,HO,HO,LR,FL,FL,LL,HO,UR,FL,FL,UL,HO,LR,FL,VE,FL,NE,FL,VE},
  131.     {VE,FL,FL,FL,FL,FL,FL,FL,FL,FL,FL,FL,VE,FL,FL,VE,FL,FL,FL,VE,FL,VE,FL,VE},
  132.     {VE,FL,FL,FL,FL,FL,FL,FL,FL,FL,FL,FL,VE,FL,FL,VE,FL,FL,FL,WT,HO,LR,FL,VE},
  133.     {VE,FL,UL,HO,HO,HO,UR,FL,FL,FL,FL,FL,VE,FL,FL,VE,FL,UL,HO,ET,FL,FL,FL,VE},
  134.     {VE,FL,VE,FL,FL,FL,LL,HO,UR,FL,FL,FL,LL,HO,HD,LR,FL,VE,FL,VE,FL,FL,FL,VE},
  135.     {VE,FL,VE,FL,FL,FL,FL,FL,VE,FL,FL,FL,FL,FL,FL,FL,FL,VE,FL,LL,UR,FL,FL,VE},
  136.     {VE,FL,VE,FL,FL,FL,FL,FL,VE,FL,FL,FL,FL,UL,HO,HO,HO,ET,FL,FL,LL,EE,FL,VE},
  137.     {VE,FL,LL,HO,HD,HO,HO,HO,LR,FL,FL,FL,FL,VE,FL,FL,FL,LL,HO,EE,FL,FL,FL,VE},
  138.     {VE,FL,FL,FL,FL,FL,FL,FL,FL,FL,FL,FL,FL,VE,FL,NE,FL,FL,FL,FL,FL,FL,FL,VE},
  139.     {VE,FL,UL,HO,HD,UR,FL,FL,FL,FL,FL,FL,FL,WT,HO,LR,FL,WE,HO,NT,HO,UR,FL,VE},
  140.     {VE,FL,VE,FL,FL,LL,HO,UR,FL,FL,FL,FL,FL,VD,FL,FL,FL,FL,FL,VE,FL,VE,FL,VE},
  141.     {VE,FL,VE,FL,FL,FL,FL,VE,FL,FL,FL,FL,FL,VE,FL,FL,FL,FL,FL,VE,FL,VE,FL,VE},
  142.     {VE,FL,LL,HO,UR,FL,FL,LL,HO,UR,FL,FL,FL,WT,HO,HO,HO,UR,FL,VE,FL,VE,FL,VE},
  143.     {VE,FL,FL,FL,VE,FL,FL,FL,FL,VD,FL,FL,FL,VE,FL,FL,FL,VE,FL,VE,FL,VE,FL,VE},
  144.     {VE,FL,FL,FL,VE,FL,FL,FL,FL,VE,FL,FL,FL,VE,FL,NE,FL,VE,FL,VE,FL,VE,FL,VE},
  145.     {VE,FL,FL,FL,LL,HO,HO,HO,HO,LR,FL,FL,FL,VE,FL,LL,HO,ST,HO,LR,FL,SE,FL,VE},
  146.     {VE,FL,FL,FL,FL,FL,FL,FL,FL,FL,FL,FL,FL,VE,FL,FL,FL,FL,FL,FL,FL,FL,FL,VE},
  147.     {LL,HO,HO,HO,HO,HO,HO,HO,HO,HO,HO,HO,HO,ST,HO,HO,HO,HO,HO,HO,HO,HO,HO,LR},
  148. };
  149. char dungeon2[DUNGEON_HEIGHT][DUNGEON_WIDTH]; // Array for small tile map
  150.                     // filled in by translate()
  151.  
  152. // ------------- Function prototypes: -------------------------
  153. #define DebugMsg(b,s)    { if (b) {\
  154.                             printf("%s/%u: %s\n",__FILE__,__LINE__,s); \
  155.                             getch(); } }
  156.  
  157. void translate();     // convert the dungeon map into quad tiles
  158.  
  159. void draw_window(Bitmap *,word,word,word,word); // draw the dungeon window
  160.  
  161. void draw_tile(Bitmap *aBitmap,word tnum, Point &destAt, Point &srcOffset);
  162.                             // draw one tile in the dungeon window
  163.  
  164. BitmapArray *tiles;        // bitmap with all the tiles, from duntiles.pcx
  165. Bitmap *background;        // background screen, from rehack.pcx
  166. byte colregs[3*256];    // Array of color register values, from rehack.pal
  167.  
  168. FILE *debugFile=NULL;    // will be "dungeon2.dbg", if opened
  169. bool doDebug=false;
  170.  
  171. // ********************************************************************
  172. //
  173. //
  174. // ********************************************************************
  175. int main(int argc, char *argv[])
  176. {
  177.     bool    doRetrace, doDirect;
  178.     doRetrace=doDirect=doDebug=false;
  179.  
  180.     while ( argc > 1 )
  181.     {
  182.         if ( ( *argv[1] == '/' ) || ( *argv[1] == '-' ) )
  183.         {
  184.             if ( *(argv[1]+1) == 'f' )
  185.                 doRetrace=true;
  186.             if ( *(argv[1]+1) == 'b' )
  187.                 doDirect=true;
  188.             if ( ( *(argv[1]+1) == 'd' ) &&
  189.                  ( (debugFile=fopen("dungeon2.dbg","w")) != NULL ) )
  190.             {
  191.                 doDebug=true;
  192.                 fprintf(debugFile,"draw_window(,xtile,ytile,xoff,yoff)\n");
  193.                 fprintf(debugFile,"draw_tile(,tnum,xpos,ypos,xoff,yoff,xext,yext)\n");
  194.             }
  195.         }
  196.         argc--;
  197.         argv++;
  198.     }
  199.     translate();   // Translate quadTiles into small tiles
  200.  
  201.     DisplayManager  display(doRetrace);
  202.  
  203.     // ------------------- read files rehack.pal, rehack.pcx -------------
  204.     FILE    *fp;
  205.     // Load palette from file "rehack.pal" into colregs[]
  206.     if ( (fp=fopen("rehack.pal","rb")) == NULL )
  207.     {
  208.         printf("Couldn't open 'rehack.pal'.\n");
  209.         return 1;
  210.     }
  211.     if ( fread(&colregs,768,1,fp) != 1 )
  212.     {
  213.         fclose(fp);
  214.         printf("Couldn't load 'rehack.pal'.\n");
  215.         return 1;
  216.     }
  217.  
  218.     display.setMode(0x13); // Set graphics mode to 13h
  219.     display.blankScreen(); // avoid trashy display while loading
  220.     display.setPalette(colregs);  // Set palette to palette in tile file
  221.  
  222.     // ----------- load in background image ------------------
  223.     background= new Bitmap("rehack.pcx");
  224.     if ( doDebug )
  225.     {
  226.         assert( background->validFlag );
  227.         assert( background->bits );
  228.         assert(heapcheck() != _HEAPCORRUPT);
  229.     }
  230.     display.putBitmap(background);
  231.     // now that we've displayed background, we could probably shuffle it out
  232.     // to xms memory, since we won't use it that often.
  233.  
  234.     // -------------- Load tiles from duntiles.pcx ----------------
  235.     tiles= new BitmapArray("duntiles.pcx", tileSize, 10, 4);
  236.     if ( doDebug )
  237.     {
  238.         assert( tiles->validFlag );
  239.         assert( tiles->bits );
  240.         assert(heapcheck() != _HEAPCORRUPT);
  241.     }
  242.  
  243.     // --------------------------------------------------
  244.     // create a dungeon window and draw the initial state into it
  245.     // --------------------------------------------------
  246.     Bitmap  *canvas;
  247.     if ( doDirect )
  248.     {
  249.         canvas=display.getDirectBitmap();
  250.         assert( canvas->validFlag );
  251.         assert( canvas->bits );
  252.         canvas->setViewPort((Rect &)windowRect);
  253.     } else {
  254.         canvas=new Bitmap(windowRect); //viewPort & ownerBounds are set
  255.         assert( canvas->validFlag );
  256.         assert( canvas->bits );
  257.     }
  258.  
  259.     if ( doDebug )
  260.     {
  261.         assert(heapcheck() != _HEAPCORRUPT);
  262.     }
  263.  
  264.     // Draw initial contents of dungeon window in graphics buffer
  265.     draw_window(canvas,0,0,0,0);
  266.  
  267.     // Move graphics buffer to the screen. If canvas is a "direct" screenmap,
  268.     // putBitmap() just returns.
  269.     display.putBitmap(canvas);
  270.     display.unblankScreen();
  271.  
  272.     // Main program loop
  273.     // Waits for cursor arrow to be pressed, then redraws dungeon window
  274.     char    ch;
  275.     int    row=0,column=0,xoff,yoff;
  276.     do
  277.     {
  278.         ch=getch();
  279.         if (ch==0)
  280.         {
  281.             ch=getch();
  282.             if ( doDebug )
  283.                 fprintf(debugFile,"<do loop> getch()=%u\n", ch);
  284.             switch (ch)
  285.             {
  286.             case 72: // Up arrow, so scroll up
  287.                 if (row>0)
  288.                 {
  289.                     --row;
  290.                     // display the non-zero yoff's, let the end-of-switch
  291.                     // draw_window take care of the zero offset.
  292.                     for ( yoff=(tileHeight-scrollRate); yoff>0;
  293.                        yoff-=scrollRate )
  294.                     {
  295.                         draw_window(canvas,column,row,0,yoff);
  296.                         display.putBitmap(canvas);
  297.                     }
  298.                 }
  299.                 break;
  300.  
  301.             case 80: // Down arrow, so scroll down
  302.                 if (row<=(DUNGEON_HEIGHT-windHeight))
  303.                 {
  304.                     // display the non-zero yoff's, let the end-of-switch
  305.                     // draw_window take care of the zero offset.
  306.                     for (yoff=scrollRate; yoff<tileHeight; yoff+=scrollRate)
  307.                     {
  308.                         draw_window(canvas,column,row,0,yoff);
  309.                         display.putBitmap(canvas);
  310.                     }
  311.                     row++;
  312.                 }
  313.                 break;
  314.  
  315.             case 75: // Left arrow, so scroll left
  316.                 if (column>0)
  317.                 {
  318.                     --column;
  319.                     // display the non-zero xoff's, let the end-of-switch
  320.                     // draw_window take care of the zero offset.
  321.                     for (xoff=tileWidth-scrollRate; xoff>0; xoff-=scrollRate)
  322.                     {
  323.                         draw_window(canvas,column,row,xoff,0);
  324.                         display.putBitmap(canvas);
  325.                     }
  326.                 }
  327.                 break;
  328.  
  329.             case 77: // Right arrow, so scroll right
  330.                 if (column<=(DUNGEON_WIDTH-windWidth))
  331.                 {
  332.                     // display the non-zero xoff's, let the end-of-switch
  333.                     // draw_window take care of the zero offset.
  334.                     for (xoff=scrollRate; xoff<tileWidth; xoff+=scrollRate)
  335.                     {
  336.                         draw_window(canvas,column,row,xoff,0);
  337.                         display.putBitmap(canvas);
  338.                         if ( doDebug ) getch();
  339.                     }
  340.                     column++;
  341.                 }
  342.                 break;
  343.  
  344.             } // end switch (ch)
  345.             draw_window(canvas,column,row,0,0);
  346.             display.putBitmap(canvas);
  347.             if ( doDebug )
  348.                 assert(heapcheck() != _HEAPCORRUPT);
  349.  
  350.         } /* end if (ch==0) */
  351.     } while (ch!=27);  // Terminate if ESC pressed
  352.  
  353.     display.setMode(3);        // Restore DOS screen mode
  354.     if ( doDebug )
  355.         fclose(debugFile);
  356.     return 0;
  357. }
  358.  
  359. // ********************************************************************
  360. // draw_window(int xtile,int ytile,int xoff,int yoff)
  361. // Draws dungeon window with dimensions (in small tiles) of windWidth,
  362. // windHeight at screen coordinates windowRect. The first row and
  363. // column of tiles is moved by xoff, yoff pixels.
  364. // ********************************************************************
  365. void draw_window(Bitmap *aBitmap,
  366.     word xtile,word ytile,        // current upper left position in the
  367.                                 // dungeon map.
  368.     word xoff,word yoff)        // offset into tile for sequenced scrolls
  369. {
  370.     if ( doDebug)
  371.     {
  372.         fprintf(debugFile,"draw_window(, %i,%i, %i,%i)\n",
  373.                             xtile, ytile, xoff, yoff);
  374.     }
  375.     int     x,y, quadX, quadY;
  376.     Point pos, offset;
  377.  
  378.     for (x=0; x<(windWidth+1);x++)
  379.         for (y=0; y<(windHeight+1);y++) {
  380.             quadX=xtile+x;
  381.             if ( quadX == 0 ) {
  382.                 offset.x=0;
  383.                 pos.x=0;
  384.             } else {
  385.                 offset.x=xoff;
  386.                 pos.x=x*tileWidth-xoff;
  387.             }
  388.             quadY=ytile+y;
  389.             if ( quadY == 0 ) {
  390.                 offset.y=0;
  391.                 pos.y=0;
  392.             } else {
  393.                 offset.y=yoff;
  394.                 pos.y=y*tileHeight-yoff;
  395.             }
  396.             if ( (quadX < DUNGEON_WIDTH) && (quadY < DUNGEON_HEIGHT) )
  397.                 draw_tile(aBitmap, dungeon2[quadY][quadX], pos, offset);
  398.             else
  399.                 draw_tile(aBitmap, blankTile, pos, offset);
  400.         }
  401. }
  402.  
  403. // ********************************************************************
  404. // Draw tile tnum starting at pixel srcOffset (within tile) at
  405. // screen coordinates destAt (local to windowRect)
  406. // ********************************************************************
  407. void draw_tile(Bitmap *aBitmap,word tnum, Point &destAt, Point &srcOffset)
  408. {
  409.     tiles->setIndex(tnum);  // this sets viewPort to the entire size of
  410.                             // the tile needed.
  411.  
  412.     Rect r=tiles->getViewPort();
  413.     if ( srcOffset.x > 0 )
  414.         r.topLeft.x += srcOffset.x;
  415.     if ( srcOffset.y > 0 )
  416.         r.topLeft.y += srcOffset.y;
  417.     tiles->setViewPort(r);
  418.     tiles->paint(aBitmap, destAt);
  419. }
  420.  
  421. // **********************************************
  422. // convert dungeon map into small tile format
  423. // **********************************************
  424. void translate()
  425. {
  426.     int     x,y;
  427.  
  428.    // Translate quadTiles to small tiles
  429.  
  430.     for (x=0;x<DUNGEON_WIDTH/2;x++)
  431.         for (y=0;y<DUNGEON_HEIGHT/2;y++) {
  432.             dungeon2[y*2][x*2]=quadTile[dungeon[y][x]][0];
  433.             dungeon2[y*2][x*2+1]=quadTile[dungeon[y][x]][1];
  434.             dungeon2[y*2+1][x*2]=quadTile[dungeon[y][x]][2];
  435.             dungeon2[y*2+1][x*2+1]=quadTile[dungeon[y][x]][3];
  436.         }
  437.  
  438.    // Add corners of doors to tiles next to door tiles
  439.  
  440.     for (x=0;x<DUNGEON_WIDTH/2;x++)
  441.         for (y=0;y<DUNGEON_HEIGHT/2;y++) {
  442.             if (dungeon[y][x]==HD) dungeon2[y*2+1][x*2-1]=28;
  443.             if (dungeon[y][x]==VD) dungeon2[y*2+2][x*2+1]=34;
  444.         }
  445. }
  446.  
  447.