Box coordinates.
예제 #1
0
        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);
        }
예제 #2
0
        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;
        }
예제 #3
0
        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);
        }
예제 #4
0
        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];
            }
        }
예제 #5
0
파일: ScummMath.cs 프로젝트: scemino/nscumm
        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;
        }
예제 #6
0
        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);
        }
예제 #7
0
파일: Actor3.cs 프로젝트: scemino/nscumm
        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];
            }
        }