/* ACK-3D ( Animation Construction Kit 3D ) */ /* Object routines */ /* Author: Lary Myers */ #include #include #include #include #include #include #include #include #include #include #include "ack3d.h" #include "ackext.h" /**************************************************************************** ** Runs the list of objects generated during xRay and yRay to determine if ** ** they are really visible, what column should be displayed and which ** ** bitmap to use. ** ** ** ** First the object coordinates are translated to be 0,0 relative to ** ** the player coordinates. ** ** ** ** Next the object coordinates are rotated to the player angle. This ** ** allows the tangent of the angle to be used to determine the column of ** ** the bitmap. Some checks are made to insure the column and distance are ** ** not out of bounds. ** ** ** ** The width of the object is determined from the same table as the height ** ** to keep the object (which is 64x64 for now) in the same ratio as the ** ** walls. ** ** ** ** If the object has multiple sides the angle is used to determine which ** ** side to display. This value is then used to get the correct bitmap ** ** number to display. The current object center row is also used to allow ** ** objects to bounce up and down. ** ** ** ** Finally the objects is displayed if it will fit on the display and the ** ** distance is closer than the corresonding wall slice. ** ** ** ****************************************************************************/ void FindObject(int xPlayer,int yPlayer,int PlayerAngle) { int i,j,count,SaveCenter; int ObjX,ObjY,ObjNum; int NewX,NewY; int MaxOpp,Column; int wt,ObjIndex; long deltax,deltay; long xp,yp,distance; long SinValue,CosValue; if (!TotalObjects) /* No objects found during ray casts */ return; SinValue = SinTable[PlayerAngle]; CosValue = CosTable[PlayerAngle]; for (i = 0; i < TotalObjects; i++) { ObjIndex = ObjNumber[i]; ObjNum = ObjList[ObjIndex].bmNum[ObjList[ObjIndex].CurNum]; ObjX = ObjList[ObjIndex].x; ObjY = ObjList[ObjIndex].y; /* Translate coordinates to 0,0 */ NewX = ObjX - xPlayer; NewY = ObjY - yPlayer; /* Rotate coordinates to current player angle */ xp = ((NewX * CosValue) + (NewY * SinValue)) >> FP_SHIFT; yp = ((NewY * CosValue) - (NewX * SinValue)) >> FP_SHIFT; deltax = xp; deltay = yp; distance = long_sqrt((deltax * deltax) + (deltay * deltay)); MaxOpp = ((LongTanTable[INT_ANGLE_30] * (long)deltax) >> FP_SHIFT); if (NewY < ObjY) MaxOpp = -MaxOpp; Column = 160; if (MaxOpp) Column = 160 - ((deltay * 160) / MaxOpp); yp = ViewCosTable[Column]; xp = distance; if (yp) { distance = distance * yp; xp = distance >> 14; if (distance - (xp << 14) >= 8096) xp++; } distance = xp; if (distance < 0) continue; if (distance >= (MAX_DISTANCE - 10)) distance = MAX_DISTANCE-11; wt = DistanceTable[distance]; if (wt > 300) continue; if (wt < 16) wt = 16; if (wt > 300) wt = 300; yp = AdjustTable[distance]; xp = 0; wt >>= 1; NewX = Column; if (ObjList[ObjIndex].Sides) ObjNum = ObjList[ObjIndex].bmNum[((PlayerAngle / ObjList[ObjIndex].Sides) & 7)]; SaveCenter = CenterRow; CenterRow = ObjList[ObjIndex].VidRow; for (Column = NewX - wt; Column < NewX + wt; Column++) { if (Column >= 0 && Column < 320) { if (distance < (Walls[Column].Distance + 10)) DrawOneObject(ObjNum,xp >> FP_SHIFT,distance,Column,PageNum); } xp += yp; } CenterRow = SaveCenter; } } /**************************************************************************** ** ** ****************************************************************************/ long CheckObjects(int xPlayer,int yPlayer,int PlayerAngle) { int i,j,count; int mPos,ObjX,ObjY,ObjNum; int NewX,NewY; int MaxOpp,Column; int wt,ObjIndex; long MinDistance; long xp,yp,distance; long SinValue,CosValue; MinDistance = 3000000L; if (!TotalObjects) return(MinDistance); SinValue = SinTable[PlayerAngle]; CosValue = CosTable[PlayerAngle]; for (i = 0; i < TotalObjects; i++) { ObjIndex = ObjNumber[i]; if (Grid[ObjList[ObjIndex].mPos] & 0x40) continue; ObjX = ObjList[ObjIndex].x; ObjY = ObjList[ObjIndex].y; /* Translate coordinates to 0,0 */ NewX = ObjX - xPlayer; NewY = ObjY - yPlayer; /* Rotate coordinates to current player angle */ xp = ((NewX * CosValue) + (NewY * SinValue)) >> FP_SHIFT; yp = ((NewY * CosValue) - (NewX * SinValue)) >> FP_SHIFT; distance = long_sqrt((xp * xp) + (yp * yp)); MaxOpp = ((LongTanTable[INT_ANGLE_30] * xp) >> FP_SHIFT); if (NewY < ObjY) MaxOpp = -MaxOpp; Column = 160; if (MaxOpp) Column = 160 - ((yp * 160) / MaxOpp); yp = ViewCosTable[Column]; xp = distance; if (yp) { distance = distance * yp; xp = distance >> 14; if (distance - (xp << 14) >= 8096) xp++; } distance = xp; if (distance < 0) continue; if (distance >= MAX_DISTANCE) distance = MAX_DISTANCE-1; if (DistanceTable[distance] > 300) continue; if (distance < MinDistance) MinDistance = distance; } return(MinDistance); } /**************************************************************************** ** ** ****************************************************************************/ void MoveObject(int Index,int dx,int dy) { int Pos,NewPos,x1,y1; Pos = ObjList[Index].mPos; ObjList[Index].y += dy; ObjList[Index].x += dx; x1 = ObjList[Index].x >> 6; y1 = ObjList[Index].y >> 6; NewPos = (y1 * GRID_WIDTH) + x1; if (NewPos != Pos) { xObjGrid[Pos] = xObjGrid[Pos-1]; xObjGrid[Pos+1] = xObjGrid[Pos+2]; yObjGrid[Pos] = yObjGrid[Pos-GRID_WIDTH]; yObjGrid[Pos+GRID_WIDTH] = yObjGrid[Pos + (GRID_WIDTH << 1)]; Grid[Pos] &= 0x7F; ObjList[Index].mPos = NewPos; xObjGrid[NewPos] = Index; xObjGrid[NewPos+1] = Index; yObjGrid[NewPos] = Index; yObjGrid[NewPos+GRID_WIDTH] = Index; Grid[NewPos] |= 0x80; } } /**************************************************************************** ** ** ****************************************************************************/ void CheckObjectMovement(void) { int i,speed; int dx,dy,dir; int NewDx,NewDy; for (i = 1; i < MaxObjects; i++) { if (!ObjList[i].Active) continue; if (!(speed = ObjList[i].Speed)) continue; dir = ObjList[i].Dir; if (dir == 8) { ObjList[i].VidRow -= speed; if (ObjList[i].VidRow < 110) { ObjList[i].VidRow = 110; ObjList[i].Dir = 9; } continue; } if (dir == 9) { ObjList[i].VidRow += speed; if (ObjList[i].VidRow > 130) { ObjList[i].VidRow = 130; ObjList[i].Dir = 8; } continue; } if (dir == 10) { dx = ObjList[i].CurNum + 1; if (dx > ObjList[i].MaxNum) dx = 0; ObjList[i].CurNum = dx; continue; } dx = DirDx[dir] * speed; dy = DirDy[dir] * speed; NewDx = ObjList[i].x + dx; NewDy = ObjList[i].y + dy; if (NewDy < 96 || NewDy > 4000 || NewDx < 96 || NewDx > 4000 || CheckHit(ObjList[i].x,ObjList[i].y,DirAngle[dir])) { dir += 2; if (dir > 7) dir = 0; if (CheckHit(ObjList[i].x,ObjList[i].y,DirAngle[dir])) { dir -= 4; if (dir < 0) dir = 7; } ObjList[i].Dir = dir; continue; } MoveObject(i,dx,dy); } }