Exemplo n.º 1
0
        public override AdjustBoxResult AdjustXYToBeInBox(Point dst)
        {
            var abr = new AdjustBoxResult();
            abr.Position = dst;
            abr.Box = InvalidBox;

            var numBoxes = _scumm.GetNumBoxes() - 1;
            var bestDist = 0xFF;
            for (int i = 0; i <= numBoxes; i++)
            {
                // MM v0 prioritizes lower boxes, other engines higher boxes
                var box = (byte)(_scumm.Game.Version == 0 ? i : numBoxes - i);
                var flags = _scumm.GetBoxFlags(box);
                if ((flags.HasFlag(BoxFlags.Invisible) && !((flags.HasFlag(BoxFlags.PlayerOnly) && !IsPlayer))))
                    continue;
                Point found;
                var dist = CheckXYInBoxBounds(box, dst, out found); // also merged with getClosestPtOnBox
                if (dist == 0)
                {
                    abr.Position = found;
                    abr.Box = box;
                    break;
                }
                if (dist < bestDist)
                {
                    bestDist = dist;
                    abr.Position = found;
                    abr.Box = box;
                }
            }

            return abr;
        }
Exemplo n.º 2
0
        public virtual AdjustBoxResult AdjustXYToBeInBox(Point dst)
        {
            var thresholdTable = new [] { 30, 80, 0 };
            var abr = new AdjustBoxResult();
            uint tmpDist, bestDist;
            int threshold, numBoxes;
            BoxFlags flags;
            byte bestBox;
            int box;
            int firstValidBox = _scumm.Game.Version < 5 ? 0 : 1;

            abr.Position = dst;
            abr.Box = InvalidBox;

            if (IgnoreBoxes)
                return abr;

            for (int tIdx = 0; tIdx < thresholdTable.Length; tIdx++)
            {
                threshold = thresholdTable[tIdx];

                numBoxes = _scumm.GetNumBoxes() - 1;
                if (numBoxes < firstValidBox)
                    return abr;

                bestDist = (_scumm.Game.Version >= 7) ? (uint)0x7FFFFFFF : (uint)0xFFFF;
                bestBox = InvalidBox;

                // We iterate (backwards) over all boxes, searching the one closest
                // to the desired coordinates.
                for (box = numBoxes; box >= firstValidBox; box--)
                {
                    flags = _scumm.GetBoxFlags((byte)box);

                    // Skip over invisible boxes
                    if (flags.HasFlag(BoxFlags.Invisible) && !(flags.HasFlag(BoxFlags.PlayerOnly)
                        && !IsPlayer))
                        continue;

                    // For increased performance, we perform a quick test if
                    // the coordinates can even be within a distance of 'threshold'
                    // pixels of the box.
                    if (threshold > 0 && _scumm.GetBoxCoordinates(box).InBoxQuickReject(dst, threshold))
                        continue;

                    // Check if the point is contained in the box. If it is,
                    // we don't have to search anymore.
                    if (_scumm.CheckXYInBoxBounds(box, dst))
                    {
                        abr.Position = dst;
                        abr.Box = (byte)box;
                        return abr;
                    }

                    // Find the point in the box which is closest to our point.
                    Point pTmp;
                    tmpDist = ScummMath.GetClosestPtOnBox(_scumm.GetBoxCoordinates(box), dst, out pTmp);

                    // Check if the box is closer than the previous boxes.
                    if (tmpDist < bestDist)
                    {
                        abr.Position = pTmp;

                        if (tmpDist == 0)
                        {
                            abr.Box = (byte)box;
                            return abr;
                        }

                        bestDist = tmpDist;
                        bestBox = (byte)box;
                    }
                }

                // If the closest ('best') box we found is within the threshold, or if
                // we are on the last run (i.e. threshold == 0), return that box.
                if (threshold == 0 || threshold * threshold >= bestDist)
                {
                    abr.Box = bestBox;
                    return abr;
                }
            }

            return abr;
        }