Esempio n. 1
0
    // Returns the largest move that this can make in the move direction, given another circle at offset
    public override double[] moveTo(GameCircle other, double[] offset, double[] move)
    {
        GameCircle c1            = this;
        GameCircle c2            = other;
        double     radius        = c1.getRadius() + c2.getRadius();
        double     desiredLength = Math.Sqrt(move[0] * move[0] + move[1] * move[1]);
        double     distFromPath  = Math.Abs(offset[0] * move[1] - offset[1] * move[0]) / desiredLength;

        if ((distFromPath >= radius) || (offset[0] * move[0] + offset[1] * move[1] <= 0))
        {
            // if we get here then the circles never collide and so any move is okay
            return(move);               // return the same move to indicate that this move is okay
        }
        double distToClosestPoint = Math.Sqrt((offset[0] * offset[0] + offset[1] * offset[1]) - distFromPath * distFromPath);
        double allowedLength      = distToClosestPoint - Math.Sqrt(radius * radius - distFromPath * distFromPath);

        if (allowedLength >= desiredLength)
        {
            // if we get here then the desired move is not long enough to collide
            return(move);
        }
        double[] result = new double[2];        // create a new array to indicate that this move is different
        result[0] = move[0] * allowedLength / desiredLength;
        result[1] = move[1] * allowedLength / desiredLength;
        return(result);
    }
Esempio n. 2
0
    // Returns the maximum amount of distance that this can move in the move direction, given a rectangle at offset
    public override double[] moveTo(GameRectangle other, double[] offset, double[] move)
    {
        GameCircle    c = this;
        GameRectangle r = other;

        double[] mirroredMove   = new double[move.Length];
        double[] mirroredOffset = new double[move.Length];
        int      i;

        // flip the coordinate system so that the offset is positive in all dimensions
        for (i = 0; i < move.Length; i++)
        {
            if (offset[i] >= 0)
            {
                mirroredOffset[i] = offset[i];
                mirroredMove[i]   = move[i];
            }
            else
            {
                mirroredOffset[i] = -offset[i];
                mirroredMove[i]   = -move[i];
            }
        }
        //System.Collections.Generic.List<double[]> intersections;
        //double[] tempIntersection;
        // figure out where it may intersect the left/right wall
        double width = r.getWidth() / 2 + c.getRadius();

        if (mirroredMove[0] > 0 && mirroredOffset[0] >= width)
        {
            // calculate where it will intersect this line
            double[] allowedMove = new double[2];
            allowedMove[0] = mirroredOffset[0] - width;
            // check that it will go far enough to collide
            if (allowedMove[0] < mirroredMove[0])
            {
                allowedMove[1] = allowedMove[0] * mirroredMove[1] / mirroredMove[0];
                // make sure that it actually intersects the line segment and not just the line
                if (Math.Abs(mirroredOffset[1] - allowedMove[1]) <= r.getHeight() / 2)
                {
                    // reflect it back correctly and return
                    if (offset[0] < 0)
                    {
                        allowedMove[0] *= -1;
                    }
                    if (offset[1] < 0)
                    {
                        allowedMove[1] *= -1;
                    }
                    return(allowedMove);
                }
            }
        }
        double height = r.getHeight() / 2 + c.getRadius();

        if (mirroredMove[1] > 0 && mirroredOffset[1] >= height)
        {
            // calculate where it will intersect this line
            double[] allowedMove = new double[2];
            allowedMove[1] = mirroredOffset[1] - height;
            // check that it will go far enough to collide
            if (allowedMove[1] < mirroredMove[1])
            {
                allowedMove[0] = allowedMove[1] * mirroredMove[0] / mirroredMove[1];
                // make sure that it actually intersects the line segment and not just the line
                if (Math.Abs(mirroredOffset[0] - allowedMove[0]) <= r.getWidth() / 2)
                {
                    // reflect it back correctly and return
                    if (offset[0] < 0)
                    {
                        allowedMove[0] *= -1;
                    }
                    if (offset[1] < 0)
                    {
                        allowedMove[1] *= -1;
                    }
                    return(allowedMove);
                }
            }
        }
        // figure out where it may intersect the corner arc
        double length       = Math.Sqrt(move[0] * move[0] + move[1] * move[1]);
        double signedWidth  = r.getWidth() / 2;
        double signedHeight = r.getHeight() / 2;

        for (i = 0; i < 2; i++)
        {
            double lateralOffset = (mirroredOffset[0] - signedWidth) * mirroredMove[1] / length - (mirroredOffset[1] - signedHeight) * mirroredMove[0] / length;
            // first check that the movement line will reach the arc
            if (Math.Abs(lateralOffset) <= c.getRadius())
            {
                double forwardOffset = (mirroredOffset[0] - signedWidth) * mirroredMove[0] / length + (mirroredOffset[1] - signedHeight) * mirroredMove[1] / length;
                // Next check that the movement line is facing the right direction
                if (forwardOffset >= 0)
                {
                    double collisionDist = forwardOffset - Math.Sqrt(c.getRadius() * c.getRadius() - lateralOffset * lateralOffset);
                    // Make sure that it is hitting the outside of the arc
                    if ((Math.Abs(mirroredOffset[0] - mirroredMove[0] * collisionDist / length) >= r.getWidth() / 2) &&
                        (Math.Abs(mirroredOffset[1] - mirroredMove[1] * collisionDist / length) >= r.getHeight() / 2))
                    {
                        // If we get here then it is, in fact, moving toward the corner of the rectangle from the outside. Now decide if it wants to move that far
                        // if it doesn't want to move that far, then it can just keep going
                        if (collisionDist >= length)
                        {
                            return(move);
                        }
                        else
                        {
                            // If we get here, it means is would collide with the arc and we need to shorten the length
                            double[] allowedMove = new double[2];
                            allowedMove[0] = move[0] * collisionDist / length;
                            allowedMove[1] = move[1] * collisionDist / length;
                            return(allowedMove);
                        }
                    }
                }
            }
            // Now alter the coordinates to check the other corner, and repeat
            if ((mirroredOffset[0] - signedWidth) * mirroredMove[0] >= (mirroredOffset[1] - signedHeight) * mirroredMove[1])
            {
                // switch vertically because we're closer to the left/right edge
                signedHeight *= -1;
            }
            else
            {
                // switch vertically because we're closer to the left/right edge
                signedWidth *= -1;
            }
        }
        // If we get here, there are no collisions and so any move is fine
        return(move);
    }