ack3d/ack_lib/ACKFLOOR.C
2019-11-03 13:05:01 -05:00

1228 lines
39 KiB
C

// 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 ****