Пример #1
0
        protected override void DoCheck(IMovable user, ref Vector2 vel, ref CollisionStatus collStatus, LayerMask mask,
                                        Bounds2D bounds, Bounds2D shrinkedBounds)
        {
            //Direction
            var direction       = Math.Sign(vel.y);
            var verticalRays    = user.VerticalRaycasts;
            var directionVector = new Vector2(0, vel.y * Time.deltaTime);
            // Bounds2D
            var bMin        = bounds.Min;
            var bMax        = bounds.Max;
            var positiveDir = direction == 1;

            var originX   = shrinkedBounds.Min.x;
            var originY   = positiveDir ? bMax.y : bMin.y;
            var origin    = new Vector2(originX, originY);
            var width     = shrinkedBounds.Size.x;
            var spacing   = width / (verticalRays - 1);
            var rayLength = directionVector.magnitude;

            LastHit = null;
            var hitDown = false;

            for (byte x = 0; x < verticalRays; x++)
            {
                var raycast = Physics2D.Raycast(origin, directionVector, rayLength, mask);
                Debug.DrawRay(origin, directionVector, raycast ? Color.green : Color.red);
                if (raycast && !raycast.collider.isTrigger && raycast.distance < rayLength)
                {
                    LastHit         = raycast;
                    vel.y           = raycast.distance / Time.deltaTime * direction;
                    rayLength       = raycast.distance;
                    collStatus.Down = direction == -1;
                    collStatus.Up   = direction == 1;
                    if (!hitDown)
                    {
                        hitDown = direction == -1;
                    }
                }

                origin.x += spacing;
            }

            if (!hitDown)
            {
                collStatus.Down = false;
            }
        }
Пример #2
0
        public override void Move(IMovable user, ref Vector2 velocity, ref CollisionStatus collisionStatus, StateMotorMachine machine, StateMotorConfig config1, LayerMask collisionMask)
        {
            var config = user.GetMotorConfig <GroundMotorConfig>();

            if (config == null)
            {
                UPMDebug.LogWarning("Expected GroundMotorConfig for GroundedState @ " + user);
                return;
            }

            ProcessInputs(user, config, ref velocity, ref collisionStatus);
            velocity.y += Gravity * config.GravityScale * Time.deltaTime;
            var max = user.MaxSpeed;

            velocity.x = Mathf.Clamp(velocity.x, -max, max);
            GroundedBehaviour.Check(user, ref velocity, ref collisionStatus, collisionMask);
        }
Пример #3
0
        public CollisionInformations(CollisionStatus status, Box obj, Box target, float tc, Vector3 x0p, Vector3 x1p, Vector3 p0p, Vector3 p1p, Vector3 speed0, Vector3 speed1, Vector3 speed20, Vector3 speed21, Vector3 av, Vector3 aw)
        {
            collision_type = status;
            colliding_obj  = obj;
            target_obj     = target;
            t = tc;

            suggested_x0 = x0p;
            suggested_x1 = x1p;
            suggested_p0 = p0p;
            suggested_p1 = p1p;

            suggested_av = av;
            suggested_aw = aw;

            suggested_speed0  = speed0;
            suggested_speed1  = speed1;
            suggested_speed20 = speed20;
            suggested_speed21 = speed21;
        }
Пример #4
0
        public override void Move(IMovable user, ref Vector2 velocity, ref CollisionStatus status)
        {
            var config = user.GetMotorConfig <StateMotorConfig>();

            if (config == null)
            {
                UPMDebug.LogWarning("Expected user " + user + " to have a StateMotorConfig but found none");
                return;
            }

            var m = config.StateMachine;

            if (m == null)
            {
                UPMDebug.LogError("Expected user " + user + " to have a state machine but found none");
                return;
            }

            m.Move(user, ref velocity, ref status, config, CollisionMask);
        }
Пример #5
0
        private CollisionInformations()
        {
            collision_type   = CollisionStatus.NO_COLLISION;
            suggested_speed0 = Vector3.Zero;
            suggested_speed1 = Vector3.Zero;
            suggested_x0     = Vector3.Zero;
            suggested_x1     = Vector3.Zero;

            suggested_speed20 = Vector3.Zero;
            suggested_speed21 = Vector3.Zero;
            suggested_p0      = Vector3.Zero;
            suggested_p1      = Vector3.Zero;

            suggested_av = Vector3.Zero;
            suggested_aw = Vector3.Zero;

            colliding_obj = null;
            target_obj    = null;

            t = 1;  // whole deltaT passed
        }
Пример #6
0
        public CollisionInformations(CollisionStatus status, Vector3 x0p, Vector3 x1p, Vector3 spd1)
        {
            collision_type   = status;
            suggested_speed0 = spd1;
            suggested_speed1 = spd1;
            suggested_x0     = x0p;
            suggested_x1     = x1p;

            suggested_speed20 = Vector3.Zero;
            suggested_speed21 = Vector3.Zero;
            suggested_p0      = Vector3.Zero;
            suggested_p1      = Vector3.Zero;

            suggested_av = Vector3.Zero;
            suggested_aw = Vector3.Zero;

            colliding_obj = null;
            target_obj    = null;

            t = 1;
        }
Пример #7
0
        public CollisionInformations(CollisionStatus status, Vector3 x0p, Vector3 x1p, Vector3 spd1, Box obj, Box target, float tc)
        {
            collision_type   = status;
            suggested_speed0 = spd1;
            suggested_speed1 = spd1;
            suggested_x0     = x0p;
            suggested_x1     = x1p;

            suggested_speed20 = Vector3.Zero;
            suggested_speed21 = Vector3.Zero;
            suggested_p0      = Vector3.Zero;
            suggested_p1      = Vector3.Zero;

            suggested_av = Vector3.Zero;
            suggested_aw = Vector3.Zero;

            colliding_obj = obj;
            target_obj    = target;

            t = tc;
        }
Пример #8
0
        public CollisionInformations(Vector3 x0p, Vector3 x1p, Vector3 spd1, float tc)
        {
            collision_type   = CollisionStatus.COLLISION_FIXED;
            suggested_speed0 = spd1;
            suggested_speed1 = spd1;
            suggested_x0     = x0p;
            suggested_x1     = x1p;

            suggested_speed20 = Vector3.Zero;
            suggested_speed21 = Vector3.Zero;
            suggested_p0      = Vector3.Zero;
            suggested_p1      = Vector3.Zero;

            suggested_av = Vector3.Zero;
            suggested_aw = Vector3.Zero;

            colliding_obj = null;
            target_obj    = null;

            t = tc;
        }
Пример #9
0
        // this method exists so that derived classes can decide what changes can be made
        // to itself just before a collision happen, like for example,
        // removing bananas as the monkey collects them
        protected virtual CollisionStatus BeforeCollision(Collidable <TBoard> otherCollidable, CollisionStatus direction)
        {
            // this is meant for overriding
            // but by default, there should be no effect

            // if we do not want CollisionAfter to be invoked after this method, simply set direction to
            // no collision

            return(direction);
        }
Пример #10
0
 public CollisionEventArgs(Collidable <TBoard> otherCollidable, CollisionStatus direction)
 {
     Direction       = direction;
     OtherCollidable = otherCollidable;
 }
        protected override CollisionStatus BeforeCollision(Collidable <MonkeyBoard> otherCollidable, CollisionStatus direction)
        {
            // display some debug message
            if (otherCollidable is Monkey)
            {
                // this will get board to remove positional, unbind its tick from given positional, and emit an event to boardUI to remove other aspects
                eatSound.Play();

                // this works because MonkeyBanana must take in only MonkeyBoard
                Board.Dispatcher.Invoke((Action)(() => Board.IncrementBananaCollected()));
                Board.RemovePositional(this);

                return(CollisionStatus.NoCollision);
            }

            return(direction);
        }
Пример #12
0
 // Use this for initialization
 void Start()
 {
     status = new CollisionStatus();
     status.Setup();
 }
        private static void FireBullets(MutableGameState gameState, TankAction[] tankActions, bool[] bulletsThatMovedThisTurn, IList <Point> wallsRemoved)
        {
            bool[]  bulletWasFired = new bool[Constants.TANK_COUNT];
            Point[] wallsShot      = new Point[MAX_WALLS_SHOT];
            byte    wallsShotCount = 0;

#if DEBUG
            CollisionStatus[] collisionStatuses = new CollisionStatus[Constants.ALL_ELEMENT_COUNT];
#endif
            for (int t = 0; t < tankActions.Length; t++)
            {
                TankAction tankAction = tankActions[t];
                if (tankAction != TankAction.FIRE)
                {
                    continue;
                }

                MobileState tankState = gameState.MobileStates[t];
                if (!tankState.IsActive)
                {
                    continue;
                }

                // A bullet can't be fired if there is already an active bullet from the same tank:
                int         bulletIndex = t + Constants.TANK_COUNT;
                MobileState bulletState = gameState.MobileStates[bulletIndex];
                if (bulletState.IsActive)
                {
                    continue;
                }

                // If a bullet was active this turn but was destroyed,
                // then the tank probably still can't fire another bullet yet:
                // UPDATE: It seems that the harness does allow this...
                if (bulletsThatMovedThisTurn[t] &&
                    !GameRuleConfiguration.RuleConfiguration.CanATankFireAgainOnTheSameTurnThatItsBulletWasDestroyed)
                {
                    continue;
                }

                bulletState = tankState.FireABulletAndGetItsState();

                // A bullet can't be shot outside the board:
                if (bulletState.Pos.X < 0 ||
                    bulletState.Pos.Y < 0 ||
                    bulletState.Pos.X >= Game.Current.BoardWidth ||
                    bulletState.Pos.Y >= Game.Current.BoardHeight)
                {
#if DEBUG
                    collisionStatuses[bulletIndex] |= CollisionStatus.WithOutOfBoundsArea;
#endif
                    bulletState = bulletState.Kill();
                    gameState.MobileStates[bulletIndex] = bulletState;
                    continue;
                }

                // Check if there is a wall to shoot:
                if (!gameState.Walls[bulletState.Pos])
                {
                    gameState.MobileStates[bulletIndex] = bulletState;
                    bulletWasFired[t] = true;
                }
                else
                {
                    bulletState = bulletState.Kill();
                    gameState.MobileStates[bulletIndex] = bulletState;

                    /* Shoot out the walls on the segment.
                     * Assume that they are all in bounds since the tank could not have shot the bullet otherwise
                     * TODO: What to do when the board shrinks after the time limit is up,
                     * as then part of the segment could be out of bounds?
                     */
                    int first;
                    int last;
                    int x;
                    int y;

                    switch (bulletState.Dir)
                    {
                    case Direction.LEFT:
                    case Direction.RIGHT:
                        x     = bulletState.Pos.X;
                        first = bulletState.Pos.Y - 2;
                        last  = bulletState.Pos.Y + 2;
                        for (y = first; y <= last; y++)
                        {
                            if (gameState.Walls[x, y])
                            {
                                wallsShot[wallsShotCount] = new Point((short)x, (short)y);
                                wallsShotCount++;
                            }
                        }
                        break;

                    case Direction.DOWN:
                    case Direction.UP:
                        y     = bulletState.Pos.Y;
                        first = bulletState.Pos.X - 2;
                        last  = bulletState.Pos.X + 2;
                        for (x = first; x <= last; x++)
                        {
                            if (gameState.Walls[x, y])
                            {
                                wallsShot[wallsShotCount] = new Point((short)x, (short)y);
                                wallsShotCount++;
                            }
                        }
                        break;
                    }
                }
            }

            // Check for collisions between bullets, tanks and bases:
            for (int t = 0; t < Constants.TANK_COUNT; t++)
            {
                if (!bulletWasFired[t])
                {
                    continue;
                }

                int         b           = t + Constants.TANK_COUNT;
                MobileState bulletState = gameState.MobileStates[b];
                if (!bulletState.IsActive)
                {
                    continue;
                }

                // Check for collisions with other bullets, tanks and bases:
                for (int i = 0; i < Constants.MOBILE_ELEMENT_COUNT; i++)
                {
                    if (i == b)
                    {
                        continue;
                    }

                    MobileState otherState = gameState.MobileStates[i];
                    if (otherState.IsActive)
                    {
                        if (i < Constants.TANK_COUNT)
                        {
                            // Check for collision with a tank:
                            if (otherState.GetTankExtent().ContainsPoint(bulletState.Pos))
                            {
#if DEBUG
                                collisionStatuses[i] |= CollisionStatus.WithBullet;
                                collisionStatuses[b] |= CollisionStatus.WithTank;
#endif
                                bulletState = bulletState.Kill();
                                gameState.MobileStates[b] = bulletState;
                                gameState.MobileStates[i] = otherState.Kill();
                            }
                        }
                        else
                        {
                            // Check for collision with another bullet:
                            if (otherState.Pos == bulletState.Pos)
                            {
#if DEBUG
                                collisionStatuses[b] |= CollisionStatus.WithBullet;
                                collisionStatuses[i] |= CollisionStatus.WithBullet;
#endif
                                bulletState = bulletState.Kill();
                                gameState.MobileStates[b] = bulletState;
                                gameState.MobileStates[i] = otherState.Kill();
                            }
                        }
                    }
                }

                // Check for collisions with bases:
                for (int p = 0; p < Constants.PLAYERS_PER_GAME; p++)
                {
                    Base @base = Game.Current.Players[p].Base;
                    if (bulletState.Pos == @base.Pos)
                    {
#if DEBUG
                        collisionStatuses[b] |= CollisionStatus.WithBase;
#endif
                        bulletState = bulletState.Kill();
                        gameState.MobileStates[b] = bulletState;
                        gameState.Outcome        |= (Outcome)(((byte)Outcome.Player1BaseKilled) << p);
                    }
                }
            }

            // Remove walls that were shot:
            for (int w = 0; w < wallsShotCount; w++)
            {
                if (wallsRemoved == null)
                {
                    gameState.Walls[wallsShot[w]] = false;
                }
                else
                {
                    Point wall = wallsShot[w];
                    if (gameState.Walls[wall])
                    {
                        gameState.Walls[wall] = false;
                        wallsRemoved.Add(wall);
                    }
                }
            }
        }
Пример #14
0
 public abstract void Move(IMovable user, ref Vector2 velocity, ref CollisionStatus status);
        protected override void CollisionAfter(Collidable <MonkeyBoard> otherCollidable, CollisionStatus direction)
        {
            if (otherCollidable is Crate)
            {
                if (direction == CollisionStatus.CollisionFromLeft || direction == CollisionStatus.CollisionFromRight)
                {
                    LastCrateCollisionDirection = direction;
                }
                else if (direction == CollisionStatus.CollisionFromTop)
                {
                    Board.TempRemovePositional(this);

                    if (LastCrateCollisionDirection == CollisionStatus.CollisionFromLeft)
                    {
                        SetPosition(otherCollidable.X + 1, Y, 0, 0);
                    }
                    else
                    {
                        SetPosition(otherCollidable.X - 1, Y, 0, 0);
                    }

                    Board.RestorePositional(this);
                    Board.Dispatcher.Invoke((Action)(() => Board.DecreaseNumberOfLives()));
                }
            }
        }
Пример #16
0
 protected abstract void DoCheck(IMovable user, ref Vector2 vel, ref CollisionStatus collStatus, LayerMask mask,
                                 Bounds2D bounds,
                                 Bounds2D shrinkedBounds);
Пример #17
0
 protected override void CollisionAfter(Collidable <TBoard> otherCollidable, CollisionStatus direction)
 {
     OnColliding(new CollisionEventArgs <TBoard>(otherCollidable, direction));
     base.CollisionAfter(otherCollidable, direction);
 }
        protected override void CollisionAfter(Collidable <MonkeyBoard> otherCollidable, CollisionStatus direction)
        {
            if (otherCollidable is Monkey && !IsMonkeyAtDoor)
            {
                // culprit
                // can't fade out here and don't know why
                // should be something to do with threading
                // can't go past stage 2 also

                Board.Dispatcher.Invoke((Action)(() =>
                {
                    Board.OnBoardFadeOut(this);
                    IsMonkeyAtDoor = true;
                }));
            }
        }
        protected override void CollisionAfter(Collidable <MonkeyBoard> otherCollidable, CollisionStatus direction)
        {
            if (otherCollidable is Monkey)
            {
                Monkey monkey = otherCollidable as Monkey;

                if (!IsCurrentlySliding() && monkey.IsOnGround())
                {
                    if (direction == CollisionStatus.CollisionFromLeft && monkey.IsTryingToMoveRight ||
                        direction == CollisionStatus.CollisionFromRight && monkey.IsTryingToMoveLeft)
                    {
                        if (!StartedPush)
                        {
                            StartedPush = true;
                            //Debug.WriteLine("started push");
                        }
                        else if (PushTick == DelayTicks)
                        {
                            // this means that there is enough "push" on the crate
                            // and it should start moving

                            if (direction == CollisionStatus.CollisionFromLeft)
                            {
                                SlideRight();
                            }
                            else
                            {
                                SlideLeft();
                            }

                            // resets push tick
                            StartedPush = false;
                            PushTick    = 0;

                            soundPlayer.Play();
                        }
                    }
                }
            }
        }
 protected override void CollisionAfter(Collidable <MonkeyBoard> otherCollidable, CollisionStatus direction)
 {
 }
        // Update position AGV icon in simulation mode (speed: cm/s)
        public static Point SimUpdatePositionAGV(int agvID, float speed)
        {
            // Find AGV in SimListAGV, get current point
            var   index    = AGV.SimListAGV.FindIndex(a => a.ID == agvID);
            AGV   agv      = AGV.SimListAGV[index];
            Point position = Display.SimLabelAGV[agvID].Location;

            // Handle (waiting method) collision if it happens
            CollisionStatus status = Collision.SimHandle(agv, Collision.SimListCollision);

            if (status == CollisionStatus.Handling)
            {
                // Update agv status and velocity
                agv.Velocity = 0;
                agv.Status   = "Stop";

                return(position);
            }

            // return old point when agv has no path
            if (agv.Path.Count == 0)
            {
                return(position);
            }

            // Get navigation frame array. Note: string is a reference type,
            // so any change in navigationArr is also in AGV.SimListAGV[index].navigationArr
            string[] navigationArr = agv.navigationArr;

            // Check whether current point is a node or not
            // Note: shift position of label to center (+LabelAGV[].Width/2, +LabelAGV[].Height/2)
            var node = Node.ListNode.FirstOrDefault(n =>
            {
                return((n.X == position.X + SimLabelAGV[agvID].Width / 2) &&
                       (n.Y == position.Y + SimLabelAGV[agvID].Height / 2));
            });

            // Current point is not a node and current position is start node,
            // it means initDistance to start node != 0, so go backward once then keep go ahead
            char orient = new char();

            if (node == null && agv.ExitNode == agv.Path[0])
            {
                switch (navigationArr[0])
                {
                case "A":
                    orient = UpdateOrient(agv.Orientation, "A");
                    break;

                case "B":
                    orient           = UpdateOrient(agv.Orientation, "B");
                    navigationArr[0] = "A";
                    break;
                }
            }
            // Current point is not a node and current position is not start node,
            // so keep go ahead
            else if (node == null)
            {
                orient = UpdateOrient(agv.Orientation, "A");
            }
            // If goal was reached, no update position, remove old path, get next path (if exist)
            else if (node.ID == agv.Path.LastOrDefault())
            {
                // Update AGV information
                agv.ExitNode           = node.ID; // Update ExitNode
                orient                 = UpdateOrient(agv.Orientation, "A");
                agv.Orientation        = orient;  // Update Orientation
                agv.DistanceToExitNode = 0f;      // Update Distance to ExitNode
                agv.Status             = "Stop";  // Update Status
                agv.Velocity           = 0;       // Update Velocity

                // Add next path
                Task.AddNextPathOfSimAGV(agv);

                return(position);
            }
            // Current point is at start node and initDistance to start node == 0
            // Turn direction once then keep go ahead
            else if (node.ID == agv.Path[0] && agv.DistanceToExitNode == 0f)
            {
                switch (navigationArr[0])
                {
                case "A":
                    orient = UpdateOrient(agv.Orientation, "A");
                    break;

                case "B":
                    orient           = UpdateOrient(agv.Orientation, "B");
                    navigationArr[0] = "A";
                    break;

                case "L":
                    orient           = UpdateOrient(agv.Orientation, "L");
                    navigationArr[0] = "A";
                    break;

                case "R":
                    orient           = UpdateOrient(agv.Orientation, "R");
                    navigationArr[0] = "A";
                    break;
                }

                // If this node is pick node, remove pallet code that was picked and save this time
                if (agv.Tasks.Count != 0 && node.ID == agv.Tasks[0].PickNode)
                {
                    RackColumn column = RackColumn.SimListColumn.Find(c => c.AtNode == agv.ExitNode);

                    Pallet.SaveDeliveryTime(column.PalletCodes[agv.Tasks[0].PickLevel - 1], Pallet.SimListPallet);
                    DBUtility.UpdatePalletDB("SimPalletInfoTable", column.PalletCodes[agv.Tasks[0].PickLevel - 1], false,
                                             DateTime.Now.ToString("dddd, MMMM dd, yyyy  h:mm:ss tt"), Pallet.SimListPallet);

                    column.PalletCodes[agv.Tasks[0].PickLevel - 1] = null;
                }
            }
            // Current point is a node but start node
            else
            {
                int    idx = Array.IndexOf(navigationArr, node.ID.ToString());
                string dir = navigationArr[idx + 1];
                orient = UpdateOrient(agv.Orientation, dir);
            }

            // Modify speed to make sure AGV icon can reach next node
            int i        = agv.Path.IndexOf(agv.ExitNode);
            int nextNode = agv.Path[i + 1];
            int dnx      = (position.X + SimLabelAGV[agvID].Width / 2) - Node.ListNode[nextNode].X;
            int dny      = (position.Y + SimLabelAGV[agvID].Height / 2) - Node.ListNode[nextNode].Y;
            int nd       = (int)Math.Sqrt(dnx * dnx + dny * dny);

            if (agv.ExitNode == agv.Path[0])
            {
                // At first node of path, having 4 cases of agv position
                // (dnx * dny != 0) for 2 cases and (dnx * dnx0 > 0 || dny * dny0 > 0) for the others
                int dnx0 = (position.X + SimLabelAGV[agvID].Width / 2) - Node.ListNode[agv.Path[0]].X;
                int dny0 = (position.Y + SimLabelAGV[agvID].Height / 2) - Node.ListNode[agv.Path[0]].Y;
                int nd0  = (int)Math.Sqrt(dnx0 * dnx0 + dny0 * dny0);
                if (dnx * dny != 0 || dnx * dnx0 > 0 || dny * dny0 > 0)
                {
                    nextNode = agv.Path[0];
                    nd       = nd0;
                }
            }
            int sp   = (int)Math.Round(speed * Display.Scale * (100.0 / 1000)); // timer1.Interval = 100ms
            int step = (nd % sp == 0) ? sp : (nd % sp);

            // Update AGV information before update position
            if (node != null)
            {
                agv.ExitNode = node.ID; // Update ExitNode
            }
            agv.Orientation = orient;   // Update Orientation
            int exitNode = agv.ExitNode;
            int dx       = (position.X + SimLabelAGV[agvID].Width / 2) - Node.ListNode[exitNode].X;
            int dy       = (position.Y + SimLabelAGV[agvID].Height / 2) - Node.ListNode[exitNode].Y;

            agv.DistanceToExitNode = (float)Math.Sqrt(dx * dx + dy * dy) / Display.Scale; // Update Distance to ExitNode
            agv.Status             = "Running";                                           // Update Status

            // Update next position of AGV icon in panel
            switch (orient)
            {
            case 'E':
                position = new Point(position.X + step, position.Y);
                break;

            case 'W':
                position = new Point(position.X - step, position.Y);
                break;

            case 'S':
                position = new Point(position.X, position.Y + step);
                break;

            case 'N':
                position = new Point(position.X, position.Y - step);
                break;
            }

            return(position);
        }
Пример #22
0
 public void Move(IMovable user, ref Vector2 velocity, ref CollisionStatus status, StateMotorConfig config, LayerMask collisionMask)
 {
     state.Move(user, ref velocity, ref status, this, config, collisionMask);
 }
Пример #23
0
 protected override void CollisionAfter(Collidable <MonkeyBoard> otherCollidable, CollisionStatus direction)
 {
     if (otherCollidable is AI <MonkeyBoard> )
     {
         AIKilledSound.Play();
         Board.RemovePositional(otherCollidable);
         Board.RemovePositional(this);
     }
     if (otherCollidable is BorderTile)
     {
         Board.RemovePositional(this);
     }
 }
Пример #24
0
        protected override void CollisionAfter(Collidable <MonkeyBoard> otherCollidable, CollisionStatus direction)
        {
            if (!(otherCollidable is Monkey) && !(otherCollidable is BasicWeapon) && otherCollidable is Collidable <MonkeyBoard> )
            {
                RemoveMovement(PreviousMovement);

                if (direction == CollisionStatus.CollisionFromRight)
                {
                    PreviousMovement = new SlideLeftRight(Board.CalculateFineness(-MovementSpeedProportion));
                }
                else if (direction == CollisionStatus.CollisionFromLeft)
                {
                    PreviousMovement = new SlideLeftRight(Board.CalculateFineness(MovementSpeedProportion));
                }

                // changes the direction to reverse
                AddMovement(PreviousMovement);
            }

            base.CollisionAfter(otherCollidable, direction);
        }
Пример #25
0
 // this method exists so that derived classes can decide what changes can be made
 // to itself after a collision with another collidable object
 protected virtual void CollisionAfter(Collidable <TBoard> otherCollidable, CollisionStatus direction)
 {
     // this is meant for overriding
     // but by default, there should be no effect
 }
Пример #26
0
        protected override CollisionStatus BeforeCollision(Collidable <MonkeyBoard> otherCollidable, CollisionStatus direction)
        {
            if (otherCollidable is Monkey)
            {
                if (direction == CollisionStatus.CollisionFromTop)
                {
                    return(CollisionStatus.CollisionFromTop);
                }
                else
                {
                    Board.RemovePositional(otherCollidable);

                    if (MonkeyKilledSound != null)
                    {
                        MonkeyKilledSound.Play();
                    }

                    Board.Dispatcher.Invoke((Action)(() => Board.DecreaseNumberOfLives()));
                    return(CollisionStatus.NoCollision);
                }
            }

            return(base.BeforeCollision(otherCollidable, direction));
        }
        private static void MoveTanks(MutableGameState gameState, TankAction[] tankActions)
        {
#if DEBUG
            CollisionStatus[] collisionStatuses = new CollisionStatus[Constants.ALL_ELEMENT_COUNT];
#endif
            foreach (int t in GameRuleConfiguration.RuleConfiguration.TankMovementIndexes)
            {
                MobileState tankState = gameState.MobileStates[t];
                if (!tankState.IsActive)
                {
                    continue;
                }
                bool       canMove     = true;
                bool       willTurn    = true;
                bool       willDie     = false;
                TankAction tankAction  = tankActions[t];
                Direction  movementDir = Direction.NONE;
                int        firstSeg;
                int        lastSeg;
                int        segX       = 0;
                int        segY       = 0;
                int        newCentreX = tankState.Pos.X;
                int        newCentreY = tankState.Pos.Y;

                switch (tankAction)
                {
                case TankAction.UP:
                    movementDir = Direction.UP;
                    willTurn    = (movementDir != tankState.Dir);
                    if (tankState.Pos.Y <= Constants.TANK_EXTENT_OFFSET)
                    {
                        // Trying to move off the edge of the board:
#if DEBUG
                        collisionStatuses[t] |= CollisionStatus.WithOutOfBoundsArea;
#endif
                        canMove  = false;
                        willDie  = GameRuleConfiguration.RuleConfiguration.DoesATankDieIfTryingToMoveOffTheBoard;
                        willTurn = willTurn && GameRuleConfiguration.RuleConfiguration.DoesATankTurnIfTryingToMoveOffTheBoard;
                    }
                    else
                    {
                        newCentreY--;
                        segY = newCentreY - Constants.TANK_EXTENT_OFFSET;
                    }
                    break;

                case TankAction.DOWN:
                    movementDir = Direction.DOWN;
                    willTurn    = (movementDir != tankState.Dir);
                    if (tankState.Pos.Y + Constants.TANK_OUTER_EDGE_OFFSET >= Game.Current.BoardHeight)
                    {
                        // Trying to move off the edge of the board:
#if DEBUG
                        collisionStatuses[t] |= CollisionStatus.WithOutOfBoundsArea;
#endif
                        canMove  = false;
                        willDie  = GameRuleConfiguration.RuleConfiguration.DoesATankDieIfTryingToMoveOffTheBoard;
                        willTurn = willTurn && GameRuleConfiguration.RuleConfiguration.DoesATankTurnIfTryingToMoveOffTheBoard;
                    }
                    else
                    {
                        newCentreY++;
                        segY = newCentreY + Constants.TANK_EXTENT_OFFSET;
                    }
                    break;

                case TankAction.LEFT:
                    movementDir = Direction.LEFT;
                    willTurn    = (movementDir != tankState.Dir);
                    if (tankState.Pos.X <= Constants.TANK_EXTENT_OFFSET)
                    {
                        // Trying to move off the edge of the board:
#if DEBUG
                        collisionStatuses[t] |= CollisionStatus.WithOutOfBoundsArea;
#endif
                        canMove  = false;
                        willDie  = GameRuleConfiguration.RuleConfiguration.DoesATankDieIfTryingToMoveOffTheBoard;
                        willTurn = willTurn && GameRuleConfiguration.RuleConfiguration.DoesATankTurnIfTryingToMoveOffTheBoard;
                    }
                    else
                    {
                        newCentreX--;
                        segX = newCentreX - Constants.TANK_EXTENT_OFFSET;
                    }
                    break;

                case TankAction.RIGHT:
                    movementDir = Direction.RIGHT;
                    willTurn    = (movementDir != tankState.Dir);
                    if (tankState.Pos.X + Constants.TANK_OUTER_EDGE_OFFSET >= Game.Current.BoardWidth)
                    {
                        // Trying to move off the edge of the board:
#if DEBUG
                        collisionStatuses[t] |= CollisionStatus.WithOutOfBoundsArea;
#endif
                        canMove  = false;
                        willDie  = GameRuleConfiguration.RuleConfiguration.DoesATankDieIfTryingToMoveOffTheBoard;
                        willTurn = willTurn && GameRuleConfiguration.RuleConfiguration.DoesATankTurnIfTryingToMoveOffTheBoard;
                    }
                    else
                    {
                        newCentreX++;
                        segX = newCentreX + Constants.TANK_EXTENT_OFFSET;
                    }
                    break;

                default:
                    // case TankAction.FIRE:
                    // case TankAction.NONE:
                    canMove  = false;
                    willTurn = false;
                    break;
                }

                if (canMove)
                {
                    switch (movementDir)
                    {
                    case Direction.DOWN:
                    case Direction.UP:
                        firstSeg = newCentreX - Constants.TANK_EXTENT_OFFSET;
                        lastSeg  = newCentreX + Constants.TANK_EXTENT_OFFSET;
                        for (segX = firstSeg; segX <= lastSeg; segX++)
                        {
                            if (gameState.Walls[segX, segY])
                            {
                                canMove = false;
                                break;
                            }
                        }

                        if (canMove)
                        {
                            Rectangle newRect = new Rectangle(
                                (short)(newCentreX - Constants.TANK_EXTENT_OFFSET),
                                (short)(newCentreY - Constants.TANK_EXTENT_OFFSET),
                                (short)(newCentreX + Constants.TANK_EXTENT_OFFSET),
                                (short)(newCentreY + Constants.TANK_EXTENT_OFFSET));

                            // Check if moving into another tank:
                            for (int tOther = 0; tOther < Constants.TANK_COUNT; tOther++)
                            {
                                if (tOther != t)
                                {
                                    MobileState otherTankState = gameState.MobileStates[tOther];
                                    if (otherTankState.IsActive && otherTankState.GetTankExtent().IntersectsWith(newRect))
                                    {
                                        canMove = false;
                                        break;
                                    }
                                }
                            }

                            if (canMove)
                            {
                                // Check if moving into a bullet:
                                for (int b = Constants.MIN_BULLET_INDEX; b <= Constants.MAX_BULLET_INDEX; b++)
                                {
                                    MobileState bulletState = gameState.MobileStates[b];
                                    if (bulletState.IsActive && (bulletState.Pos.Y == segY))
                                    {
                                        for (segX = firstSeg; segX <= lastSeg; segX++)
                                        {
                                            if (bulletState.Pos.X == segX)
                                            {
                                                willDie = GameRuleConfiguration.RuleConfiguration.DoesATankDieIfMovingIntoABullet;
#if DEBUG
                                                collisionStatuses[t] |= CollisionStatus.WithBullet;
#endif
                                                if (willDie)
                                                {
#if DEBUG
                                                    collisionStatuses[b] |= CollisionStatus.MovedIntoByATank;
#endif
                                                    bulletState = bulletState.Kill();
                                                    gameState.MobileStates[b] = bulletState;
                                                }
                                                canMove = !willDie;
                                                break;
                                            }
                                        }
                                        if (willDie || !canMove)
                                        {
                                            break;
                                        }
                                    }
                                }
                            }
                        }
                        break;

                    case Direction.LEFT:
                    case Direction.RIGHT:
                        firstSeg = newCentreY - Constants.TANK_EXTENT_OFFSET;
                        lastSeg  = newCentreY + Constants.TANK_EXTENT_OFFSET;
                        for (segY = firstSeg; segY <= lastSeg; segY++)
                        {
                            if (gameState.Walls[segX, segY])
                            {
                                canMove = false;
                                break;
                            }
                        }

                        if (canMove)
                        {
                            Rectangle newRect = new Rectangle(
                                (short)(newCentreX - Constants.TANK_EXTENT_OFFSET),
                                (short)(newCentreY - Constants.TANK_EXTENT_OFFSET),
                                (short)(newCentreX + Constants.TANK_EXTENT_OFFSET),
                                (short)(newCentreY + Constants.TANK_EXTENT_OFFSET));

                            // Check if moving into another tank:
                            for (int tOther = 0; tOther < Constants.TANK_COUNT; tOther++)
                            {
                                if (tOther != t)
                                {
                                    MobileState otherTankState = gameState.MobileStates[tOther];
                                    if (otherTankState.IsActive && otherTankState.GetTankExtent().IntersectsWith(newRect))
                                    {
                                        canMove = false;
                                        break;
                                    }
                                }
                            }

                            if (canMove)
                            {
                                // Check if moving into a bullet:
                                for (int b = Constants.MIN_BULLET_INDEX; b <= Constants.MAX_BULLET_INDEX; b++)
                                {
                                    MobileState bulletState = gameState.MobileStates[b];
                                    if (bulletState.IsActive && (bulletState.Pos.X == segX))
                                    {
                                        for (segY = firstSeg; segY <= lastSeg; segY++)
                                        {
                                            if (bulletState.Pos.Y == segY)
                                            {
                                                willDie = GameRuleConfiguration.RuleConfiguration.DoesATankDieIfMovingIntoABullet;
#if DEBUG
                                                collisionStatuses[t] |= CollisionStatus.WithBullet;
#endif
                                                if (willDie)
                                                {
#if DEBUG
                                                    collisionStatuses[b] |= CollisionStatus.MovedIntoByATank;
#endif
                                                    bulletState = bulletState.Kill();
                                                    gameState.MobileStates[b] = bulletState;
                                                }
                                                canMove = !willDie;
                                                break;
                                            }
                                        }
                                        if (willDie || !canMove)
                                        {
                                            break;
                                        }
                                    }
                                }
                            }
                        }
                        break;
                    }
                }

                if (canMove || willTurn || willDie)
                {
                    if (canMove)
                    {
                        tankState = tankState.MoveTo(newCentreX, newCentreY);
                    }
                    if (willDie)
                    {
                        tankState = tankState.Kill();
                    }
                    if (willTurn)
                    {
                        tankState = tankState.ChangeDirection(movementDir);
                    }
                    gameState.MobileStates[t] = tankState;
                }
            }

            // Check for collisions with bases:
            for (int b = Constants.MIN_BULLET_INDEX; b <= Constants.MAX_BULLET_INDEX; b++)
            {
                MobileState bulletState = gameState.MobileStates[b];
                if (bulletState.IsActive)
                {
                    for (int i = 0; i < Constants.MOBILE_ELEMENT_COUNT; i++)
                    {
                        if (i == b)
                        {
                            continue;
                        }

                        MobileState otherState = gameState.MobileStates[i];
                        if (!otherState.IsActive)
                        {
                            continue;
                        }

                        if (i < Constants.TANK_COUNT)
                        {
                            // Check for collision with a tank:
                            if (otherState.GetTankExtent().ContainsPoint(bulletState.Pos))
                            {
#if DEBUG
                                collisionStatuses[i] |= CollisionStatus.WithBullet;
                                collisionStatuses[b] |= CollisionStatus.WithTank;
#endif
                                bulletState = bulletState.Kill();
                                gameState.MobileStates[b] = bulletState;
                                gameState.MobileStates[i] = otherState.Kill();
                            }
                        }
                        else
                        {
                            // Check for collision with another bullet:
                            if (otherState.Pos == bulletState.Pos)
                            {
#if DEBUG
                                collisionStatuses[b] |= CollisionStatus.WithBullet;
                                collisionStatuses[i] |= CollisionStatus.WithBullet;
#endif
                                bulletState = bulletState.Kill();
                                gameState.MobileStates[b] = bulletState;
                                gameState.MobileStates[i] = otherState.Kill();
                            }
                        }
                    }

                    // Check for collisions with bases:
                    for (int p = 0; p < Constants.PLAYERS_PER_GAME; p++)
                    {
                        Base @base = Game.Current.Players[p].Base;
                        if (bulletState.Pos == @base.Pos)
                        {
#if DEBUG
                            collisionStatuses[b] |= CollisionStatus.WithBase;
#endif
                            bulletState = bulletState.Kill();
                            gameState.MobileStates[b] = bulletState;
                            gameState.Outcome        |= (Outcome)(((byte)Outcome.Player1BaseKilled) << p);
                        }
                    }
                }
            }
        }
Пример #28
0
        protected override void CollisionAfter(Collidable <MonkeyBoard> otherCollidable, CollisionStatus direction)
        {
            if (otherCollidable is Monkey || otherCollidable is Crate)
            {
                if (direction == CollisionStatus.CollisionFromTop)
                {
                    Board.RemovePositional(this);

                    if (AIKilledSound != null)
                    {
                        AIKilledSound.Play();
                    }
                }
            }

            base.CollisionAfter(otherCollidable, direction);
        }
        /// <summary>
        /// Separate out the moving of bullets from moving of tanks.
        /// This is so that distance calculations can take place AFTER the bullets are moved.
        /// ISSUE: What about when the board shrinks after time is up?
        /// That could cause bullets to be removed during the next game tick, before they move.
        /// </summary>
        /// <param name="gameState"></param>
        public static void MoveBulletsTwice(MutableGameState gameState, IList <Point> wallsRemoved)
        {
            for (byte phase = 0; phase < 2; phase++)
            {
#if DEBUG
                CollisionStatus[] collisionStatuses = new CollisionStatus[Constants.ALL_ELEMENT_COUNT];
#endif
                Point[] wallsShot      = new Point[MAX_WALLS_SHOT];
                byte    wallsShotCount = 0;

                for (int b = Constants.MIN_BULLET_INDEX; b <= Constants.MAX_BULLET_INDEX; b++)
                {
                    MobileState bulletState = gameState.MobileStates[b];
                    if (!bulletState.IsActive)
                    {
                        continue;
                    }
                    bulletState = bulletState.Move();
                    gameState.MobileStates[b] = bulletState;
                    if (bulletState.Pos.X < 0 || bulletState.Pos.Y < 0 ||
                        bulletState.Pos.X >= Game.Current.BoardWidth ||
                        bulletState.Pos.Y >= Game.Current.BoardHeight)
                    {
#if DEBUG
                        collisionStatuses[b] |= CollisionStatus.WithOutOfBoundsArea;
#endif
                        bulletState = bulletState.Kill();
                        gameState.MobileStates[b] = bulletState;
                    }
                    else
                    {
                        if (gameState.Walls[bulletState.Pos])
                        {
                            bulletState = bulletState.Kill();
                            gameState.MobileStates[b] = bulletState;

                            /* Shoot out the walls on the segment.
                             * Assume that they are all in bounds since the tank could not have shot the bullet otherwise
                             * TODO: What to do when the board shrinks after the time limit is up,
                             * as then part of the segment could be out of bounds?
                             */
                            int first;
                            int last;
                            int x;
                            int y;

                            switch (bulletState.Dir)
                            {
                            case Direction.LEFT:
                            case Direction.RIGHT:
                                x     = bulletState.Pos.X;
                                first = bulletState.Pos.Y - 2;
                                last  = bulletState.Pos.Y + 2;
                                for (y = first; y <= last; y++)
                                {
                                    if (gameState.Walls[x, y])
                                    {
                                        wallsShot[wallsShotCount] = new Point((short)x, (short)y);
                                        wallsShotCount++;
                                    }
                                }
                                break;

                            case Direction.DOWN:
                            case Direction.UP:
                                y     = bulletState.Pos.Y;
                                first = bulletState.Pos.X - 2;
                                last  = bulletState.Pos.X + 2;
                                for (x = first; x <= last; x++)
                                {
                                    if (gameState.Walls[x, y])
                                    {
                                        wallsShot[wallsShotCount] = new Point((short)x, (short)y);
                                        wallsShotCount++;
                                    }
                                }
                                break;
                            }
                        }
                        else
                        {
                            // Check for swapping places with another bullet:
                            Direction oppositeDir = bulletState.Dir.GetOpposite();

                            // Check if colliding with a bullet that hasn't moved yet, and which is moving in the opposite direction:
                            for (int otherBulletIndex = b + 1; otherBulletIndex <= Constants.MAX_BULLET_INDEX; otherBulletIndex++)
                            {
                                MobileState otherBulletState = gameState.MobileStates[otherBulletIndex];
                                if (otherBulletState.IsActive &&
                                    (otherBulletState.Dir == oppositeDir) &&
                                    (otherBulletState.Pos == bulletState.Pos))
                                {
                                    // Collision with another bullet
#if DEBUG
                                    collisionStatuses[b] |= CollisionStatus.WithBullet;
                                    collisionStatuses[otherBulletIndex] |= CollisionStatus.WithBullet;
#endif
                                    bulletState = bulletState.Kill();
                                    gameState.MobileStates[b] = bulletState;

                                    gameState.MobileStates[otherBulletIndex] = otherBulletState.Kill();
                                    break;
                                }

                                // TODO: What happens if two bullets collide, but then a tank moves into the two bullets?
                                // Check with Entelect and ensure logic works for this case
                            }
                        }
                    }
                }

                // Check for collisions between bullets, tanks and bases:
                for (int b = Constants.MIN_BULLET_INDEX; b <= Constants.MAX_BULLET_INDEX; b++)
                {
                    MobileState bulletState = gameState.MobileStates[b];

                    // Only if bullet is active:
                    if (!bulletState.IsActive)
                    {
                        continue;
                    }

                    for (int i = 0; i < Constants.MOBILE_ELEMENT_COUNT; i++)
                    {
                        // Only if not self:
                        if (i == b)
                        {
                            continue;
                        }

                        // Only check active elements:
                        MobileState otherState = gameState.MobileStates[i];
                        if (!otherState.IsActive)
                        {
                            continue;
                        }

                        if (i < Constants.TANK_COUNT)
                        {
                            // Check for collision with a tank:
                            if (otherState.GetTankExtent().ContainsPoint(bulletState.Pos))
                            {
#if DEBUG
                                collisionStatuses[i] |= CollisionStatus.WithBullet;
                                collisionStatuses[b] |= CollisionStatus.WithTank;
#endif
                                bulletState = bulletState.Kill();
                                gameState.MobileStates[b] = bulletState;
                                gameState.MobileStates[i] = otherState.Kill();
                            }
                        }
                        else
                        {
                            // Check for collision with another bullet:
                            if (otherState.Pos == bulletState.Pos)
                            {
#if DEBUG
                                collisionStatuses[b] |= CollisionStatus.WithBullet;
                                collisionStatuses[i] |= CollisionStatus.WithBullet;
#endif
                                bulletState = bulletState.Kill();
                                gameState.MobileStates[b] = bulletState;
                                gameState.MobileStates[i] = otherState.Kill();
                            }
                        }
                    }

                    // Check for collisions with bases:
                    for (int p = 0; p < Constants.PLAYERS_PER_GAME; p++)
                    {
                        Base @base = Game.Current.Players[p].Base;
                        if (bulletState.Pos == @base.Pos)
                        {
#if DEBUG
                            collisionStatuses[b] |= CollisionStatus.WithBase;
#endif
                            bulletState = bulletState.Kill();
                            gameState.MobileStates[b] = bulletState;
                            gameState.Outcome        |= (Outcome)(((byte)Outcome.Player1BaseKilled) << p);
                        }
                    }
                }

                // Remove walls that were shot:
                for (int w = 0; w < wallsShotCount; w++)
                {
                    if (wallsRemoved == null)
                    {
                        gameState.Walls[wallsShot[w]] = false;
                    }
                    else
                    {
                        Point wall = wallsShot[w];
                        if (gameState.Walls[wall])
                        {
                            gameState.Walls[wall] = false;
                            wallsRemoved.Add(wall);
                        }
                    }
                }
            }
        }
Пример #30
0
        protected override void DoCheck(IMovable user, ref Vector2 vel, ref CollisionStatus collStatus, LayerMask mask,
                                        Bounds2D bounds, Bounds2D shrinkedBounds)
        {
            var direction = (int)Mathf.Sign(vel.x);

            var bMin = bounds.Min;
            var bMax = bounds.Max;

            var horizontalRays  = user.HorizontalRaycasts;
            var directionVector = new Vector2(vel.x * Time.deltaTime, 0);
            var positiveDir     = direction == 1;
            var originX         = positiveDir ? bMax.x : bMin.x;
            var originY         = shrinkedBounds.Min.y;
            var origin          = new Vector2(originX, originY);
            var height          = shrinkedBounds.Size.y;
            var spacing         = height / (horizontalRays - 1);

            var rayLength = directionVector.magnitude;

            LastHit = null;
            var config   = user.GetMotorConfig <GroundMotorConfig>();
            var maxAngle = config == null ? 0 : config.MaxAngle;

            for (var y = 0; y < horizontalRays; y++)
            {
                var raycast = Physics2D.Raycast(origin, directionVector, rayLength, mask);
                Debug.DrawRay(origin, directionVector, raycast ? Color.green : Color.red);
                if (raycast && !raycast.collider.isTrigger && raycast.distance < rayLength)
                {
                    LastHit          = raycast;
                    collStatus.Left  = direction == -1;
                    collStatus.Right = direction == 1;
                    var slopeAngle = Vector2.Angle(raycast.normal, Vector2.up);
                    if (config != null)
                    {
                        if (slopeAngle > maxAngle)
                        {
                            //Hit wall
                            vel.x     = raycast.distance / Time.deltaTime * direction;
                            rayLength = raycast.distance;

                            /*  if (Collisions.ClimbingSlope) {
                             *    moveAmount.y = Mathf.Tan(Collisions.SlopeAngle * Mathf.Deg2Rad) * Mathf.Abs(moveAmount.x);
                             * }*/


                            continue;
                        }
                    }
                    else
                    {
                        //Hit wall
                        if (Mathf.RoundToInt(slopeAngle) % 90 == 0)
                        {
                            vel.x = 0;
                        }
                        else
                        {
                            vel.x     = raycast.distance / Time.deltaTime * direction;
                            rayLength = raycast.distance;
                            vel.y     = Mathf.Tan(slopeAngle * Mathf.Deg2Rad) * Mathf.Abs(vel.x);
                            continue;
                        }
                    }
                }


                origin.y += spacing;
            }

            if (LastHit != null)
            {
                return;
            }

            collStatus.Left  = false;
            collStatus.Right = false;
        }