// This source file contains the functions needed to process floors. // (c) 1995 ACK Software (Lary Myers) #include "ack3d.h" #include "ackeng.h" #include "ackext.h" #define MAX_F_VIEWHALFHEIGHT 50 void DrawBackDrop(void); extern long FloorCosTable[]; extern short gWinStartX; extern short gWinStartY; extern short gWinEndX; extern short gWinHalfHeight; extern UCHAR *gScrnBufferCenter; extern long WallDistTable[]; long zdTable[VIEW_WIDTH][50]; long mFactor; long dFactor; //ħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħ // Internal function called during the initialize process to setup the // floor and light shading arrays. //ħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħ void SetupFloors(ACKENG *ae) { short i,a; int ht,scanline,ht1; int Scale_Fac; long scan1,scan2,f; long x,y,dist; long Lastx,Lasty; for ( i=0; i<12;i++ ) scantables[i] = (char*)(ae->PalTable + (7*256)); for ( i=12;i<24;i++ ) scantables[i] = (char*)(ae->PalTable + (6*256)); for ( i=24;i<36;i++ ) scantables[i] = (char*)(ae->PalTable + (5*256)); for ( i=36;i<48;i++ ) scantables[i] = (char*)(ae->PalTable + (4*256)); for ( i=48;i<60;i++ ) scantables[i] = (char*)(ae->PalTable + (3*256)); for ( i=60;i<72;i++ ) scantables[i] = (char*)(ae->PalTable + (2*256)); for ( i=72;i<84;i++ ) scantables[i] = (char*)(ae->PalTable + (1*256)); for ( i=84;i<96;i++ ) scantables[i] = (char*)(ae->PalTable); Scale_Fac = (89 - ViewHeight) * 5; ht = 89 - ViewHeight; ht *= Scale_Fac; for (i = 0; i < VIEW_WIDTH; i++) { f = FloorCosTable[i]; zdTable[i][0] = 0; for (scanline = 1; scanline < MAX_F_VIEWHALFHEIGHT; scanline++) { scan2 = ht / scanline; zdTable[i][scanline] = (f * scan2) >> 15; if (zdTable[i][scanline-1] < zdTable[i][scanline]) zdTable[i][scanline-1] = zdTable[i][scanline]; } } // Some debugging values for internal use mFactor = 10368; dFactor = 160; } // Optimization attempts were made with drawing the rotating background // as the ceiling was being drawn and drawing the entire background before // drawing any ceiling tiles or walls. The former seemed to be faster // in most cases, so the define below was used to toggle between the two // methods. #define DRAW_BACK 1 //ħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħ // Draws the floor and ceiling horizontally. //ħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħ void AckDrawFloorHz(void) { int i,col,row,ht,Rcol,EndCol,BegCol; int Scale_Fac,ScaleHt; UCHAR *scr,*fscr,*bmp,*scrCeil,*cscr; UCHAR *Rscr,*Rfscr,*RscrCeil,*Rcscr; UCHAR *ba,*ba1,*Rba,*Rba1; short va,va1; long LastDist,scan2; long cv,sv,dist,x,y,bx,by,mPos,bPos,wdist,bcol; long Rbcol,Rwdist,xp,yp; long *zd,*wPtr,*RwPtr,*xyPtr; long fcv; UCHAR ch; USHORT bCode; #if !(DRAW_BACK) DrawBackDrop(); // Draw entire background #endif BegCol = gWinStartX; EndCol = gWinEndX; // Get the starting offset of the center row of the view scr = gScrnBufferCenter + BegCol; // Get the left side of the POV view va = PlayerAngle - INT_ANGLE_32; // Check for wrap-around if (va < 0) va += INT_ANGLE_360; // Adjust the viewing angle based on the starting view column va += BegCol; // and check for wrap-around if (va >= INT_ANGLE_360) va -= INT_ANGLE_360; // Get the starting column for the background, there are 640 // columns possible, so the remainder when we divide is where // we want to begin displaying bcol = va % 640; // Temporarily hold onto the view height / 2 ht = gWinHalfHeight; // Since our horizon should always have some form of wall or object, // no matter how far away it is, we can optimize alittle here by not // drawing the first few horizon rows (it does actually save time!). // Start 5 video rows above the center row scrCeil = scr - 1600; // Start 6 video rows below the center row scr += 1920; // Initial right side of view Rcol = 319; wPtr = &WallDistTable[BegCol]; // Get pointers to avoid indexing RwPtr = &WallDistTable[Rcol]; // The ScaleHt is used to determine the distance from the player for each // row of the floor and ceiling. The value 89 was arrived at based on a // reasonable height above the floor that the player is standing. By // experimenting with this value, the effect of jumping up and down can // be achieved, (as long as the walls and objects are made to jump by the // same amount). Scale_Fac = (89 - ViewHeight) * 5; ScaleHt = 89 - ViewHeight; ScaleHt *= Scale_Fac; // Here we loop through each column of the viewing window for (col = BegCol; col < EndCol; col += 2) { // Pick up the cosine and sine values for the current angle cv = CosTable[va]; sv = SinTable[va]; // Point to the left side of the current floor and ceiling columns fscr = scr; cscr = scrCeil; // Advance the columns for the next pass scr += 2; scrCeil += 2; // Pick up the current distance to the wall that was found for the // current column wdist = *wPtr; // Advance the wall distance pointer for the next pass wPtr += 2; #if DRAW_BACK // Pick up the pointer to the background image for the current column ba = BackArray[bcol++]; // Check for wrap-around in our 640 column image if (bcol > 639) bcol = 0; // Pick up the next column as well since the floor and ceiling are // always done in low resolution ba1 = BackArray[bcol++]; if (bcol > 639) bcol = 0; ba += ht; ba1 += ht; #endif // Initialize a last distance variable LastDist = -1; // Our floor cosine is used to counteract a fisheye effect fcv = FloorCosTable[col]; for (row = 6; row <= ht; row++) { scan2 = ScaleHt / row; // Get the distance for the current column and row position dist = (fcv * scan2) >> 15; // If we're still closer than any wall if (dist < wdist) { // Do some extra calculations if it's a new distance from last time // (Sometimes our distance works out to be the same so we can avoid // the next few lines) if (dist != LastDist) { x = xPglobal + ((cv * dist) >> 16); y = yPglobal + ((sv * dist) >> 16); LastDist = dist; } mPos = (y & 0xFC0) + (x >> 6); // Calc the Map Posn if (mPos < 0L || mPos > 4095L) continue; bPos = (y & 63) + ((x & 63)<<6); // Calc the Bitmap Pixel // Get the bitmap number for our floor bCode = FloorMap[mPos]; // And use it to pull the actual bitmap from our array of wall bitmaps bmp = WallbMaps[bCode]; // Make sure it's really a bitmap and then get the actual pixel to display if (bmp != NULL) ch = bmp[bPos]; // Place the pixel in this column as well as the next. Since we have a // scattering effect we can display in low resolution without too much // loss in detail. This really speeds up the drawing of the floor and // ceiling. *fscr = ch; // Put it into two locations fscr[1] = ch; // for low resolution // Only draw a ceiling pixel if there is a ceiling tile placed in the map // This gives the effect of seeing the background through holes in the ceiling if ((bCode = CeilMap[mPos]) != 0) { bmp = WallbMaps[bCode]; if (bmp != NULL) ch = bmp[bPos]; *cscr = ch; cscr[1] = ch; } #if DRAW_BACK // If no ceiling is drawn, then we need to draw the background image else { *cscr = *ba; cscr[1] = *ba1; } #endif } fscr += 320; // Advance our screen position for the floor cscr -= 320; // and the ceiling #if DRAW_BACK // Advance the pointers to the background image for the next pass ba--; ba1--; #endif } // Advance our current viewing angle by 2 since we are in low resolution va += 2; // and check for wrap-around if (va >= INT_ANGLE_360) va -= INT_ANGLE_360; } } //ħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħ // Draws the floor and ceiling horizontally. //ħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħ void AckDrawCeilingOnlyNS(void) { int i,col,row,ht,Rcol,EndCol,BegCol; int Scale_Fac,ScaleHt; UCHAR *scr,*fscr,*bmp,*scrCeil,*cscr; UCHAR *Rscr,*Rfscr,*RscrCeil,*Rcscr; UCHAR *ba,*ba1,*Rba,*Rba1; short va,va1; long LastDist,scan2; long cv,sv,dist,x,y,bx,by,mPos,bPos,wdist,bcol; long Rbcol,Rwdist,xp,yp; long *zd,*wPtr,*RwPtr,*xyPtr; long fcv; UCHAR ch; USHORT bCode; #if !(DRAW_BACK) DrawBackDrop(); // Draw entire background #endif BegCol = gWinStartX; EndCol = gWinEndX; // Get the starting offset of the center row of the view scr = gScrnBufferCenter + BegCol; // Get the left side of the POV view va = PlayerAngle - INT_ANGLE_32; // Check for wrap-around if (va < 0) va += INT_ANGLE_360; // Adjust the viewing angle based on the starting view column va += BegCol; // and check for wrap-around if (va >= INT_ANGLE_360) va -= INT_ANGLE_360; // Get the starting column for the background, there are 640 // columns possible, so the remainder when we divide is where // we want to begin displaying bcol = va % 640; // Temporarily hold onto the view height / 2 ht = gWinHalfHeight; // Since our horizon should always have some form of wall or object, // no matter how far away it is, we can optimize alittle here by not // drawing the first few horizon rows (it does actually save time!). // Start 5 video rows above the center row scrCeil = scr - 1600; // Initial right side of view Rcol = 319; wPtr = &WallDistTable[BegCol]; // Get pointers to avoid indexing RwPtr = &WallDistTable[Rcol]; // The ScaleHt is used to determine the distance from the player for each // row of the floor and ceiling. The value 89 was arrived at based on a // reasonable height above the floor that the player is standing. By // experimenting with this value, the effect of jumping up and down can // be achieved, (as long as the walls and objects are made to jump by the // same amount). Scale_Fac = (89 - ViewHeight) * 5; ScaleHt = 89 - ViewHeight; ScaleHt *= Scale_Fac; // Here we loop through each column of the viewing window for (col = BegCol; col < EndCol; col += 2) { // Pick up the cosine and sine values for the current angle cv = CosTable[va]; sv = SinTable[va]; // Point to the left side of the current ceiling columns cscr = scrCeil; // Advance the columns for the next pass scrCeil += 2; // Pick up the current distance to the wall that was found for the // current column wdist = *wPtr; // Advance the wall distance pointer for the next pass wPtr += 2; #if DRAW_BACK // Pick up the pointer to the background image for the current column ba = BackArray[bcol++]; // Check for wrap-around in our 640 column image if (bcol > 639) bcol = 0; // Pick up the next column as well since the floor and ceiling are // always done in low resolution ba1 = BackArray[bcol++]; if (bcol > 639) bcol = 0; ba += ht; ba1 += ht; #endif // Initialize a last distance variable LastDist = -1; // Our floor cosine is used to counteract a fisheye effect fcv = FloorCosTable[col]; for (row = 6; row <= ht; row++) { scan2 = ScaleHt / row; // Get the distance for the current column and row position dist = (fcv * scan2) >> 15; // If we're still closer than any wall if (dist < wdist) { // Do some extra calculations if it's a new distance from last time // (Sometimes our distance works out to be the same so we can avoid // the next few lines) if (dist != LastDist) { x = xPglobal + ((cv * dist) >> 16); y = yPglobal + ((sv * dist) >> 16); LastDist = dist; } mPos = (y & 0xFC0) + (x >> 6); // Calc the Map Posn if (mPos < 0L || mPos > 4095L) continue; bPos = (y & 63) + ((x & 63)<<6); // Calc the Bitmap Pixel // Only draw a ceiling pixel if there is a ceiling tile placed in the map // This gives the effect of seeing the background through holes in the ceiling if ((bCode = CeilMap[mPos]) != 0) { bmp = WallbMaps[bCode]; if (bmp != NULL) ch = bmp[bPos]; *cscr = ch; cscr[1] = ch; } #if DRAW_BACK // If no ceiling is drawn, then we need to draw the background image else { *cscr = *ba; cscr[1] = *ba1; } #endif } cscr -= 320; // and the ceiling #if DRAW_BACK // Advance the pointers to the background image for the next pass ba--; ba1--; #endif } // Advance our current viewing angle by 2 since we are in low resolution va += 2; // and check for wrap-around if (va >= INT_ANGLE_360) va -= INT_ANGLE_360; } } //ħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħ // Draws the floor and ceiling horizontally. //ħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħ void AckDrawFloorOnlyNS(void) { int i,col,row,ht,Rcol,EndCol,BegCol; int Scale_Fac,ScaleHt; UCHAR *scr,*fscr,*bmp,*scrCeil,*cscr; UCHAR *Rscr,*Rfscr,*RscrCeil,*Rcscr; UCHAR *ba,*ba1,*Rba,*Rba1; short va,va1; long LastDist,scan2; long cv,sv,dist,x,y,bx,by,mPos,bPos,wdist,bcol; long Rbcol,Rwdist,xp,yp; long *zd,*wPtr,*RwPtr,*xyPtr; long fcv; UCHAR ch; USHORT bCode; #if !(DRAW_BACK) DrawBackDrop(); // Draw entire background #endif BegCol = gWinStartX; EndCol = gWinEndX; // Get the starting offset of the center row of the view scr = gScrnBufferCenter + BegCol; // Get the left side of the POV view va = PlayerAngle - INT_ANGLE_32; // Check for wrap-around if (va < 0) va += INT_ANGLE_360; // Adjust the viewing angle based on the starting view column va += BegCol; // and check for wrap-around if (va >= INT_ANGLE_360) va -= INT_ANGLE_360; // Get the starting column for the background, there are 640 // columns possible, so the remainder when we divide is where // we want to begin displaying bcol = va % 640; // Temporarily hold onto the view height / 2 ht = gWinHalfHeight; // Since our horizon should always have some form of wall or object, // no matter how far away it is, we can optimize alittle here by not // drawing the first few horizon rows (it does actually save time!). // Start 6 video rows below the center row scr += 1920; // Initial right side of view Rcol = 319; wPtr = &WallDistTable[BegCol]; // Get pointers to avoid indexing RwPtr = &WallDistTable[Rcol]; // The ScaleHt is used to determine the distance from the player for each // row of the floor and ceiling. The value 89 was arrived at based on a // reasonable height above the floor that the player is standing. By // experimenting with this value, the effect of jumping up and down can // be achieved, (as long as the walls and objects are made to jump by the // same amount). Scale_Fac = (89 - ViewHeight) * 5; ScaleHt = 89 - ViewHeight; ScaleHt *= Scale_Fac; // Here we loop through each column of the viewing window for (col = BegCol; col < EndCol; col += 2) { // Pick up the cosine and sine values for the current angle cv = CosTable[va]; sv = SinTable[va]; // Point to the left side of the current floor and ceiling columns fscr = scr; // Advance the columns for the next pass scr += 2; // Pick up the current distance to the wall that was found for the // current column wdist = *wPtr; // Advance the wall distance pointer for the next pass wPtr += 2; #if DRAW_BACK // Pick up the pointer to the background image for the current column ba = BackArray[bcol++]; // Check for wrap-around in our 640 column image if (bcol > 639) bcol = 0; // Pick up the next column as well since the floor and ceiling are // always done in low resolution ba1 = BackArray[bcol++]; if (bcol > 639) bcol = 0; ba += ht; ba1 += ht; #endif // Initialize a last distance variable LastDist = -1; // Our floor cosine is used to counteract a fisheye effect fcv = FloorCosTable[col]; for (row = 6; row <= ht; row++) { scan2 = ScaleHt / row; // Get the distance for the current column and row position dist = (fcv * scan2) >> 15; // If we're still closer than any wall if (dist < wdist) { // Do some extra calculations if it's a new distance from last time // (Sometimes our distance works out to be the same so we can avoid // the next few lines) if (dist != LastDist) { x = xPglobal + ((cv * dist) >> 16); y = yPglobal + ((sv * dist) >> 16); LastDist = dist; } mPos = (y & 0xFC0) + (x >> 6); // Calc the Map Posn if (mPos < 0L || mPos > 4095L) continue; bPos = (y & 63) + ((x & 63)<<6); // Calc the Bitmap Pixel // Get the bitmap number for our floor bCode = FloorMap[mPos]; // And use it to pull the actual bitmap from our array of wall bitmaps bmp = WallbMaps[bCode]; // Make sure it's really a bitmap and then get the actual pixel to display if (bmp != NULL) ch = bmp[bPos]; // Place the pixel in this column as well as the next. Since we have a // scattering effect we can display in low resolution without too much // loss in detail. This really speeds up the drawing of the floor and // ceiling. *fscr = ch; // Put it into two locations fscr[1] = ch; // for low resolution } fscr += 320; // Advance our screen position for the floor #if DRAW_BACK // Advance the pointers to the background image for the next pass ba--; ba1--; #endif } // Advance our current viewing angle by 2 since we are in low resolution va += 2; // and check for wrap-around if (va >= INT_ANGLE_360) va -= INT_ANGLE_360; } } //ħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħ // The function performs the same process as AckDrawFloorHz except here // we include light shading with distance. //ħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħ void AckDrawFloor(void) { int i,col,row,ht,Rcol,EndCol,BegCol; int Scale_Fac,ScaleHt; UCHAR *scr,*fscr,*bmp,*scrCeil,*cscr; UCHAR *Rscr,*Rfscr,*RscrCeil,*Rcscr; UCHAR *ba,*ba1,*Rba,*Rba1; char *stPtr; short va,va1,LineNum; long LastDist,scan2; long cv,sv,dist,x,y,bx,by,mPos,bPos,wdist,bcol; long Rbcol,Rwdist,xp,yp; long *zd,*wPtr,*RwPtr,*xyPtr; long fcv; UCHAR ch; USHORT bCode; #if !(DRAW_BACK) DrawBackDrop(); // Draw entire background #endif BegCol = gWinStartX; EndCol = gWinEndX; // Get the starting offset of the center row of the view scr = gScrnBufferCenter + BegCol; // Get the left side of the POV view va = PlayerAngle - INT_ANGLE_32; // Check for wrap-around if (va < 0) va += INT_ANGLE_360; // Adjust the viewing angle based on the starting view column va += BegCol; // and check for wrap-around if (va >= INT_ANGLE_360) va -= INT_ANGLE_360; // Get the starting column for the background, there are 640 // columns possible, so the remainder when we divide is where // we want to begin displaying bcol = va % 640; // Temporarily hold onto the view height / 2 ht = gWinHalfHeight; // Since our horizon should always have some form of wall or object, // no matter how far away it is, we can optimize alittle here by not // drawing the first few horizon rows (it does actually save time!). // Start 5 video rows above the center row scrCeil = scr - 1600; // Start 6 video rows below the center row scr += 1920; // Initial right side of view Rcol = 319; wPtr = &WallDistTable[BegCol]; // Get pointers to avoid indexing RwPtr = &WallDistTable[Rcol]; // The ScaleHt is used to determine the distance from the player for each // row of the floor and ceiling. The value 89 was arrived at based on a // reasonable height above the floor that the player is standing. By // experimenting with this value, the effect of jumping up and down can // be achieved, (as long as the walls and objects are made to jump by the // same amount). Scale_Fac = (89 - ViewHeight) * 5; ScaleHt = 89 - ViewHeight; ScaleHt *= Scale_Fac; // Here we loop through each column of the viewing window for (col = BegCol; col < EndCol; col += 2) { // Pick up the cosine and sine values for the current angle cv = CosTable[va]; sv = SinTable[va]; // Point to the left side of the current floor and ceiling columns fscr = scr; cscr = scrCeil; // Advance the columns for the next pass scr += 2; scrCeil += 2; // Pick up the current distance to the wall that was found for the // current column wdist = *wPtr; // Advance the wall distance pointer for the next pass wPtr += 2; #if DRAW_BACK // Pick up the pointer to the background image for the current column ba = BackArray[bcol++]; // Check for wrap-around in our 640 column image if (bcol > 639) bcol = 0; // Pick up the next column as well since the floor and ceiling are // always done in low resolution ba1 = BackArray[bcol++]; if (bcol > 639) bcol = 0; ba += ht; ba1 += ht; #endif // Initialize a last distance variable LastDist = -1; // Our floor cosine is used to counteract a fisheye effect fcv = FloorCosTable[col]; LineNum = 0; for (row = 6; row <= ht; row++) { stPtr = scantables[LineNum++]; scan2 = ScaleHt / row; // Get the distance for the current column and row position dist = (fcv * scan2) >> 15; // If we're still closer than any wall if (dist < wdist) { // Do some extra calculations if it's a new distance from last time // (Sometimes our distance works out to be the same so we can avoid // the next few lines) if (dist != LastDist) { x = xPglobal + ((cv * dist) >> 16); y = yPglobal + ((sv * dist) >> 16); LastDist = dist; } mPos = (y & 0xFC0) + (x >> 6); // Calc the Map Posn if (mPos < 0L || mPos > 4095L) continue; bPos = (y & 63) + ((x & 63)<<6); // Calc the Bitmap Pixel // Get the bitmap number for our floor bCode = FloorMap[mPos]; // And use it to pull the actual bitmap from our array of wall bitmaps bmp = WallbMaps[bCode]; // Make sure it's really a bitmap and then get the actual pixel to display if (bmp != NULL) ch = bmp[bPos]; ch = stPtr[ch]; // Get shaded value for pixel // Place the pixel in this column as well as the next. Since we have a // scattering effect we can display in low resolution without too much // loss in detail. This really speeds up the drawing of the floor and // ceiling. *fscr = ch; // Put it into two locations fscr[1] = ch; // for low resolution // Only draw a ceiling pixel if there is a ceiling tile placed in the map // This gives the effect of seeing the background through holes in the ceiling if ((bCode = CeilMap[mPos]) != 0) { bmp = WallbMaps[bCode]; if (bmp != NULL) ch = bmp[bPos]; ch = stPtr[ch]; // Get shaded value for pixel *cscr = ch; cscr[1] = ch; } #if DRAW_BACK // If no ceiling is drawn, then we need to draw the background image else { *cscr = *ba; cscr[1] = *ba1; } #endif } fscr += 320; // Advance our screen position for the floor cscr -= 320; // and the ceiling #if DRAW_BACK // Advance the pointers to the background image for the next pass ba--; ba1--; #endif } // Advance our current viewing angle by 2 since we are in low resolution va += 2; // and check for wrap-around if (va >= INT_ANGLE_360) va -= INT_ANGLE_360; } } //ħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħ // Draw ceiling texture bitmaps only. Floor is assumed to be a solid color. //ħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħ void AckDrawCeilingOnly(void) { int i,col,row,ht,Rcol,EndCol,BegCol; int Scale_Fac,ScaleHt; UCHAR *scr,*fscr,*bmp,*scrCeil,*cscr; UCHAR *Rscr,*Rfscr,*RscrCeil,*Rcscr; UCHAR *ba,*ba1,*Rba,*Rba1; short va,va1,LineNum; char *stPtr; long LastDist,scan2; long cv,sv,dist,x,y,bx,by,mPos,bPos,wdist,bcol; long Rbcol,Rwdist,xp,yp; long *zd,*wPtr,*RwPtr,*xyPtr; long fcv; UCHAR ch; USHORT bCode; #if !(DRAW_BACK) DrawBackDrop(); // Draw entire background #endif BegCol = gWinStartX; EndCol = gWinEndX; // Get the starting offset of the center row of the view scr = gScrnBufferCenter + BegCol; // Get the left side of the POV view va = PlayerAngle - INT_ANGLE_32; // Check for wrap-around if (va < 0) va += INT_ANGLE_360; // Adjust the viewing angle based on the starting view column va += BegCol; // and check for wrap-around if (va >= INT_ANGLE_360) va -= INT_ANGLE_360; // Get the starting column for the background, there are 640 // columns possible, so the remainder when we divide is where // we want to begin displaying bcol = va % 640; // Temporarily hold onto the view height / 2 ht = gWinHalfHeight; // Since our horizon should always have some form of wall or object, // no matter how far away it is, we can optimize alittle here by not // drawing the first few horizon rows (it does actually save time!). // Start 5 video rows above the center row scrCeil = scr - 1600; // Initial right side of view Rcol = 319; wPtr = &WallDistTable[BegCol]; // Get pointers to avoid indexing RwPtr = &WallDistTable[Rcol]; // The ScaleHt is used to determine the distance from the player for each // row of the floor and ceiling. The value 89 was arrived at based on a // reasonable height above the floor that the player is standing. By // experimenting with this value, the effect of jumping up and down can // be achieved, (as long as the walls and objects are made to jump by the // same amount). Scale_Fac = (89 - ViewHeight) * 5; ScaleHt = 89 - ViewHeight; ScaleHt *= Scale_Fac; // Here we loop through each column of the viewing window for (col = BegCol; col < EndCol; col += 2) { // Pick up the cosine and sine values for the current angle cv = CosTable[va]; sv = SinTable[va]; // Point to the left side of the current ceiling columns cscr = scrCeil; // Advance the columns for the next pass scrCeil += 2; // Pick up the current distance to the wall that was found for the // current column wdist = *wPtr; // Advance the wall distance pointer for the next pass wPtr += 2; #if DRAW_BACK // Pick up the pointer to the background image for the current column ba = BackArray[bcol++]; // Check for wrap-around in our 640 column image if (bcol > 639) bcol = 0; // Pick up the next column as well since the floor and ceiling are // always done in low resolution ba1 = BackArray[bcol++]; if (bcol > 639) bcol = 0; ba += ht; ba1 += ht; #endif // Initialize a last distance variable LastDist = -1; // Our floor cosine is used to counteract a fisheye effect fcv = FloorCosTable[col]; LineNum = 0; for (row = 6; row <= ht; row++) { stPtr = scantables[LineNum++]; scan2 = ScaleHt / row; // Get the distance for the current column and row position dist = (fcv * scan2) >> 15; // If we're still closer than any wall if (dist < wdist) { // Do some extra calculations if it's a new distance from last time // (Sometimes our distance works out to be the same so we can avoid // the next few lines) if (dist != LastDist) { x = xPglobal + ((cv * dist) >> 16); y = yPglobal + ((sv * dist) >> 16); LastDist = dist; } mPos = (y & 0xFC0) + (x >> 6); // Calc the Map Posn if (mPos < 0L || mPos > 4095L) continue; bPos = (y & 63) + ((x & 63)<<6); // Calc the Bitmap Pixel // Only draw a ceiling pixel if there is a ceiling tile placed in the map // This gives the effect of seeing the background through holes in the ceiling if ((bCode = CeilMap[mPos]) != 0) { bmp = WallbMaps[bCode]; if (bmp != NULL) ch = bmp[bPos]; ch = stPtr[ch]; // Get shaded pixel *cscr = ch; cscr[1] = ch; } #if DRAW_BACK // If no ceiling is drawn, then we need to draw the background image else { *cscr = *ba; cscr[1] = *ba1; } #endif } cscr -= 320; // and the ceiling #if DRAW_BACK // Advance the pointers to the background image for the next pass ba--; ba1--; #endif } // Advance our current viewing angle by 2 since we are in low resolution va += 2; // and check for wrap-around if (va >= INT_ANGLE_360) va -= INT_ANGLE_360; } } //ħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħ // Draw floor textured bitmaps only. Ceiling is a solid color. //ħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħ void AckDrawFloorOnly(void) { int i,col,row,ht,Rcol,EndCol,BegCol; int Scale_Fac,ScaleHt; UCHAR *scr,*fscr,*bmp,*scrCeil,*cscr; UCHAR *Rscr,*Rfscr,*RscrCeil,*Rcscr; UCHAR *ba,*ba1,*Rba,*Rba1; short va,va1,LineNum; char *stPtr; long LastDist,scan2; long cv,sv,dist,x,y,bx,by,mPos,bPos,wdist,bcol; long Rbcol,Rwdist,xp,yp; long *zd,*wPtr,*RwPtr,*xyPtr; long fcv; UCHAR ch; USHORT bCode; #if !(DRAW_BACK) DrawBackDrop(); // Draw entire background #endif BegCol = gWinStartX; EndCol = gWinEndX; // Get the starting offset of the center row of the view scr = gScrnBufferCenter + BegCol; // Get the left side of the POV view va = PlayerAngle - INT_ANGLE_32; // Check for wrap-around if (va < 0) va += INT_ANGLE_360; // Adjust the viewing angle based on the starting view column va += BegCol; // and check for wrap-around if (va >= INT_ANGLE_360) va -= INT_ANGLE_360; // Get the starting column for the background, there are 640 // columns possible, so the remainder when we divide is where // we want to begin displaying bcol = va % 640; // Temporarily hold onto the view height / 2 ht = gWinHalfHeight; // Since our horizon should always have some form of wall or object, // no matter how far away it is, we can optimize alittle here by not // drawing the first few horizon rows (it does actually save time!). // Start 6 video rows below the center row scr += 1920; // Initial right side of view Rcol = 319; wPtr = &WallDistTable[BegCol]; // Get pointers to avoid indexing RwPtr = &WallDistTable[Rcol]; // The ScaleHt is used to determine the distance from the player for each // row of the floor and ceiling. The value 89 was arrived at based on a // reasonable height above the floor that the player is standing. By // experimenting with this value, the effect of jumping up and down can // be achieved, (as long as the walls and objects are made to jump by the // same amount). Scale_Fac = (89 - ViewHeight) * 5; ScaleHt = 89 - ViewHeight; ScaleHt *= Scale_Fac; // Here we loop through each column of the viewing window for (col = BegCol; col < EndCol; col += 2) { // Pick up the cosine and sine values for the current angle cv = CosTable[va]; sv = SinTable[va]; // Point to the left side of the current floor and ceiling columns fscr = scr; // Advance the columns for the next pass scr += 2; // Pick up the current distance to the wall that was found for the // current column wdist = *wPtr; // Advance the wall distance pointer for the next pass wPtr += 2; #if DRAW_BACK // Pick up the pointer to the background image for the current column ba = BackArray[bcol++]; // Check for wrap-around in our 640 column image if (bcol > 639) bcol = 0; // Pick up the next column as well since the floor and ceiling are // always done in low resolution ba1 = BackArray[bcol++]; if (bcol > 639) bcol = 0; ba += ht; ba1 += ht; #endif // Initialize a last distance variable LastDist = -1; // Our floor cosine is used to counteract a fisheye effect fcv = FloorCosTable[col]; LineNum = 0; for (row = 6; row <= ht; row++) { stPtr = scantables[LineNum++]; scan2 = ScaleHt / row; // Get the distance for the current column and row position dist = (fcv * scan2) >> 15; // If we're still closer than any wall if (dist < wdist) { // Do some extra calculations if it's a new distance from last time // (Sometimes our distance works out to be the same so we can avoid // the next few lines) if (dist != LastDist) { x = xPglobal + ((cv * dist) >> 16); y = yPglobal + ((sv * dist) >> 16); LastDist = dist; } mPos = (y & 0xFC0) + (x >> 6); // Calc the Map Posn if (mPos < 0L || mPos > 4095L) continue; bPos = (y & 63) + ((x & 63)<<6); // Calc the Bitmap Pixel // Get the bitmap number for our floor bCode = FloorMap[mPos]; // And use it to pull the actual bitmap from our array of wall bitmaps bmp = WallbMaps[bCode]; // Make sure it's really a bitmap and then get the actual pixel to display if (bmp != NULL) ch = bmp[bPos]; ch = stPtr[ch]; // Get shaded pixel // Place the pixel in this column as well as the next. Since we have a // scattering effect we can display in low resolution without too much // loss in detail. This really speeds up the drawing of the floor and // ceiling. *fscr = ch; // Put it into two locations fscr[1] = ch; // for low resolution } fscr += 320; // Advance our screen position for the floor #if DRAW_BACK // Advance the pointers to the background image for the next pass ba--; ba1--; #endif } // Advance our current viewing angle by 2 since we are in low resolution va += 2; // and check for wrap-around if (va >= INT_ANGLE_360) va -= INT_ANGLE_360; } } //ħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħ // This function performs the same process as AckDrawFloorHz except // we don't need to check for a bitmap index for every pixel since only // one bitmap will be used for the floor and one bitmap for the ceiling. // Draws a floor that contains only one type of bitmap. This is a much // faster process and may be useful in some applications. //ħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħħ void AckDrawOneFloor(void) { int i,col,row,ht,Rcol,EndCol,BegCol; int Scale_Fac,ScaleHt; UCHAR *scr,*fscr,*bmp,*cbmp,*scrCeil,*cscr; UCHAR *Rscr,*Rfscr,*RscrCeil,*Rcscr; UCHAR *ba,*ba1,*Rba,*Rba1; short va,va1; long LastDist,scan2; long cv,sv,dist,x,y,bx,by,mPos,bPos,wdist,bcol; long Rbcol,Rwdist,xp,yp; long *zd,*wPtr,*RwPtr,*xyPtr; long fcv; UCHAR ch; USHORT bCode; BegCol = gWinStartX; EndCol = gWinEndX; // Get the starting offset of the center row of the view scr = gScrnBufferCenter + BegCol; // Get the left side of the POV view va = PlayerAngle - INT_ANGLE_32; // Check for wrap-around if (va < 0) va += INT_ANGLE_360; // Adjust the viewing angle based on the starting view column va += BegCol; // and check for wrap-around if (va >= INT_ANGLE_360) va -= INT_ANGLE_360; // Temporarily hold onto the view height / 2 ht = gWinHalfHeight; // Since our horizon should always have some form of wall or object, // no matter how far away it is, we can optimize alittle here by not // drawing the first few horizon rows (it does actually save time!). // Start 5 video rows above the center row scrCeil = scr - 1600; // Start 6 video rows below the center row scr += 1920; // Initial right side of view Rcol = 319; wPtr = &WallDistTable[BegCol]; // Get pointers to avoid indexing RwPtr = &WallDistTable[Rcol]; // The ScaleHt is used to determine the distance from the player for each // row of the floor and ceiling. The value 89 was arrived at based on a // reasonable height above the floor that the player is standing. By // experimenting with this value, the effect of jumping up and down can // be achieved, (as long as the walls and objects are made to jump by the // same amount). Scale_Fac = (89 - ViewHeight) * 5; ScaleHt = 89 - ViewHeight; ScaleHt *= Scale_Fac; bmp = aeGlobal->bMaps[aeGlobal->FloorBitmap]; cbmp = aeGlobal->bMaps[aeGlobal->CeilBitmap]; // Here we loop through each column of the viewing window for (col = BegCol; col < EndCol; col += 2) { // Pick up the cosine and sine values for the current angle cv = CosTable[va]; sv = SinTable[va]; // Point to the left side of the current floor and ceiling columns fscr = scr; cscr = scrCeil; // Advance the columns for the next pass scr += 2; scrCeil += 2; // Pick up the current distance to the wall that was found for the // current column wdist = *wPtr; // Advance the wall distance pointer for the next pass wPtr += 2; // Initialize a last distance variable LastDist = -1; // Our floor cosine is used to counteract a fisheye effect fcv = FloorCosTable[col]; for (row = 6; row <= ht; row++) { scan2 = ScaleHt / row; // Get the distance for the current column and row position dist = (fcv * scan2) >> 15; // If we're still closer than any wall if (dist < wdist) { // Do some extra calculations if it's a new distance from last time // (Sometimes our distance works out to be the same so we can avoid // the next few lines) if (dist != LastDist) { x = xPglobal + ((cv * dist) >> 16); y = yPglobal + ((sv * dist) >> 16); LastDist = dist; } bPos = (y & 63) + ((x & 63)<<6); // Calc the Bitmap Pixel ch = bmp[bPos]; // Place the pixel in this column as well as the next. Since we have a // scattering effect we can display in low resolution without too much // loss in detail. This really speeds up the drawing of the floor and // ceiling. *fscr = ch; // Put it into two locations fscr[1] = ch; // for low resolution ch = cbmp[bPos]; *cscr = ch; cscr[1] = ch; } fscr += 320; // Advance our screen position for the floor cscr -= 320; // and the ceiling } // Advance our current viewing angle by 2 since we are in low resolution va += 2; // and check for wrap-around if (va >= INT_ANGLE_360) va -= INT_ANGLE_360; } } // **** End of Source ****