Exemple #1
0
    void FixedUpdate()
    {
        if (!initialized)
        {
            return;
        }

        //See if any teams have captured the waypoint.
        foreach (Color c in collidedWith.Keys)
        {
            if (teams[c].Count == collidedWith[c].Count)
            {
                //Give the waypoint capture to the first player that entered the waypoint.
                teams[c][0].OwnerStats.WaypointsCaptured += 1;

                WorldConstants.Creator.CreateFloatingTextsForPlayers(WorldConstants.Creator.FourMessages(WorldConstants.ActorConsts.WaypointCapturedMessages, teams[c][0], null),
                                                                     st => st.ActorData.Team == c,
                                                                     WorldConstants.Creator.CreateWaypointFloatingText);
                WorldConstants.CrowdCheering.CreateCrowdCheer(CrowdCheers.Events.WaypointCaptured);

                GameObject.Destroy(gameObject);
                return;
            }
        }

        //Now check to see which players aren't colliding anymore.
        List <Color>        keys = collidedWith.Keys.ToList();
        List <StateMachine> temp;
        RecBounds           thisB = new RecBounds(collider.bounds);

        foreach (Color c in keys)
        {
            temp = collidedWith[c].ToList();
            foreach (StateMachine st in temp)
            {
                if (!st.ActorBounds.Intersects(thisB))
                {
                    collidedWith[c].Remove(st);
                }
            }
        }
    }
    /// <summary>
    /// Checks to see if this actor got outside the level somehow, and puts him back in.
    /// </summary>
    private void CheckOutside()
    {
        if (!ActorBounds.Intersects(WorldConstants.LevelBounds))
        {
            Vector2   pos    = transform.position;
            RecBounds levelB = WorldConstants.LevelBounds;

            Vector2 dir = new Vector2(Sign(levelB.center.x - pos.x, 0.001f),
                                      Sign(levelB.center.y - pos.y, 0.001f));

            //Move in along the X.
            if (!Manager.LevelGen.GenSettings.WrapX &&
                !(new Interval(levelB.left, levelB.right, true, 2).Inside(pos.x)))
            {
                transform.position += new Vector3(2.0f * dir.x, 0.0f, transform.position.z);
                Velocity.x          = 0.0f;

                if (IsPlayer && !(CurrentState is InAirState) && !(CurrentState is HurtState))
                {
                    ChangeState(ScriptableObject.CreateInstance <InAirState>(), false);
                }
            }

            //Move in along the Y.
            if (!Manager.LevelGen.GenSettings.WrapY &&
                !(new Interval(levelB.bottom, levelB.top, true, 2).Inside(pos.y)))
            {
                transform.position += new Vector3(0.0f, 2.0f * dir.y, transform.position.z);
                Velocity.y          = 0.0f;

                if (IsPlayer && !(CurrentState is InAirState) && !(CurrentState is HurtState))
                {
                    ChangeState(ScriptableObject.CreateInstance <InAirState>(), false);
                }
            }
        }
    }
    public override void EnteringState()
    {
        Owner.Animator.CurrentAnimation = Animations.P_CeilingSlide;

        originalParticleYSpeed           = Owner.RunningParts.WorldVelocity.y;
        Owner.RunningParts.WorldVelocity = new Vector3(Owner.RunningParts.WorldVelocity.x, 0.0f);

        RecBounds ab = Owner.ActorBounds;

        Owner.RunningParts.Position = new Vector3(ab.center.x, ab.top, Owner.RunningParts.Position.z);

        //Make the sliding noise.
        if (useSlidingNoise)
        {
            slidingNoise = new FadeLoopNoise(WorldConstants.PlayPhysNoises.GetNoise(PlayerPhysicsNoises.Events.Slide), "Sliding on Ceiling");
        }
        else
        {
            slidingNoise = new FadeLoopNoise(WorldConstants.PlayPhysNoises.GetNoise(PlayerPhysicsNoises.Events.Run), "Runnin on Ceiling");
        }

        slidingNoise.StartLoop();
        slidingNoiseMaxVolume = slidingNoise.Loop.GetComponent <ControlledNoise>().MaxVolume;
    }
 /// <summary>
 /// Adds a static wall to be tracked.
 /// </summary>
 public void AddWall(RecBounds wall)
 {
     wallBounds.Add(wall);
 }
Exemple #5
0
 /// <summary>
 /// Finds if the given side of the given wall exists in this system.
 /// </summary>
 public bool SideExists(RecBounds wall, ColType side)
 {
     return(references.ContainsKey(wall) &&
            references[wall].ContainsKey(side));
 }
Exemple #6
0
 /// <summary>
 /// Finds if the given wall exists in this system.
 /// </summary>
 public bool WallExists(RecBounds wall)
 {
     return(references.ContainsKey(wall));
 }
Exemple #7
0
 /// <summary>
 /// Gets all sides of the givne wall that represent part of a Line.
 /// </summary>
 /// <param name="wall"></param>
 /// <returns></returns>
 public IEnumerable <ColType> GetSides(RecBounds wall)
 {
     return(references[wall].Keys.ToList());
 }
Exemple #8
0
 /// <summary>
 /// Gets all Lines that the given wall is a part of.
 /// </summary>
 public IEnumerable <Line> GetLines(RecBounds wall)
 {
     return(references[wall].Values.ToList());
 }
Exemple #9
0
    public static ColType CollisionType(RecBounds actor, Vector2 velocity, RecBounds wall)
    {
        //TODO: [SO FAR, THIS DOESN'T SEEM NECESSARY]. If the player hit a wall but only barely, and the y interval below/above the wall that the player is mainly occupying is clear, let him pass through the wall.

        //Figure out which edge was collided with first: top/bottom, or side. Return that edge.

        //1) Get the closest wall corner to the actor's center, and the opposite corner on the actor's bounds.

        Vector2 lastCenter  = actor.center - (velocity * Time.fixedDeltaTime);
        ColType topOrBottom = (lastCenter.y > wall.center.y) ? ColType.Top : ColType.Bottom;
        ColType leftOrRight = (lastCenter.x > wall.center.x) ? ColType.Right : ColType.Left;
        //If the actor is going at least half a unit per second, use

        Vector2 playerCenter = new Vector2(actor.center.x, actor.center.y);
        Vector2 wallCorner = new Vector2(wall.center.x - wall.extents.x, wall.center.y - wall.extents.y);
        Vector2 actorOppositeCorner = new Vector2(actor.center.x + actor.extents.x, actor.center.y + actor.extents.y);
        float   temp, tempDistSqr = System.Single.MaxValue;

        //Go through every corner searching for the closest.
        Vector2 tempDir, tempCorner;

        for (int i = 0; i < 4; ++i)
        {
            switch (i)
            {
            case 0:
                tempDir = new Vector2(-1.0f, -1.0f);
                break;

            case 1:
                tempDir = new Vector2(-1.0f, 1.0f);
                break;

            case 2:
                tempDir = new Vector2(1.0f, -1.0f);
                break;

            case 3:
                tempDir = new Vector2(1.0f, 1.0f);
                break;

            default:
                tempDir = Vector2.zero;
                break;
            }

            tempCorner = new Vector2(wall.center.x + (tempDir.x * wall.extents.x),
                                     wall.center.y + (tempDir.y * wall.extents.y));
            temp = Mathf.Pow(playerCenter.x - tempCorner.x, 2.0f) + Mathf.Pow(playerCenter.y - tempCorner.y, 2.0f);

            if (temp < tempDistSqr)
            {
                tempDistSqr         = temp;
                actorOppositeCorner = new Vector2(actor.center.x - (tempDir.x * actor.extents.x),
                                                  actor.center.y - (tempDir.y * actor.extents.y));
                wallCorner = tempCorner;
            }
        }

        //2) Get the amount of overlap along both dimensions.
        Vector2 overlap = wallCorner - actorOppositeCorner;

        //3) Handle edge cases for the overlap.
        const float marginOfErrorOverlap = 0.01f;

        if (Mathf.Abs(overlap.x) <= marginOfErrorOverlap)
        {
            return(leftOrRight);
        }
        if (Mathf.Abs(overlap.y) <= marginOfErrorOverlap)
        {
            return(topOrBottom);
        }

        //4) Handle edge cases for velocity.
        //No margin of error is needed because StateMachines already set the velocity to 0 when under a certain magnitude.
        if (velocity.x == 0)
        {
            return(topOrBottom);
        }
        if (velocity.y == 0)
        {
            return(leftOrRight);
        }

        //5) Get the amount of time needed at the actor's current velocity
        //   to move both the side and top/bottom edges back to bare contact with the wall.
        Vector2 t = new Vector2(Mathf.Abs(overlap.x / velocity.x), Mathf.Abs(overlap.y / velocity.y));

        //6) Depending on which edge would take longer to move back to bare contact
        //   (i.e. which edge was collided with first), return the correct value.
        if (t.x < t.y)
        {
            return(leftOrRight);
        }
        else
        {
            return(topOrBottom);
        }
    }
Exemple #10
0
    void CollideWithWall(RecBounds bounds)
    {
        if (DebugStopOnCol)
        {
            DebugStopOnCol = DebugStopOnCol;
        }

        StateMachine.DrawBounds(bounds, Color.cyan);

        //Get the side of the wall that was collided with. Ignore collision if necessary.
        ColType c = CollisionType(thisActor.NextActorBounds, thisActor.Velocity, bounds);

        if (disableVerticalColl && (c == ColType.Bottom || c == ColType.Top))
        {
            return;
        }

        //Get the closest single wall inside the bound to the player.
        Vector2   wallCenter = new Vector2(Mathf.RoundToInt(transform.position.x), Mathf.RoundToInt(transform.position.y));
        RecBounds tempB;

        wallCenter = new Vector2(Mathf.Clamp(wallCenter.x, bounds.left + 0.5f, bounds.right - 0.5f),
                                 Mathf.Clamp(wallCenter.y, bounds.bottom + 0.5f, bounds.top - 0.5f));
        if (false && !bounds.Inside(wallCenter))
        {
            switch (c)
            {
            case ColType.Bottom:
                wallCenter.y += 1.0f;
                break;

            case ColType.Left:
                wallCenter.x += 1.0f;
                break;

            case ColType.Top:
                wallCenter.y -= 1.0f;
                break;

            case ColType.Right:
                wallCenter.x -= 1.0f;
                break;

            default: throw new NotImplementedException();
            }
        }

        tempB = new RecBounds(wallCenter, new Vector2(1.0f, 1.0f));

        Line l = null;

        //Check to see if the line exists in the collision tracker.
        if (!colTracker.Lines.WallExists(tempB))
        {
            //Debug.Log("Wall not valid: wall " + bounds + ", small wall " + tempB + ", side " + CollisionManager.ToString(c));

            //Create a substitute line.
            switch (c)
            {
            case ColType.Bottom:
                l = new Line(Line.Orientation.Horizontal, new Interval(tempB.left, tempB.right, true, 2), tempB.bottom);
                break;

            case ColType.Left:
                l = new Line(Line.Orientation.Vertical, new Interval(tempB.bottom, tempB.top, true, 2), tempB.left);
                break;

            case ColType.Top:
                l = new Line(Line.Orientation.Horizontal, new Interval(tempB.left, tempB.right, true, 2), tempB.top);
                break;

            case ColType.Right:
                l = new Line(Line.Orientation.Vertical, new Interval(tempB.bottom, tempB.top, true, 2), tempB.right);
                break;
            }
        }
        else if (!colTracker.Lines.SideExists(tempB, c))
        {
            //Debug.Log("Coll. side not valid: wall " + bounds + ", small wall " + tempB + ", side " + CollisionManager.ToString(c));

            //Create a substitute line.
            switch (c)
            {
            case ColType.Bottom:
                l = new Line(Line.Orientation.Horizontal, new Interval(tempB.left, tempB.right, true, 2), tempB.bottom);
                break;

            case ColType.Left:
                l = new Line(Line.Orientation.Vertical, new Interval(tempB.bottom, tempB.top, true, 2), tempB.left);
                break;

            case ColType.Top:
                l = new Line(Line.Orientation.Horizontal, new Interval(tempB.left, tempB.right, true, 2), tempB.top);
                break;

            case ColType.Right:
                l = new Line(Line.Orientation.Vertical, new Interval(tempB.bottom, tempB.top, true, 2), tempB.right);
                break;
            }
        }
        else
        {
            l = colTracker.Lines.GetLine(tempB, c);
        }

        l = new Line(l.Dir, new Interval(l.LineRange), l.ConstValue);
        l.LineRange.Range -= ColLineMarginOfError * 2.0f;

        //If the collision was already being tracked, don't change anything.
        if (WallSides[c].Contains(l))
        {
            return;
        }
        //Otherwise, start tracking the line.
        WallSides[c].Add(l);
        SendMessage("WallCollision", new ColIndexPair()
        {
            Index = WallSides[c].Count - 1, Type = c
        }, SendMessageOptions.DontRequireReceiver);
    }
Exemple #11
0
    public static bool OnLine(Line l, ColType side, RecBounds b)
    {
        const float error = 0.01f;

        switch (side)
        {
        case ColType.Bottom:

            //Make sure this line makes sense.
            if (l.Dir == Line.Orientation.Vertical)
            {
                throw new ArgumentException();
            }

            //Next, if the bound's top edge isn't touching the line, exit.
            float top     = b.center.y + b.extents.y;
            float lineTop = l.ConstValue;
            if (!StateMachine.WithinError(top, lineTop, error))
            {
                return(false);
            }

            //Finally, check to make sure the bounds are within the range of the line.
            return(l.LineRange.Touches(new Interval(b.center.x - b.extents.x, b.center.x + b.extents.x, true, 2)));

        case ColType.Top:

            //Make sure this line makes sense.
            if (l.Dir == Line.Orientation.Vertical)
            {
                throw new ArgumentException();
            }

            //Next, if the bound's bottom edge isn't touching the line, exit.
            float bottom     = b.center.y - b.extents.y;
            float lineBottom = l.ConstValue;
            if (!StateMachine.WithinError(bottom, lineBottom, error))
            {
                return(false);
            }

            //Finally, check to make sure the bounds are within the range of the line.
            return(l.LineRange.Touches(new Interval(b.center.x - b.extents.x, b.center.x + b.extents.x, true, 2)));

        case ColType.Left:

            //Make sure this line makes sense.
            if (l.Dir == Line.Orientation.Horizontal)
            {
                throw new ArgumentException();
            }

            //Next, if the bound's right edge isn't touching the line, exit.
            float right     = b.center.x + b.extents.x;
            float lineRight = l.ConstValue;
            if (!StateMachine.WithinError(right, lineRight, error))
            {
                return(false);
            }

            //Finally, check to make sure the bounds are within the range of the line.
            return(l.LineRange.Touches(new Interval(b.center.y - b.extents.y, b.center.y + b.extents.y, true, 2)));

        case ColType.Right:

            //Make sure this line makes sense.
            if (l.Dir == Line.Orientation.Horizontal)
            {
                throw new ArgumentException();
            }

            //Next, if the bound's left edge isn't touching the line, exit.
            float left     = b.center.x - b.extents.x;
            float lineLeft = l.ConstValue;
            if (!StateMachine.WithinError(left, lineLeft, error))
            {
                return(false);
            }

            //Finally, check to make sure the bounds are within the range of the line.
            return(l.LineRange.Touches(new Interval(b.center.y - b.extents.y, b.center.y + b.extents.y, true, 2)));

        default: throw new NotImplementedException();
        }
    }
Exemple #12
0
    /// <summary>
    /// Adds the given wall boundaries to the collection of walls to create.
    /// </summary>
    /// <exception cref="InvalidOperationException">Thrown if this object is no longer taking walls to create.</exception>
    public void AddWall(RecBounds b)
    {
        if (currentWallsState != InitializeWallsState.TakingWalls)
        {
            throw new System.InvalidOperationException("This object is no longer taking walls!");
        }

        WallBounds.Add(b);

        //If the wall is close enough to the edge and the level wraps around horizontally, duplicate it.
        if (WrapX)
        {
            float left  = b.center.x - b.extents.x,
                  right = b.center.x + b.extents.x;

            //If the wall is near the left edge, put a wall on the right.
            if (Mathf.Abs(left - (levelBounds.center.x - levelBounds.extents.x)) <= 1.0f)
            {
                MirroredWallBounds.Add(new RecBounds(b.center + new Vector2(WorldConstants.Size.x, 0.0f), b.size));
                //If the level also wraps vertically, put the wall above and below.
                if (WrapY)
                {
                    MirroredWallBounds.Add(new RecBounds(b.center + new Vector2(WorldConstants.Size.x, -WorldConstants.Size.y), b.size));
                    MirroredWallBounds.Add(new RecBounds(b.center + new Vector2(WorldConstants.Size.x, WorldConstants.Size.y), b.size));
                }
            }
            //If the wall is near the right edge, put a wall on the left.
            if (Mathf.Abs(right - (levelBounds.center.x + levelBounds.extents.x)) <= 1.0f)
            {
                MirroredWallBounds.Add(new RecBounds(b.center + new Vector2(-WorldConstants.Size.x, 0.0f), b.size));
                //If the level also wraps vertically, put the wall above and below.
                if (WrapY)
                {
                    MirroredWallBounds.Add(new RecBounds(b.center + new Vector2(-WorldConstants.Size.x, -WorldConstants.Size.y), b.size));
                    MirroredWallBounds.Add(new RecBounds(b.center + new Vector2(-WorldConstants.Size.x, WorldConstants.Size.y), b.size));
                }
            }
        }
        //Do the same for vertical wrapping.
        if (WrapY)
        {
            float bottom = b.center.y - b.extents.y,
                  top    = b.center.y + b.extents.y;
            //If the wall is near the bottom edge, put a wall on the top.
            if (Mathf.Abs(bottom - (levelBounds.center.y - levelBounds.extents.y)) <= 1.0f)
            {
                MirroredWallBounds.Add(new RecBounds(b.center + new Vector2(0.0f, WorldConstants.Size.y), b.size));
                //If the level also wraps horizontally, put the wall to the left and right.
                if (WrapX)
                {
                    MirroredWallBounds.Add(new RecBounds(b.center - new Vector2(-WorldConstants.Size.x, WorldConstants.Size.y), b.size));
                    MirroredWallBounds.Add(new RecBounds(b.center + new Vector2(WorldConstants.Size.x, WorldConstants.Size.y), b.size));
                }
            }
            //If the wall is near the top edge, put a wall on the bottom.
            if (Mathf.Abs(top - (levelBounds.center.y + levelBounds.extents.y)) <= 1.0f)
            {
                MirroredWallBounds.Add(new RecBounds(b.center + new Vector2(0.0f, -WorldConstants.Size.y), b.size));
                //If the level also wraps horizontally, put the wall to the left and right.
                if (WrapX)
                {
                    MirroredWallBounds.Add(new RecBounds(b.center + new Vector2(WorldConstants.Size.x, -WorldConstants.Size.y), b.size));
                    MirroredWallBounds.Add(new RecBounds(b.center + new Vector2(-WorldConstants.Size.x, -WorldConstants.Size.y), b.size));
                }
            }
        }
    }