Beispiel #1
0
        public void Colise()
        {
            var movements = new MovementSegment[]
            {
                new MovementSegment {
                    startPoint = new Vector2(-12.5f, 3f), endPoint = new Vector2(-10.7f, 1.5f)
                },
                new MovementSegment {
                    startPoint = new Vector2(-10.41489f, 1.61148f), endPoint = new Vector2(-9.71394f, 3.34835f)
                },
                new MovementSegment {
                    startPoint = new Vector2(-7.5f, 3.3f), endPoint = new Vector2(-12.43711f, 3.59647f)
                },
                new MovementSegment {
                    startPoint = new Vector2(-11.17787f, 4.60138f), endPoint = new Vector2(-11.12205f, 3.31733f)
                },
                new MovementSegment {
                    startPoint = new Vector2(-10.3f, 3.9f), endPoint = new Vector2(-11.8f, 4.1f)
                },
            };

            var normals = new Vector2[]
            {
                new Vector2(-1.0f, 0.0f),
                new Vector2(0.0f, -1.0f),
                new Vector2(1.0f, 0.0f),
                new Vector2(0.0f, 1.0f),
                new Vector2(0.0f, 1.0f)
            };

            var colisePoints = new Vector2[]
            {
                new Vector2(-12.0f, 2.6f),
                new Vector2(-10.3f, 2.0f),
                new Vector2(-10.0f, 3.5f),
                new Vector2(-11.2f, 4.0f),
                new Vector2(-11.3f, 4.0f)
            };

            for (var i = 0; i < movements.Length; i++)
            {
                var result = _coliseController.CheckColise(movements[i], 0.0, _block);
                Assert.IsTrue(result.isColise, $"Fail movement vector: start point: {movements[i].startPoint} end point: {movements[i].endPoint}");
                Assert.AreEqual(normals[i], result.normal, $"Uncorrect normal: start point: {movements[i].startPoint} end point: {movements[i].endPoint}");
                Assert.AreEqual(colisePoints[i].x, result.colisePoint.x, 0.3, $"Uncorrect x coord colise point: start point: {movements[i].startPoint} end point: {movements[i].endPoint}");
                Assert.AreEqual(colisePoints[i].y, result.colisePoint.y, 0.3, $"Uncorrect y coord colise point: start point: {movements[i].startPoint} end point: {movements[i].endPoint}");
            }
        }
Beispiel #2
0
        public void DontColise()
        {
            var movements = new MovementSegment[]
            {
                new MovementSegment {
                    startPoint = new Vector2(-10.06561f, 4.32486f), endPoint = new Vector2(-9.1461f, 3.67668f)
                },
                new MovementSegment {
                    startPoint = new Vector2(-11.2275f, 1.79137f), endPoint = new Vector2(-11.31434f, 0.89192f)
                },
                new MovementSegment {
                    startPoint = new Vector2(-12.74106f, 3.38557f), endPoint = new Vector2(-12.4185f, 1.2579f)
                },
                new MovementSegment {
                    startPoint = new Vector2(-12.54256f, 4.52694f), endPoint = new Vector2(-8.78347f, 4.55175f)
                },
            };

            foreach (var movement in movements)
            {
                var result = _coliseController.CheckColise(movement, 0.0, _block);
                Assert.IsFalse(result.isColise, $"Fail movement vector: start point: {movement.startPoint} end point: {movement.endPoint}");
            }
        }
Beispiel #3
0
        /// <summary>
        /// <see cref="IColiseController.CheckColise(MovementSegment, Block)"/>
        /// </summary>
        public ColiseData CheckColise(MovementSegment segment, double radius, Block block, bool isInBlock = false)
        {
            var startPoint = segment.startPoint;
            var endPoint   = segment.endPoint;

            double startX = segment.startPoint.x;
            double startY = segment.startPoint.y;

            double endX = segment.startPoint.x;
            double endY = segment.startPoint.y;

            double minX = Mathf.Min(startPoint.x, endPoint.x);
            double minY = Mathf.Min(startPoint.y, endPoint.y);

            double maxX = Mathf.Max(startPoint.x, endPoint.x);
            double maxY = Mathf.Max(startPoint.y, endPoint.y);

            double segmentDeltaY = startPoint.y - endPoint.y;
            double segmentDeltaX = startPoint.x - endPoint.x;
            double segmentK      = startPoint.x * endPoint.y - endPoint.x * startPoint.y;

            var l = isInBlock ? -1.0f : 1.0f;

            var sides = new Side[]
            {
                new Side {
                    K = block.TopK, deltaX = block.DeltaTop.x, deltaY = block.DeltaTop.y, normal = new Vector2(0.0f, l)
                },
                new Side {
                    K = block.RightK, deltaX = block.DeltaRight.x, deltaY = block.DeltaRight.y, normal = new Vector2(l, 0.0f)
                },
                new Side {
                    K = block.BottomK, deltaX = block.DeltaBottom.x, deltaY = block.DeltaBottom.y, normal = new Vector2(0.0f, -l)
                },
                new Side {
                    K = block.LeftK, deltaX = block.DeltaLeft.x, deltaY = block.DeltaLeft.y, normal = new Vector2(-l, 0.0f)
                }
            };

            var result          = new ColiseData();
            var currSqrDistance = double.MaxValue;

            foreach (var side in sides)
            {
                var d = side.deltaX * segmentDeltaY - side.deltaY * segmentDeltaX;

                /// Отрезок параллелен прямой.
                if (d == 0)
                {
                    continue;
                }

                var    pointX = (side.K * segmentDeltaX - side.deltaX * segmentK) / d;
                var    pointY = (side.K * segmentDeltaY - side.deltaY * segmentK) / d;
                double e      = radius;
                if (pointX >= minX - e &&
                    pointX <= maxX + e &&
                    pointY >= minY - e &&
                    pointY <= maxY + e &&
                    block.IsOnBounds(pointX, pointY, e))
                {
                    var v = (pointX - startX) * (pointX - startX) + (pointY - startY) * (pointY - startY);
                    if (v < currSqrDistance)
                    {
                        currSqrDistance    = v;
                        result.sqrDist     = v;
                        result.colisePoint = new Vector2((float)pointX, (float)pointY) + side.normal * (float)e * 1.05f;
                        result.normal      = side.normal;
                    }
                }
            }

            result.isColise = currSqrDistance != double.MaxValue;

            return(result);
        }
Beispiel #4
0
        /// <summary>
        /// Обработка перемещения шаров.
        /// </summary>
        private void HandleBalls()
        {
            var balls = _gameFieldView.Balls;

            for (var ballId = 0; ballId < balls.Count; ballId++)
            {
                var currentPos      = balls[ballId].GetCenter();
                var movementSegment = new MovementSegment()
                {
                    startPoint = currentPos,
                    endPoint   = currentPos + balls[ballId].LastMoveDir * _gameParams.ballSpeed
                };

                var coliseResult = _coliseController.CheckColise(movementSegment, balls[ballId].GetRadius(), _gameFieldView.FieldBlock, true);

                if (coliseResult.isColise)
                {
                    if (coliseResult.normal.y == 1)
                    {
                        balls[ballId].Remove();
                        balls.RemoveAt(ballId);
                        ballId--;
                        if (balls.Count == 0)
                        {
                            HandleFailEnd();
                        }
                    }
                    else
                    {
                        var lastDir = _coliseController.CalculateRicochet(balls[ballId].LastMoveDir,
                                                                          coliseResult.normal);
                        balls[ballId].Move(coliseResult.colisePoint - balls[ballId].GetCenter());
                        balls[ballId].LastMoveDir = lastDir;
                    }
                    continue;
                }

                var distance      = double.MaxValue;
                var blocks        = _gameFieldView.CurrentLvl.Blocks;
                var blockIdColise = 0;
                for (var blockId = _curFirstBlock; blockId < blocks.Length; blockId++)
                {
                    var coliseInfo = _coliseController.CheckColise(movementSegment, balls[ballId].GetRadius(), blocks[blockId].GetBlockInfo());
                    if (coliseInfo.isColise)
                    {
                        var newDistance = coliseInfo.sqrDist;
                        if (newDistance < distance)
                        {
                            coliseResult  = coliseInfo;
                            blockIdColise = blockId;
                            distance      = newDistance;
                        }
                    }
                }

                if (coliseResult.isColise)
                {
                    var lastDir = _coliseController.CalculateRicochet(balls[ballId].LastMoveDir,
                                                                      coliseResult.normal);
                    balls[ballId].Move(coliseResult.colisePoint - balls[ballId].GetCenter());
                    balls[ballId].LastMoveDir = lastDir;

                    blocks[blockIdColise].Strike();
                    if (!blocks[blockIdColise].IsLive())
                    {
                        if (blocks[blockIdColise].IsHasBonus)
                        {
                            _gameFieldView.AddBonus(blocks[blockIdColise].Bonus, blocks[blockIdColise].GetBlockInfo().GetCenter());
                        }
                        var t = _gameFieldView.CurrentLvl.Blocks[blockIdColise];
                        _gameFieldView.CurrentLvl.Blocks[blockIdColise]  = blocks[_curFirstBlock];
                        _gameFieldView.CurrentLvl.Blocks[_curFirstBlock] = t;
                        _curFirstBlock++;
                        if (_curFirstBlock == blocks.Length)
                        {
                            HandleSuccessEnd();
                        }
                    }
                    continue;
                }

                var slideBlock = _userSlideView.GetBlock();
                coliseResult = _coliseController.CheckColise(movementSegment, balls[ballId].GetRadius(), slideBlock);
                if (coliseResult.isColise)
                {
                    if (coliseResult.normal.y == 1)
                    {
                        var ricochet = _coliseController.CalculateRicochet(balls[ballId].LastMoveDir, coliseResult.normal);
                        var center   = slideBlock.GetCenter();
                        ricochet += new Vector2(center.x - coliseResult.colisePoint.x, 0);
                        balls[ballId].Move(coliseResult.colisePoint - center);
                        balls[ballId].LastMoveDir = ricochet;

                        continue;
                    }
                }

                balls[ballId].Move(balls[ballId].LastMoveDir * (_gameParams.ballSpeed + _speedBallBonus));
            }
        }