Ejemplo n.º 1
0
    /// ---------------- Respawn Point Collision Avoidance Section ---------------- ///

    /// <summary>
    /// <para>The dot product of vector A and second vector B results in
    /// the length of vector A projected in the direction of vector B.
    /// Here the dot product is the projection of an asteroid's velocity onto the relative position
    /// of the potential respawn point.  Divide the dot product by the relative speed squared
    /// (magnitude of the relative velocity) to calculate
    /// the time when the objects will be closest to each other during their trajectories.
    /// minSeparation becomes the distance between the two objects at their closest approach.
    /// If this distance is small enough they will collide.</para>
    /// <para>I have set it to check for a minSeparation value of < .3 and if the asteroid is
    /// within 3 seconds of approaching this point.</para>
    /// </summary>
    /// <returns>A safe respawn point.</returns>

    static public IEnumerator PlotRespawnPointCoroutine(CallbackDelegateV3 callback)
    {
        Vector3 respawnPoint = Vector3.zero;
        bool    isSafePoint;
        // Attempt to find a safe point 20 times max to avoid possible infinite loop
        // if there are no possible safe spots
        int attempts = 20;

        do
        {
            // Choose a random location within 80% of the play area;
            respawnPoint = ScreenBounds.RANDOM_RESPAWN_LOC;
            isSafePoint  = true;
            attempts--;

            foreach (Asteroid a in ASTEROIDS)
            {
                // Only predict collisions with parent asteroids
                if (a.transform.parent == null)
                {
                    Vector3 relativePos   = a.transform.position - respawnPoint;
                    Vector3 relativeVel   = a.GetComponent <Rigidbody> ().velocity;
                    float   relativeSpeed = relativeVel.magnitude;

                    // Calculate the time of the closest approach of this asteroid to the respawn point
                    float timeToClosestApproach = Vector3.Dot(relativePos, relativeVel);
                    timeToClosestApproach /= relativeSpeed * relativeSpeed * -1;

                    float distance = relativePos.magnitude;
                    // The minimal Separation is the distance between the two objects at the time of the closest approach.
                    float minSeparation = distance - relativeSpeed * timeToClosestApproach;

                    // If a collision is likely within 3 seconds flag this point as false
                    // Increase minSeparation if you want to give the player a bit more room to move after respawn.
                    if (minSeparation < .3 && timeToClosestApproach <= 3)
                    {
                                                #if DEBUG_Asteroid_PlotCollision
                        Debug.DrawLine(respawnPoint, a.transform.position, Color.white, 3f);
                                                #endif
                        isSafePoint = false;
                    }
                }
            }
        } while (attempts > 0 && isSafePoint == false);

        yield return(new WaitForSeconds(PlayerShip.respawnTimer));

        callback(respawnPoint);
    }
    /// <summary>
    /// <para>Given the point of the PlayerShip when it hit an Asteroid, this method
    /// chooses a respawn point. The RESPAWN_POINT_GRID_DIVISIONS above determines
    /// how many points the game will check. If that number is 8, then the game
    /// will check 49 (7x7) points within the play area (dividing each dimension
    /// into 8ths and avoiding the edges of the play area).</para>
    /// <para>This method will not find and avoid the location closest to the
    /// PlayerShip's previous location and then will iterate through all points
    /// and all Asteroids.</para>
    /// <para>This process is not very performant (though given the
    /// small numbers of objects, it's still really fast), so we'll have it use
    /// a coroutine to demonstrate their use.</para>
    /// </summary>
    /// <returns>The respawn point for the PlayerShip.</returns>
    /// <param name="prevPos">Previous position of the PlayerShip.</param>
    /// <param name="callback">Method to be called when this method is finished.</param>
    static public IEnumerator FindRespawnPointCoroutine(Vector3 prevPos, CallbackDelegateV3 callback, ParticleManager _particleSystem)
    {
# if DEBUG_AsteraX_RespawnNotifications
Ejemplo n.º 3
0
    static public IEnumerator FindRespawnPointCoroutine(Vector3 prevPos, CallbackDelegateV3 callback)
    {
        if (RESPAWN_POINTS == null)
        {
            RESPAWN_POINTS = new Vector3[RESPAWN_DIVISIONS + 1, RESPAWN_DIVISIONS + 1];
            Bounds playAreaBounds = ScreenBounds.BOUNDS;
            float  dX             = playAreaBounds.size.x / RESPAWN_DIVISIONS;
            float  dY             = playAreaBounds.size.y / RESPAWN_DIVISIONS;
            for (int i = 0; i <= RESPAWN_DIVISIONS; i++)
            {
                for (int j = 0; j <= RESPAWN_DIVISIONS; j++)
                {
                    RESPAWN_POINTS[i, j] = new Vector3(
                        playAreaBounds.min.x + i * dX,
                        playAreaBounds.min.y + j * dY,
                        0);
                }
            }
        }

        yield return(new WaitForSeconds(PlayerShip.RESPAWN_DELAY * 0.8f));

        float distSqr, closestDistSqr = float.MaxValue;
        int   prevI = 0, prevJ = 0;

        for (int i = RESPAWN_AVOID_EDGES; i <= RESPAWN_DIVISIONS - RESPAWN_AVOID_EDGES; i++)
        {
            for (int j = RESPAWN_AVOID_EDGES; j <= RESPAWN_DIVISIONS - RESPAWN_AVOID_EDGES; j++)
            {
                distSqr = (RESPAWN_POINTS[i, j] - prevPos).sqrMagnitude;
                if (distSqr < closestDistSqr)
                {
                    closestDistSqr = distSqr;
                    prevI          = i;
                    prevJ          = j;
                }
            }
        }

        float   furthestDistSqr = 0;
        Vector3 nextPos         = prevPos;

        for (int i = RESPAWN_AVOID_EDGES; i <= RESPAWN_DIVISIONS - RESPAWN_AVOID_EDGES; i++)
        {
            for (int j = RESPAWN_AVOID_EDGES; j <= RESPAWN_DIVISIONS - RESPAWN_AVOID_EDGES; j++)
            {
                if (i == prevI && j == prevJ)
                {
                    continue;
                }
                closestDistSqr = float.MaxValue;
                for (int k = 0; k < ASTEROIDS.Count; k++)
                {
                    distSqr = (ASTEROIDS[k].transform.position - RESPAWN_POINTS[i, j]).sqrMagnitude;
                    if (distSqr < closestDistSqr)
                    {
                        closestDistSqr = distSqr;
                    }
                }
                if (closestDistSqr > furthestDistSqr)
                {
                    furthestDistSqr = closestDistSqr;
                    nextPos         = RESPAWN_POINTS[i, j];
                }
            }
        }
        yield return(new WaitForSeconds(PlayerShip.RESPAWN_DELAY * 0.2f));

        callback(nextPos);
    }