public static uint GetClosestPtOnBox(BoxCoords box, Point pIn, out Point pOut) { Point tmp; uint dist; uint bestdist = 0xFFFFFF; pOut = new Point(); tmp = ScummMath.ClosestPtOnLine(box.UpperLeft, box.UpperRight, pIn); dist = pIn.SquareDistance(tmp); if (dist < bestdist) { bestdist = dist; pOut = tmp; } tmp = ScummMath.ClosestPtOnLine(box.UpperRight, box.LowerRight, pIn); dist = pIn.SquareDistance(tmp); if (dist < bestdist) { bestdist = dist; pOut = tmp; } tmp = ScummMath.ClosestPtOnLine(box.LowerRight, box.LowerLeft, pIn); dist = pIn.SquareDistance(tmp); if (dist < bestdist) { bestdist = dist; pOut = tmp; } tmp = ScummMath.ClosestPtOnLine(box.LowerLeft, box.UpperLeft, pIn); dist = pIn.SquareDistance(tmp); if (dist < bestdist) { bestdist = dist; pOut = tmp; } return(bestdist); }
internal BoxCoords GetBoxCoordinates(int boxnum) { var bp = GetBoxBase(boxnum); var box = new BoxCoords(); box.UpperLeft.X = bp.Ulx; box.UpperLeft.Y = bp.Uly; box.UpperRight.X = bp.Urx; box.UpperRight.Y = bp.Ury; box.LowerLeft.X = bp.Llx; box.LowerLeft.Y = bp.Lly; box.LowerRight.X = bp.Lrx; box.LowerRight.Y = bp.Lry; if (Game.Version == 8) { // WORKAROUND (see patch #684732): Some walkboxes in CMI appear // to have been flipped, in the sense that for instance the // lower boundary is above the upper one. We work around this // by simply flipping them back. if (box.UpperLeft.Y > box.LowerLeft.Y && box.UpperRight.Y > box.LowerRight.Y) { ScummHelper.Swap(ref box.UpperLeft, ref box.LowerLeft); ScummHelper.Swap(ref box.UpperRight, ref box.LowerRight); } if (box.UpperLeft.X > box.UpperRight.X && box.LowerLeft.X > box.LowerRight.X) { ScummHelper.Swap(ref box.UpperLeft, ref box.UpperRight); ScummHelper.Swap(ref box.LowerLeft, ref box.LowerRight); } } return box; }
internal BoxCoords GetBoxCoordinates(int boxnum) { var bp = GetBoxBase(boxnum); var box = new BoxCoords(); box.UpperLeft.X = bp.Ulx; box.UpperLeft.Y = bp.Uly; box.UpperRight.X = bp.Urx; box.UpperRight.Y = bp.Ury; box.LowerLeft.X = bp.Llx; box.LowerLeft.Y = bp.Lly; box.LowerRight.X = bp.Lrx; box.LowerRight.Y = bp.Lry; if (Game.Version == 8) { // WORKAROUND (see patch #684732): Some walkboxes in CMI appear // to have been flipped, in the sense that for instance the // lower boundary is above the upper one. We work around this // by simply flipping them back. if (box.UpperLeft.Y > box.LowerLeft.Y && box.UpperRight.Y > box.LowerRight.Y) { ScummHelper.Swap(ref box.UpperLeft, ref box.LowerLeft); ScummHelper.Swap(ref box.UpperRight, ref box.LowerRight); } if (box.UpperLeft.X > box.UpperRight.X && box.LowerLeft.X > box.LowerRight.X) { ScummHelper.Swap(ref box.UpperLeft, ref box.UpperRight); ScummHelper.Swap(ref box.LowerLeft, ref box.LowerRight); } } return(box); }
void GetGates(BoxCoords box1, BoxCoords box2, Point[] gateA, Point[] gateB) { int i, j; var dist = new int[8]; var minDist = new int[3]; var closest = new int[3]; var box = new bool[3]; var closestPoint = new Point[8]; var boxCorner = new Point[8]; int line1, line2; // For all corner coordinates of the first box, compute the point closest // to them on the second box (and also compute the distance of these points). boxCorner[0] = box1.UpperLeft; boxCorner[1] = box1.UpperRight; boxCorner[2] = box1.LowerRight; boxCorner[3] = box1.LowerLeft; for (i = 0; i < 4; i++) { dist[i] = (int)ScummMath.GetClosestPtOnBox(box2, boxCorner[i], out closestPoint[i]); } // Now do the same but with the roles of the first and second box swapped. boxCorner[4] = box2.UpperLeft; boxCorner[5] = box2.UpperRight; boxCorner[6] = box2.LowerRight; boxCorner[7] = box2.LowerLeft; for (i = 4; i < 8; i++) { dist[i] = (int)ScummMath.GetClosestPtOnBox(box1, boxCorner[i], out closestPoint[i]); } // Find the three closest "close" points between the two boxes. for (j = 0; j < 3; j++) { minDist[j] = 0xFFFF; for (i = 0; i < 8; i++) { if (dist[i] < minDist[j]) { minDist[j] = dist[i]; closest[j] = i; } } dist[closest[j]] = 0xFFFF; minDist[j] = (int)Math.Sqrt(minDist[j]); box[j] = (closest[j] > 3); // Is the point on the first or on the second box? } // Finally, compute the actual "gate". if (box[0] == box[1] && Math.Abs(minDist[0] - minDist[1]) < 4) { line1 = closest[0]; line2 = closest[1]; } else if (box[0] == box[1] && minDist[0] == minDist[1]) { // parallel line1 = closest[0]; line2 = closest[1]; } else if (box[0] == box[2] && minDist[0] == minDist[2]) { // parallel line1 = closest[0]; line2 = closest[2]; } else if (box[1] == box[2] && minDist[1] == minDist[2]) { // parallel line1 = closest[1]; line2 = closest[2]; } else if (box[0] == box[2] && Math.Abs(minDist[0] - minDist[2]) < 4) { line1 = closest[0]; line2 = closest[2]; } else if (Math.Abs(minDist[0] - minDist[2]) < 4) { line1 = closest[1]; line2 = closest[2]; } else if (Math.Abs(minDist[0] - minDist[1]) < 4) { line1 = closest[0]; line2 = closest[1]; } else { line1 = closest[0]; line2 = closest[0]; } // Set the gate if (line1 < 4) { gateA[0] = boxCorner[line1]; gateA[1] = closestPoint[line1]; } else { gateA[1] = boxCorner[line1]; gateA[0] = closestPoint[line1]; } if (line2 < 4) { gateB[0] = boxCorner[line2]; gateB[1] = closestPoint[line2]; } else { gateB[1] = boxCorner[line2]; gateB[0] = closestPoint[line2]; } }
public static uint GetClosestPtOnBox(BoxCoords box, Point pIn, out Point pOut) { Point tmp; uint dist; uint bestdist = 0xFFFFFF; pOut = new Point(); tmp = ScummMath.ClosestPtOnLine(box.UpperLeft, box.UpperRight, pIn); dist = pIn.SquareDistance(tmp); if (dist < bestdist) { bestdist = dist; pOut = tmp; } tmp = ScummMath.ClosestPtOnLine(box.UpperRight, box.LowerRight, pIn); dist = pIn.SquareDistance(tmp); if (dist < bestdist) { bestdist = dist; pOut = tmp; } tmp = ScummMath.ClosestPtOnLine(box.LowerRight, box.LowerLeft, pIn); dist = pIn.SquareDistance(tmp); if (dist < bestdist) { bestdist = dist; pOut = tmp; } tmp = ScummMath.ClosestPtOnLine(box.LowerLeft, box.UpperLeft, pIn); dist = pIn.SquareDistance(tmp); if (dist < bestdist) { bestdist = dist; pOut = tmp; } return bestdist; }
static int CheckXYInBoxBounds(int boxnum, Point p, out Point dest) { BoxCoords box = ScummEngine.Instance.GetBoxCoordinates(boxnum); int xmin, xmax; // We are supposed to determine the point (destX,destY) contained in // the given box which is closest to the point (x,y), and then return // some kind of "distance" between the two points. // First, we determine destY and a range (xmin to xmax) in which destX // is contained. if (p.Y < box.UpperLeft.Y) { // Point is above the box dest.Y = box.UpperLeft.Y; xmin = box.UpperLeft.X; xmax = box.UpperRight.X; } else if (p.Y >= box.LowerLeft.Y) { // Point is below the box dest.Y = box.LowerLeft.Y; xmin = box.LowerLeft.X; xmax = box.LowerRight.X; } else if ((p.X >= box.UpperLeft.X) && (p.X >= box.LowerLeft.X) && (p.X < box.UpperRight.X) && (p.X < box.LowerRight.X)) { // Point is strictly inside the box dest.X = p.X; dest.Y = p.Y; xmin = xmax = p.X; } else { // Point is to the left or right of the box, // so the y coordinate remains unchanged dest.Y = p.Y; int ul = box.UpperLeft.X; int ll = box.LowerLeft.X; int ur = box.UpperRight.X; int lr = box.LowerRight.X; int top = box.UpperLeft.Y; int bottom = box.LowerLeft.Y; int cury; // Perform a binary search to determine the x coordinate. // Note: It would be possible to compute this value in a // single step simply by calculating the slope of the left // resp. right side and using that to find the correct // result. However, the original engine did use the search // approach, so we do that, too. do { xmin = (ul + ll) / 2; xmax = (ur + lr) / 2; cury = (top + bottom) / 2; if (cury < p.Y) { top = cury; ul = xmin; ur = xmax; } else if (cury > p.Y) { bottom = cury; ll = xmin; lr = xmax; } } while (cury != p.Y); } // Now that we have limited the value of destX to a fixed // interval, it's a trivial matter to finally determine it. if (p.X < xmin) { dest.X = xmin; } else if (p.X > xmax) { dest.X = xmax; } else { dest.X = p.X; } // Compute the distance of the points. We measure the // distance with a granularity of 8x8 blocks only (hence // yDist must be divided by 4, as we are using 8x2 pixels // blocks for actor coordinates). int xDist = Math.Abs(p.X - dest.X); int yDist = Math.Abs(p.Y - dest.Y) / 4; int dist; if (ScummEngine.Instance.Game.Version == 0) { xDist *= 2; } if (xDist < yDist) { dist = (xDist >> 1) + yDist; } else { dist = (yDist >> 1) + xDist; } return(dist); }