コード例 #1
0
        public override void Update()
        {
            IsDownPrevious = IsDown;
            IsDown         = false;
            foreach (var actorEntity in Scene.GetEntityListByComponent <StackableActorComponent>())
            {
                var physics  = actorEntity.GetComponent <PhysicsComponent>();
                var position = actorEntity.GetComponent <PositionComponent>();

                physics.Collider.Position         = position.Position;
                physics.Collider.PreviousPosition = position.PreviousPosition;

                if (CollisionDetector.CheckCollision(_collider, physics.Collider))
                {
                    IsDown = true;
                    break;
                }
            }

            if (Pressed)
            {
                var position = GetComponent <PositionComponent>();
                SoundController.PlaySoundAt(Resources.Sounds.ButtonPress, position.Position);
            }
            if (Released)
            {
                var position = GetComponent <PositionComponent>();
                SoundController.PlaySoundAt(Resources.Sounds.ButtonRelease, position.Position);
            }
        }
コード例 #2
0
 /// <summary>
 /// Handles the collision between a laser and a meteor.
 /// </summary>
 /// <param name="laser">The laser that may collide.</param>
 /// <param name="meteor">The meteor that may collide.</param>
 private void HandleLaserMeteorCollision(Laser laser, Meteor meteor)
 {
     if (CollisionDetector.CheckCollision(laser.BoundingRectangle, meteor.BoundingCircle))
     {
         laser.Destroy();
         meteor.Damage(laser.Damage);
         _entityManager.AddEntity(new Explosion(meteor.Position, meteor.BoundingCircle.Radius));
     }
 }
コード例 #3
0
 /// <summary>
 /// Handles the collision between the player and a meteor.
 /// </summary>
 /// <param name="player">The player that may collide.</param>
 /// <param name="meteor">The meteor that may collide.</param>
 private void HandlePlayerMeteorCollision(Player player, Meteor meteor)
 {
     if (CollisionDetector.CheckCollision(player.BoundingCircle, meteor.BoundingCircle))
     {
         player.Damage(1);
         meteor.Destroy();
         _entityManager.AddEntity(new Explosion(meteor.Position, meteor.BoundingCircle.Radius));
     }
 }
コード例 #4
0
        public static string CreateCollisionSet(string firstobjects, string secondobjects, double nmDistance)
        {
            Station station = Project.ActiveProject as Station;

            nmDistance = nmDistance / 1000;

            GraphicComponent a, b;

            station.GraphicComponents.TryGetGraphicComponent(firstobjects, out a);
            station.GraphicComponents.TryGetGraphicComponent(secondobjects, out b);
            Vector3 aPoint, bPoint;

            CollisionType colType = CollisionDetector.CheckCollision(a, b, nmDistance);

            switch (colType)
            {
            case CollisionType.Collision:
                Logger.AddMessage(new LogMessage("Part: " + a.Name + " and part: " + b.Name + " is colliding!"));
                break;

            case CollisionType.NearMiss:
                Logger.AddMessage(new LogMessage("There is a near miss between part: " + a.Name + " and part: " + b.Name + "."));
                Logger.AddMessage(new LogMessage("The distance between them are: "
                                                 + CollisionDetector.MinimumDistance(a, b, out aPoint, out bPoint)));
                Logger.AddMessage(new LogMessage("The closest points are: "));
                Logger.AddMessage(new LogMessage("For part: " + a.Name + " x: " + aPoint.x
                                                 + " y: " + aPoint.y + " z: " + aPoint.z));
                Logger.AddMessage(new LogMessage("For part: " + b.Name + " x: " + bPoint.x
                                                 + " y: " + bPoint.y + " z: " + bPoint.z));
                break;

            case CollisionType.None:
                Logger.AddMessage(new LogMessage("No collisions!"));
                break;
            }

            CollisionDetector.Collision += new CollisionEventHandler(MyCollisionEventHandler);
            CollisionSet cs = new CollisionSet();

            cs.Name             = "CSet";
            cs.NearMissDistance = nmDistance;

            cs.Active = true;
            station.CollisionSets.Add(cs);



            cs.FirstGroup.Add(a);
            cs.SecondGroup.Add(b);

            CollisionDetector.CheckCollisions(station);
            CollisionDetector.CheckCollisions(cs);
            return("Collisionset Created. Checking collisions.");
        }
コード例 #5
0
        public override void Update(List <Component> components)
        {
            foreach (FrogEnemyComponent frog in components)
            {
                frog.LogicStateMachine.Update();
                frog.AttackDelay.Update();

                var actor = frog.Owner.GetComponent <StackableActorComponent>();

                // Damaging the player.
                if (
                    !actor.Crouching &&
                    actor.LogicStateMachine.CurrentState == ActorStates.InAir &&
                    actor.StackedNext == null
                    )
                {
                    var players = SceneMgr.CurrentScene.GetEntityListByComponent <PlayerComponent>();
                    var physics = frog.Owner.GetComponent <PhysicsComponent>();

                    foreach (var playerEntity in players)
                    {
                        var player      = playerEntity.GetComponent <PlayerComponent>();
                        var playerActor = playerEntity.GetComponent <StackableActorComponent>();

                        if (playerActor.Crouching && actor.LogicStateMachine.CurrentState != ActorStates.Stacked)
                        {
                            continue;
                        }

                        var position       = frog.Owner.GetComponent <PositionComponent>();
                        var playerPosition = playerEntity.GetComponent <PositionComponent>();
                        var playerPhysics  = playerEntity.GetComponent <PhysicsComponent>();


                        // Setting up colliders.
                        physics.Collider.Position               = position.Position;
                        physics.Collider.PreviousPosition       = position.PreviousPosition;
                        playerPhysics.Collider.Position         = playerPosition.Position;
                        playerPhysics.Collider.PreviousPosition = playerPosition.PreviousPosition;
                        // Seting up colliders.

                        if (CollisionDetector.CheckCollision(physics.Collider, playerPhysics.Collider))
                        {
                            StackableActorSystem.Damage(playerEntity.GetComponent <StackableActorComponent>());
                        }
                    }
                }
                // Damaging the player.
            }
        }
コード例 #6
0
        private bool tireCollisionWithCar(Vector tirePos, PCar car, out Vector normal, double multR = 1)
        {
            CollisionCircle collisionTire = new CollisionCircle(tirePos, game.TireRadius * multR);
            CollisionRect   collisionCar  = new CollisionRect(car);

            CollisionInfo collision = new CollisionInfo(collisionTire, collisionCar);

            if (CollisionDetector.CheckCollision(collision))
            {
                normal = collision.NormalObj1;
                return(true);
            }

            normal = null;
            return(false);
        }
コード例 #7
0
        /// <summary>
        /// Checks collision of a given collider with solid objects.
        /// </summary>
        public static Entity CheckCollision(Entity checker, ICollider collider)
        {
            // Note that this won't work well, if a lot of solid objects will be constantly created\deleted.
            // In case of problems, make an overload searching for a new solid list every call.
            foreach (var solid in _solidEntities)
            {
                if (solid != checker)
                {
                    var otherCollider = solid.GetComponent <SolidComponent>().Collider;
                    var position      = solid.GetComponent <PositionComponent>();
                    otherCollider.Position         = position.Position;
                    otherCollider.PreviousPosition = position.PreviousPosition;

                    if (CollisionDetector.CheckCollision(collider, otherCollider))
                    {
                        return(solid);
                    }
                }
            }
            return(null);
        }
コード例 #8
0
        void OnGround(StateMachine <ActorStates> stateMachine, Entity owner)
        {
            var actor    = owner.GetComponent <StackableActorComponent>();
            var physics  = owner.GetComponent <PhysicsComponent>();
            var position = owner.GetComponent <PositionComponent>();


            // Jumping.
            if (actor.CanJump && actor.JumpActionPress && !actor.Crouching && !physics.InAir)
            {
                Jump(physics, actor);
                return;
            }
            // Jumping.

            // Falling off.
            if (physics.InAir)
            {
                if (!actor.Jumping)
                {
                    actor.JumpBufferAlarm.Set(actor.JumpBufferTime);
                    if (actor.Crouching)
                    {
                        // NOTE: This may pose problems if there is not enough room to uncrouch.
                        Uncrouch(position, physics, actor);
                    }
                }

                stateMachine.ChangeState(ActorStates.InAir);
                return;
            }
            // Falling off.



            if (!actor.Crouching && actor.CrouchAction)
            {
                Crouch(position, physics, actor);
            }
            if (actor.Crouching && !actor.CrouchAction)
            {
                // Setting up new collider.
                var collider = (ICollider)physics.Collider.Clone();
                collider.Position         = position.Position - Vector2.UnitY * (actor.Height - collider.Size.Y) / 2;
                collider.PreviousPosition = collider.Position;
                collider.Size             = new Vector2(collider.Size.X, actor.Height);
                // Setting up new collider.

                // If a solid is above actor - keep crouching.
                if (PhysicsSystem.CheckCollision(actor.Owner, collider) == null)
                {
                    Uncrouch(position, physics, actor);
                    var stackables = SceneMgr.CurrentScene.GetEntityListByComponent <StackableActorComponent>();
                    physics.Collider.Position         = position.Position;
                    physics.Collider.PreviousPosition = position.PreviousPosition;

                    foreach (var other in stackables)
                    {
                        if (other != owner && other.Enabled)
                        {
                            var otherPosition = other.GetComponent <PositionComponent>();
                            var otherPhysics  = other.GetComponent <PhysicsComponent>();
                            var otherActor    = other.GetComponent <StackableActorComponent>();

                            otherPhysics.Collider.Position         = otherPosition.Position;
                            otherPhysics.Collider.PreviousPosition = otherPosition.PreviousPosition;

                            if (
                                CollisionDetector.CheckCollision(physics.Collider, otherPhysics.Collider) &&
                                otherActor.LogicStateMachine.CurrentState == ActorStates.OnGround
                                )
                            {
                                StackEntity(actor, otherActor);
                            }
                        }
                    }
                }
            }


            if (actor.Crouching)
            {
                actor.MaxMovementSpeed = actor.CrouchMovementSpeed;
                actor.Acceleration     = actor.CrouchAcceleration;
                actor.Deceleration     = actor.CrouchDeceleration;
            }
            else
            {
                actor.MaxMovementSpeed = actor.WalkMovementSpeed;
                actor.Acceleration     = actor.GroundAcceleration;
                actor.Deceleration     = actor.GroundDeceleration;
            }

            physics.Gravity = actor.FallGravity;

            UpdateSpeed(actor, physics);
        }
コード例 #9
0
        public override void Update(List <Component> components)
        {
            foreach (CatEnemyComponent gato in components)
            {
                var physics = gato.Owner.GetComponent <PhysicsComponent>();
                var actor   = gato.Owner.GetComponent <StackableActorComponent>();

                actor.LeftAction  = (gato.Direction == -1);
                actor.RightAction = (gato.Direction == 1);

                if (actor.LogicStateMachine.CurrentState == ActorStates.OnGround)
                {
                    var position = gato.Owner.GetComponent <PositionComponent>();

                    // Checking if there is a wall next to us.
                    physics.Collider.Position = position.Position
                                                + Vector2.UnitX * gato.Direction * (physics.Collider.Size.X / 2 + 1);

                    if (physics.CollisionH == gato.Direction)
                    {
                        gato.Direction   *= -1;
                        actor.Orientation = gato.Direction;
                    }
                    // Checking if there is a wall next to us.
                    else
                    {
                        // Checking if there is a pit below us.
                        var collider = new RectangleCollider();
                        collider.Size     = Vector2.One;
                        collider.Position = position.Position
                                            + (physics.Collider.Size / 2 + Vector2.One) * new Vector2(gato.Direction, 1);

                        if (PhysicsSystem.CheckCollision(gato.Owner, collider) == null)
                        {
                            gato.Direction   *= -1;
                            actor.Orientation = gato.Direction;
                        }
                        // Checking if there is a pit below us.
                    }
                }


                // Damaging the player.
                if (
                    (
                        actor.StackOwner == null ||
                        (
                            actor.StackOwner != null &&
                            !actor.StackOwner.HasComponent <PlayerComponent>()
                        )
                    ) &&
                    actor.LogicStateMachine.CurrentState != ActorStates.Dead
                    )
                {
                    var players = SceneMgr.CurrentScene.GetEntityListByComponent <PlayerComponent>();
                    foreach (var playerEntity in players)
                    {
                        var player      = playerEntity.GetComponent <PlayerComponent>();
                        var playerActor = playerEntity.GetComponent <StackableActorComponent>();

                        if (playerActor.Crouching && actor.LogicStateMachine.CurrentState != ActorStates.Stacked)
                        {
                            continue;
                        }

                        var position       = gato.Owner.GetComponent <PositionComponent>();
                        var playerPosition = playerEntity.GetComponent <PositionComponent>();
                        var playerPhysics  = playerEntity.GetComponent <PhysicsComponent>();


                        // Setting up colliders.
                        physics.Collider.Position               = position.Position;
                        physics.Collider.PreviousPosition       = position.PreviousPosition;
                        playerPhysics.Collider.Position         = playerPosition.Position;
                        playerPhysics.Collider.PreviousPosition = playerPosition.PreviousPosition;
                        // Seting up colliders.

                        if (CollisionDetector.CheckCollision(physics.Collider, playerPhysics.Collider))
                        {
                            StackableActorSystem.Damage(playerEntity.GetComponent <StackableActorComponent>());
                        }
                    }
                }
                // Damaging the player.
            }
        }
コード例 #10
0
ファイル: CannonBall.cs プロジェクト: Martenfur/Monofoxe.Demo
        public override void Update()
        {
            var position = GetComponent <PositionComponent>();

            if (!_dead)
            {
                position.Position += _direction * TimeKeeper.GlobalTime(_speed);

                _collider.Position         = position.Position;
                _collider.PreviousPosition = position.PreviousPosition;

                if (!CollisionDetector.CheckCollision(_collider, _myCannon.GetComponent <SolidComponent>().Collider))
                {
                    foreach (SolidComponent solid in Scene.GetComponentList <SolidComponent>())
                    {
                        var solidPosition = solid.Owner.GetComponent <PositionComponent>();
                        solid.Collider.Position         = solidPosition.Position;
                        solid.Collider.PreviousPosition = solidPosition.PreviousPosition;
                        if (CollisionDetector.CheckCollision(_collider, solid.Collider))
                        {
                            Die();
                        }
                    }
                }

                var actors = SceneMgr.CurrentScene.GetEntityListByComponent <StackableActorComponent>();
                foreach (var actorEntity in actors)
                {
                    var playerActor = actorEntity.GetComponent <StackableActorComponent>();

                    var playerPosition = actorEntity.GetComponent <PositionComponent>();
                    var playerPhysics  = actorEntity.GetComponent <PhysicsComponent>();

                    // Setting up colliders.
                    playerPhysics.Collider.Position         = playerPosition.Position;
                    playerPhysics.Collider.PreviousPosition = playerPosition.PreviousPosition;
                    // Seting up colliders.

                    if (CollisionDetector.CheckCollision(_collider, playerPhysics.Collider))
                    {
                        StackableActorSystem.Damage(actorEntity.GetComponent <StackableActorComponent>());
                        Die();
                        break;
                    }
                }
            }
            else
            {
                _deadSpeed.Y      += TimeKeeper.GlobalTime(_deadGravity);
                position.Position += TimeKeeper.GlobalTime(_deadSpeed);
            }

            if (_dead)
            {
                var inBounds = false;
                foreach (var camera in SceneMgr.CurrentScene.GetEntityList <GameCamera>())
                {
                    if (camera.InBounds(position.Position))
                    {
                        inBounds = true;
                        break;
                    }
                }

                if (!inBounds)
                {
                    DestroyEntity();
                }
            }

            if (_lifetimeAlarm.Update())
            {
                DestroyEntity();
            }
        }
コード例 #11
0
        private MoveDirection FindSafestMove(IEnumerable <ShotViewData> allShots, ChickenUnitState unitState)
        {
            var safetyCircle   = new CirclePrimitive(unitState.Position, _dangerousRadius);
            var dangerousShots = new List <ShotViewData>(unitState.View.Shots.Count);

            //// ReSharper disable once LoopCanBeConvertedToQuery
            foreach (var shot in allShots)
            {
                if (unitState.Position.GetDistance(shot.Position) > _tooCloseShot)
                {
                    continue;
                }

                var shotDirection    = shot.Angle.ToUnitVector();
                var shotToUnitVector = unitState.Position - shot.Position;
                var angle            = shotDirection.GetAngle(shotToUnitVector);
                if (angle.DegreeValue.Abs() >= MathHelper.QuarterRevolutionDegrees)
                {
                    continue;
                }

                var shotLine = new LinePrimitive(
                    shot.Position,
                    shot.Position + shot.Angle.ToUnitVector() * _boardDiagonalSize);
                if (CollisionDetector.CheckCollision(shotLine, safetyCircle))
                {
                    dangerousShots.Add(shot);
                }
            }

            if (dangerousShots.Count <= 0)
            {
                return(null);
            }

            var safeMoves = GameHelper.BasicMoveDirections.ToDictionary(item => item, item => 0);

            foreach (var dangerousShot in dangerousShots)
            {
                var shotVector = dangerousShot.Angle.ToUnitVector();

                var maxDistanceMove = MoveDirection.None;
                var maxDistanceSqr  = float.MinValue;
                foreach (var moveDirection in GameHelper.BasicMoveDirections)
                {
                    var potentialPosition = GameHelper.GetNewPosition(
                        unitState.Position,
                        unitState.BeakAngle,
                        moveDirection,
                        GameConstants.ChickenUnit.DefaultRectilinearSpeed);
                    var shotToUnitVector = potentialPosition - dangerousShot.Position;
                    var shotToUnitVectorLengthSquared = shotToUnitVector.GetLengthSquared();
                    var angleCosine = shotVector.GetAngleCosine(shotToUnitVector);
                    var distanceSqr = shotToUnitVectorLengthSquared
                                      - shotToUnitVectorLengthSquared * angleCosine.Sqr();
                    if (distanceSqr > maxDistanceSqr)
                    {
                        maxDistanceSqr  = distanceSqr;
                        maxDistanceMove = moveDirection;
                    }
                }

                safeMoves[maxDistanceMove]++;
            }

            var actuallySafeMovePair = safeMoves
                                       .Where(pair => pair.Value > 0)
                                       .OrderByDescending(pair => pair.Value)
                                       .FirstOrDefault();

            return(actuallySafeMovePair.Value > 0 ? actuallySafeMovePair.Key : null);
        }
コード例 #12
0
        private bool ProcessChickenUnitMoves(IList <ChickenUnit> aliveChickens)
        {
            //// TODO: [vmcl] Use bisection to get conflicting units closer to each other
            //// TODO: [vmcl] Optimize number of collision checks!
            //// TODO: [vmcl] Divide move: eg. unit couldn't move but could turn beak or vice versa

            _moveInfoStates.Clear();
            for (var unitIndex = 0; unitIndex < aliveChickens.Count; unitIndex++)
            {
                if (IsStopping())
                {
                    return(false);
                }

                var unit = aliveChickens[unitIndex];
                _moveInfoStates[unit] = MoveInfoStates.Handled;

                var moveInfo = _moveInfos.GetValueOrDefault(unit);
                if (moveInfo == null)
                {
                    continue;
                }

                DebugHelper.WriteLine(
                    "{0} is processing move {{{1}}} of chicken {{{2}}}.",
                    GetType().Name,
                    moveInfo,
                    unit);

                var movementAndNewPosition = GameHelper.GetMovementAndNewPosition(
                    unit.Position,
                    unit.BeakAngle,
                    moveInfo.MoveDirection,
                    GameConstants.ChickenUnit.DefaultRectilinearSpeed);

                var beakMovementAndNewAngle = GameHelper.GetBeakMovementAndNewAngle(unit.BeakAngle, moveInfo.BeakTurn);

                var newPositionElement = new ChickenElement(
                    movementAndNewPosition.Position,
                    beakMovementAndNewAngle.Position);
                if (HasOutOfBoardCollision(newPositionElement))
                {
                    _moveInfoStates[unit] = MoveInfoStates.RejectedBoardCollision;
                    DebugHelper.WriteLine(
                        "Blocked collision of chicken {{{0}}} with game board border.",
                        unit);
                    continue;
                }

                ChickenUnit conflictingChicken = null;

                // ReSharper disable once LoopCanBeConvertedToQuery
                // ReSharper disable once ForCanBeConvertedToForeach
                for (var conflictingIndex = 0; conflictingIndex < aliveChickens.Count; conflictingIndex++)
                {
                    var aliveChicken = aliveChickens[conflictingIndex];
                    if (aliveChicken == unit)
                    {
                        continue;
                    }

                    if (CollisionDetector.CheckCollision(newPositionElement, aliveChicken.GetElement()))
                    {
                        conflictingChicken = aliveChicken;
                        break;
                    }
                }

                if (conflictingChicken != null)
                {
                    _moveInfoStates[unit] = MoveInfoStates.RejectedOtherUnitCollision;
                    DebugHelper.WriteLine(
                        "Blocked collision of chicken {{{0}}} with {{{1}}}.",
                        unit,
                        conflictingChicken);
                    continue;
                }

                unit.SetMovement(movementAndNewPosition.Movement, beakMovementAndNewAngle.Movement);

                DebugHelper.WriteLine("Chicken {{{0}}} has moved.", unit);
            }

            return(true);
        }
コード例 #13
0
        private void ProcessEngineStep()
        {
            var aliveChickens = this.AliveChickens
                                .Where(item => !item.IsDead && item.LogicExecutor.Error == null)
                                .ToList();

            _moveInfos.Clear();
            _previousMoves.Clear();
            for (var logicIndex = 0; logicIndex < _logicExecutors.Count; logicIndex++)
            {
                var logic = _logicExecutors[logicIndex];

                lock (logic.UnitsMovesLock)
                {
                    foreach (var pair in logic.UnitsMoves)
                    {
                        _moveInfos.Add(pair.Key, pair.Value);
                        _previousMoves.Add(pair.Key, pair.Value);
                    }
                }
            }

            if (!ProcessChickenUnitMoves(aliveChickens))
            {
                return;
            }

            // Processing new shot units
            var shootingMoves = _moveInfos.Where(item => !item.Key.IsDead && item.Value.FireMode != FireMode.None);

            ProcessNewShots(shootingMoves);

            #region Processing Shot Collisions

            foreach (var shotUnit in _shotUnitsDirect)
            {
                var movement = GameHelper.GetMovement(
                    shotUnit.Angle,
                    MoveDirection.MoveForward,
                    GameConstants.ShotUnit.DefaultRectilinearSpeed);

                shotUnit.SetMovement(movement);
                DebugHelper.WriteLine("Shot {{{0}}} has moved.", shotUnit);

                var hasOutOfBoardCollision = HasOutOfBoardCollision(shotUnit.GetElement());
                if (hasOutOfBoardCollision)
                {
                    shotUnit.Exploded = true;
                    DebugHelper.WriteLine("Shot {{{0}}} has exploded outside of game board.", shotUnit);
                }
            }

            var injuredChickens = new List <ChickenUnit>(aliveChickens.Count);
            for (var index = 0; index < _shotUnitsDirect.Count; index++)
            {
                var shotUnit = _shotUnitsDirect[index];

                for (var otherIndex = index + 1; otherIndex < _shotUnitsDirect.Count; otherIndex++)
                {
                    var otherShotUnit = _shotUnitsDirect[otherIndex];

                    var isCollision = CollisionDetector.CheckCollision(
                        shotUnit.GetElement(),
                        otherShotUnit.GetElement());
                    if (!isCollision)
                    {
                        continue;
                    }

                    shotUnit.Exploded      = true;
                    otherShotUnit.Exploded = true;

                    DebugHelper.WriteLine(
                        "Mutual annihilation of shots {{{0}}} and {{{1}}}.",
                        shotUnit,
                        otherShotUnit);
                }

                var shotElement = shotUnit.GetElement();

                injuredChickens.Clear();

                // ReSharper disable once LoopCanBeConvertedToQuery
                // ReSharper disable once ForCanBeConvertedToForeach
                for (var chickenIndex = 0; chickenIndex < aliveChickens.Count; chickenIndex++)
                {
                    var aliveChicken = aliveChickens[chickenIndex];
                    if (!aliveChicken.IsDead &&
                        CollisionDetector.CheckCollision(shotElement, aliveChicken.GetElement()))
                    {
                        injuredChickens.Add(aliveChicken);
                    }
                }

                foreach (var injuredChicken in injuredChickens)
                {
                    shotUnit.Exploded = true; //// TODO [vmcl] Move out of loop

                    injuredChicken.IsDead   = true;
                    injuredChicken.KilledBy = shotUnit.Owner;
                    var suicide = shotUnit.Owner == injuredChicken;
                    if (!suicide)
                    {
                        shotUnit.Owner.KillCount++;
                    }

                    DebugHelper.WriteLine(
                        "Shot {{{0}}} has exploded and killed {{{1}}}{2}.",
                        shotUnit,
                        injuredChicken,
                        suicide ? " [suicide]" : string.Empty);
                }
            }

            #endregion

            UpdateLastGamePresentation();

            _aliveChickensDirect.RemoveAll(item => item.IsDead);
            _aliveChickensDirect.DoForEach(item => item.ApplyMovement());

            _shotUnitsDirect.RemoveAll(item => item.Exploded);
            _shotUnitsDirect.DoForEach(item => item.ApplyMovement());

            var aliveTeams = _aliveChickensDirect.Select(item => item.Team).Distinct().ToList();
            if (aliveTeams.Count > 1)
            {
                return;
            }

            _finalizingStage = true;
            if (_shotUnitsDirect.Any())
            {
                return;
            }

            var winningTeam = aliveTeams.SingleOrDefault();

            ChickenUnitLogic winningLogic;
            switch (winningTeam)
            {
            case GameTeam.Light:
                winningLogic = _lightTeamLogicExecutor.Logic;
                break;

            case GameTeam.Dark:
                winningLogic = _darkTeamLogicExecutor.Logic;
                break;

            default:
                winningLogic = null;
                break;
            }

            RaiseGameEnded(winningTeam, winningLogic);
        }