Example #1
0
    private Vector2 GetForceOnLeftOrRight(BallBase ball, CollisionSide colSide)
    {
        Vector2 forceVector = StrikerCollisionForceManager.GetCollisionEndVelocity(CollisionType, colSide, isMovingOrMovedUp, isForceModeOn);
        float   endSpeed    = PhysicsConstants.BallSpeedAfterStrikerIdleHit;

        return((ball.LastFrameVelocity.normalized + forceVector).normalized * endSpeed);
    }
Example #2
0
    private void Update()
    {
        bool isKeyDown = GamePad.GetButtonDown(GamePad.Button.Y, GamePad.Index.Any) || Input.GetKeyDown(KeyCode.Space);

        if (isKeyDown)
        {
            BallBase ball = BallPool.TryTakeBallToPlay();
            if (ball != null)
            {
                ball.enabled = false;
                Vector2 pos = PhysicsTools.GetRandomPositionBetweenVectors(BallSpawnPositionMin.position, BallSpawnPositionMax.position);
                ball.SetGravityState(false);
                ball.ResetTrailEmitter();
                ball.transform.position = pos;
                ball.Rigidbody.velocity = Vector2.zero;
                ball.Rigidbody.AddForce(Vector2.down * PhysicsConstants.BallSpeedAtStart, ForceMode2D.Impulse);
                BallsInPlay.Add(ball);
                ball.ResetLastFrameVelocityAndPosition();

                ball.enabled = true;
            }
            CallOnGameStateChanged();
            GameStarted = true;
            EnemyController.Instance.TryInitEnemySpawning();
        }

        if (GameStarted)
        {
            GameTime += Time.deltaTime;
        }
    }
Example #3
0
    private Vector2 GetForceOnBottomSide(BallBase ball)
    {
        Vector2 forceVector = StrikerCollisionForceManager.GetCollisionEndVelocity(CollisionType, CollisionSide.Top, isMovingOrMovedUp, isForceModeOn);
        float   endSpeed    = isForceModeOn ? PhysicsConstants.BallSpeedAfterStrikerForceHit : PhysicsConstants.BallSpeedAfterStrikerIdleHit;

        return((ball.LastFrameVelocity.normalized + forceVector).normalized * endSpeed);
    }
Example #4
0
 public void RemoveBallFromPlay(BallBase ball)
 {
     if (BallsInPlay.Contains(ball))
     {
         BallsInPlay.Remove(ball);
     }
     Destroy(ball.gameObject, 1f);
 }
Example #5
0
    private BallBase SpawnBallOnRandomPoint()
    {
        Vector3  pos  = new Vector3(BallTestSpawnPosition.position.x, BallTestSpawnPosition.position.y, BallTestSpawnPosition.position.z + UnityEngine.Random.Range(0, 2f));
        BallBase ball = Instantiate(BallToSpawn, pos, Quaternion.identity, null);

        ball.gameObject.name = "Ball " + ballCounter;
        ballCounter++;
        return(ball);
    }
Example #6
0
 public BallBase TryTakeBallToPlay()
 {
     if (ballsInPool.Count > 0)
     {
         int      randomIndex = UnityEngine.Random.Range(0, ballsInPool.Count);
         BallBase randomBall  = ballsInPool[randomIndex];
         ballsInPool.RemoveAt(randomIndex);
         return(randomBall);
     }
     return(null);
 }
Example #7
0
    private void AddBallToPool()
    {
        Vector3  randomPos = PhysicsTools.GetRandomPositionBetweenVectors(BallSpawnPlaceMin.position, BallSpawnPlaceMax.position);
        BallBase ball      = Instantiate(BallPrefab, randomPos, Quaternion.identity);

        ball.SetGravityState(true);
        ballsInPool.Add(ball);
        ball.gameObject.name = "Ball " + ballCounter;
        ballCounter++;
        GameController.Instance.CallOnGameStateChanged();
    }
Example #8
0
    public BallBase Copy()
    {
        BallBase c = new BallBase();

        c.Initialize(this.BType);
        c.ObjNo          = this.ObjNo;
        c.DisplayName    = this.DisplayName;
        c.ThrowDexterity = this.ThrowDexterity;
        if (CommonFunction.IsNull(this.Options) == false)
        {
            c.Options = this.Options;
        }

        return(c);
    }
Example #9
0
    //private void OnCollisionEnter2D(Collision2D collision)
    //{
    //    if (collision.collider.CompareTag(GameTags.Ball))
    //    {
    //        BallBase ball = collision.collider.GetComponent<BallBase>();
    //        if(ball != null)
    //        {
    //            ContactPoint2D contactPoint = collision.GetContact(0);
    //            CollisionSide colSide = CollisionSideDetect.GetCollisionSide(ball.LastFrameCenterPoint, contactPoint.point);
    //            ball.SetOppositeVelocity(colSide, PhysicsConstants.BallSpeedAfterEnemyHit);
    //            if (ball.LastFrameVelocity.magnitude < PhysicsConstants.BallSpeedPowerShotThreshold)
    //            {
    //                currentHealth--;
    //            }
    //            else
    //            {
    //                currentHealth -= 3;
    //            }
    //            SetColor();
    //        }
    //        if(currentHealth <= 0)
    //        {
    //            associatedSpawner.TryToDestroy(this);
    //        }
    //    }
    //}

    public void OnCollisionWithBall(BallBase ball)
    {
        if (ball.LastFrameVelocity.magnitude < PhysicsConstants.BallSpeedPowerShotThreshold)
        {
            currentHealth--;
        }
        else
        {
            currentHealth -= 3;
        }

        if (currentHealth <= 0)
        {
            associatedSpawner.TryToDestroy(this);
        }
    }
Example #10
0
 /// <summary>
 /// Updates the score. Points are calculated here before it's added to player's score
 /// </summary>
 public override void UpdatePoint(int score = 0, BallBase baseObj = null)
 {
     if (!_stopScoreUpdate)
     {
         base.UpdatePoint(score, baseObj);
         if (score < 0)
         {
             _cueBallSunk     = true;
             _stopScoreUpdate = true;                     //Stop subsequent point being added into the score
         }
         else if (score > 0)
         {
             _colourBallSunk = true;
         }
     }
 }
Example #11
0
    public Vector2 GetForceOnBallHit(BallBase ball, CollisionSide colSide)
    {
        switch (colSide)
        {
        case CollisionSide.Top:
            return(GetForceOnTopSide(ball));

        case CollisionSide.Bottom:
            return(GetForceOnBottomSide(ball));

        case CollisionSide.Left:
        case CollisionSide.Right:
            return(GetForceOnLeftOrRight(ball, colSide));

        default:
            return(Vector2.one);
        }
    }
Example #12
0
    private void OnCollisionWithBall(BallBase ball, RaycastHit2D rayHit, CollisionSide colSide, Vector2 direction, out float distanceForRay)
    {
        Vector2 lastFramePos  = LastFrameCenterPoint;
        Vector2 velocity      = LastFrameVelocity;
        Vector2 actualPos     = currentPosition;
        Vector2 centroidPoint = rayHit.centroid;
        Vector2 contactPoint  = rayHit.point;

        float distanceToCollision = (lastFramePos - centroidPoint).magnitude;
        float totalDistance       = (actualPos - lastFramePos).magnitude;
        float distanceAfterHit    = totalDistance - distanceToCollision;

        distanceForRay = distanceAfterHit;

        Vector2 distanceToAdd = distanceAfterHit * direction.normalized;

        ball.AddToPosition(distanceToAdd);
        ball.RaycastAndSkipThisFrameCollision();
    }
Example #13
0
    public CollisionSide GetCollisionSideWithBall(BallBase ball, Vector2 ballLastFramePosition)
    {
        CollisionSide colSide = CollisionSide.Top;

        Vector2 centerPoint = Collider.bounds.center;
        Vector2 targetPoint = ballLastFramePosition;
        float   objectCenterToTargetLength = (targetPoint - centerPoint).magnitude;
        float   bottomToTargetLength       = (targetPoint - LastFrameBottomPoint).magnitude;

        if (objectCenterToTargetLength < bottomToTargetLength)
        {
            colSide = CollisionSide.Bottom;
        }
        else
        {
            colSide = CollisionSide.Top;
        }

        return(colSide);
    }
Example #14
0
    public static BallBase GetItem(long objNo)
    {
        TableBallData data = Array.Find(Table, i => i.ObjNo == objNo);
        BallBase      item = new BallBase();

        item.Initialize(data.BallType);
        item.RestCount = (sbyte)CommonFunction.ConvergenceRandom(data.StartGap, data.Startprob, data.Con, data.MaxGap);
        item.ObjNo     = data.ObjNo;
        if (GameStateInformation.IsEnglish == false)
        {
            item.DisplayName = data.DisplayName;
            item.Description = data.Description;
        }
        else
        {
            item.DisplayName = data.DisplayNameEn;
            item.Description = data.DescriptionEn;
        }
        item.ThrowDexterity = data.ThrowDexterity;
        return(item);
    }
Example #15
0
 public virtual void UpdatePoint(int score = 0, BallBase baseObj = null)
 {
     UpdatePlayerScore(score);
 }
Example #16
0
    /// <summary>
    /// 投げる効果(誰かに当たった時)
    /// </summary>
    private bool ThrowActionEffect(ManageDungeon dun, PlayerCharacter player, BaseCharacter target)
    {
        switch (BType)
        {
        case BallType.Fire:

            //サウンドを鳴らす
            SoundInformation.Sound.Play(SoundInformation.SoundType.Bomb);

            int damage = FireBallFixDamage + Mathf.FloorToInt(player.BaseAttack * 2);

            AttackState atState = target.AddDamage(damage);
            //ボールエフェクト
            EffectFireBallLanding.CreateObject(target).Play();

            //ダメージエフェクト
            EffectDamage d = EffectDamage.CreateObject(target);
            d.SetText(damage.ToString(), AttackState.Hit);
            d.Play();

            //ヒットメッセージ
            DisplayInformation.Info.AddMessage(
                target.GetMessageAttackHit(damage));

            //対象が死亡したら
            if (atState == AttackState.Death)
            {
                if (target.Type == ObjectType.Player)
                {
                    ScoreInformation.Info.CauseDeath =
                        string.Format(CommonConst.DeathMessage.Item, this.DisplayNameNormal);

                    ScoreInformation.Info.CauseDeathType = DeathCouseType.Item;
                }

                DisplayInformation.Info.AddMessage(
                    target.GetMessageDeath(target.HaveExperience));

                player.Death(target, player.AttackInfo);
                target.DeathAction(dun);
            }
            break;

        case BallType.Gyro:

            SoundInformation.Sound.Play(SoundInformation.SoundType.BucketFall);

            //ターゲットが吹き飛ぶ先のポイントを取得
            bool     isWall;
            MapPoint point = dun.GetBlow(target.CurrentPoint, Direction, out isWall);

            //対象のポイントが取得できなければ
            if (CommonFunction.IsNull(point) == true)
            {
            }
            //対象ポイントが取得できればそこに移動
            else
            {
                if (typeof(BaseEnemyCharacter) == target.GetType())
                {
                    ((BaseEnemyCharacter)target).MoveState = EnemySearchState.FightPlayer;
                }
                DisplayInformation.Info.AddMessage(
                    string.Format(CommonConst.Message.BlowCharacter, target.DisplayNameInMessage));
                target.BlowDirection = Direction;
                target.BlowPoint     = point;
                target.MoveSpeed     = CommonConst.SystemValue.MoveSpeedDash;
                dun.MoveCharacter(point, target);

                //対象に衝突ダメージ
                if (isWall == true)
                {
                    target.BlowAfterDamage = GyroFixDamage;
                }

                //吹っ飛び先に誰かがいた場合
                MapPoint      vector = CommonFunction.CharacterDirectionVector[Direction];
                MapPoint      next   = MapPoint.Get(point.X + vector.X, point.Y + vector.Y);
                BaseCharacter second = dun.CharacterMap.Get(point.X, point.Y);
                if (CommonFunction.IsNull(second) == false)
                {
                    second.BlowAfterDamage = GyroFixDamage;
                    second.BlowPoint       = second.CurrentPoint;
                }
            }

            break;

        case BallType.Change:

            //サウンドを鳴らす
            SoundInformation.Sound.Play(SoundInformation.SoundType.Smoke);

            if (typeof(BaseEnemyCharacter) == target.GetType())
            {
                ((BaseEnemyCharacter)target).MoveState = EnemySearchState.FightPlayer;
            }
            //ターゲットとプレイヤーの場所を交換

            EffectSmoke.CreateObject(target).Play();
            EffectSmoke.CreateObject(player).Play();
            MapPoint tarp = target.CurrentPoint;
            target.SetPosition(player.CurrentPoint.X, player.CurrentPoint.Y);
            player.SetPosition(tarp.X, tarp.Y);
            DisplayInformation.Info.AddMessage(
                string.Format(CommonConst.Message.ChangePoint, target.DisplayNameInMessage));
            break;

        case BallType.Pickoff:

            //サウンドを鳴らす
            SoundInformation.Sound.Play(SoundInformation.SoundType.Smoke);

            //対象に混乱を付与
            int result = target.AddStateAbnormal((int)StateAbnormal.Confusion);
            //対象が混乱になったらメッセージを表示
            if (result != 0)
            {
                EffectSmoke.CreateObject(target).Play();
                DisplayInformation.Info.AddMessage(
                    CommonFunction.GetAbnormalMessage(StateAbnormal.Confusion, target));
            }
            break;

        case BallType.Bean:

            //サウンドを鳴らす
            SoundInformation.Sound.Play(SoundInformation.SoundType.Smoke);

            //対象に麻痺を付与
            int bresult = target.AddStateAbnormal((int)StateAbnormal.Palalysis);
            //対象が麻痺になったらメッセージを表示
            if (bresult != 0)
            {
                EffectSmoke.CreateObject(target).Play();
                DisplayInformation.Info.AddMessage(
                    CommonFunction.GetAbnormalMessage(StateAbnormal.Palalysis, target));
            }
            break;

        case BallType.Decoy:

            //サウンドを鳴らす
            SoundInformation.Sound.Play(SoundInformation.SoundType.Smoke);

            //対象にデコイを付与
            int dresult = target.AddStateAbnormal((int)StateAbnormal.Decoy);
            //対象がデコイになったらメッセージを表示
            if (dresult != 0)
            {
                EffectSmoke.CreateObject(target).Play();
                DisplayInformation.Info.AddMessage(
                    CommonFunction.GetAbnormalMessage(StateAbnormal.Decoy, target));
            }
            break;

        case BallType.Slow:

            //サウンドを鳴らす
            SoundInformation.Sound.Play(SoundInformation.SoundType.Smoke);

            //対象にスローを付与
            int sresult = target.AddStateAbnormal((int)StateAbnormal.Slow);
            //対象がスローになったらメッセージを表示
            if (sresult != 0)
            {
                EffectSmoke.CreateObject(target).Play();
                DisplayInformation.Info.AddMessage(
                    CommonFunction.GetAbnormalMessage(StateAbnormal.Slow, target));
            }
            break;

        //ナックル
        case BallType.Knuckle:

            List <BallType> blist = new List <BallType>();
            foreach (BallType val in Enum.GetValues(typeof(BallType)))
            {
                blist.Add(val);
            }
            blist.Remove(BallType.Knuckle);
            blist.Remove(BallType.Handmaid);

            //ナックル以外の効果をランダムで取得
            BallType temp = blist[UnityEngine.Random.Range(0, blist.Count)];

            BallBase b = new BallBase();
            b.CurrentPoint = CurrentPoint;
            b.Direction    = Direction;
            b.BType        = temp;
            //効果を発動
            b.ThrowActionEffect(dun, player, target);
            break;

        case BallType.Trap:

            TrapBreaker(dun, player);
            break;

        case BallType.Handmaid:

            //ヒットエフェクト
            EffectFireBallLanding.CreateObject(target).Play();

            //サウンドを鳴らす
            SoundInformation.Sound.Play(SoundInformation.SoundType.AttackHit);

            //範囲拡大がついているとき
            int   plus;
            float cf;
            int   dist = 0;
            if (CommonFunction.HasOptionType(this.Options, OptionType.Wildfire, out plus, out cf) == true)
            {
                dist = plus;
            }

            dun.SetUpCharacterMap();
            List <BaseCharacter> targets = dun.GetNearCharacters(target.CurrentPoint, dist, true);

            foreach (BaseCharacter t in targets)
            {
                //int damage2 = FireBallFixDamage + Mathf.FloorToInt(player.BaseAttack * 2);
                int damage2 = Mathf.FloorToInt((15 + player.BaseAttack) / (target.CurrentPoint.DistanceAbs(t.CurrentPoint) + 1));

                //効果増幅があったら
                if (CommonFunction.HasOptionType(this.Options, OptionType.EffectUp, out plus, out cf) == true)
                {
                    damage2 = damage2 + plus * (int)cf;
                }
                //効果縮小があったら
                if (CommonFunction.HasOptionType(this.Options, OptionType.EffectDown, out plus, out cf) == true)
                {
                    damage2 = damage2 - plus * (int)cf;
                }

                //ダメージ増減30%
                float rand = 0.3f;
                if (CommonFunction.HasOptionType(this.Options, OptionType.EffectStabile, out plus, out cf) == true)
                {
                    rand -= cf * plus;
                }
                else if (CommonFunction.HasOptionType(this.Options, OptionType.EffectNotStabile, out plus, out cf) == true)
                {
                    rand += cf * plus;
                }

                damage2 += Mathf.CeilToInt(UnityEngine.Random.Range(-rand * damage2, rand * damage2));

                //通常ダメージの場合
                if (CommonFunction.HasOptionType(this.Options, OptionType.ReverceDamage) == false)
                {
                    AttackState atState2 = t.AddDamage(damage2);

                    //ダメージエフェクト
                    EffectDamage d2 = EffectDamage.CreateObject(t);
                    d2.SetText(damage2.ToString(), AttackState.Hit);
                    d2.Play();

                    //ヒットメッセージ
                    DisplayInformation.Info.AddMessage(
                        t.GetMessageAttackHit(damage2));

                    //対象が死亡したら
                    if (atState2 == AttackState.Death)
                    {
                        DisplayInformation.Info.AddMessage(
                            t.GetMessageDeath(t.HaveExperience));

                        if (t.Type == ObjectType.Player)
                        {
                            ScoreInformation.Info.CauseDeath =
                                string.Format(CommonConst.DeathMessage.Item, this.DisplayNameNormal);

                            ScoreInformation.Info.CauseDeathType = DeathCouseType.Item;

                            t.Death();
                        }
                        else
                        {
                            if (IsExp == true)
                            {
                                player.Death(t, player.AttackInfo);
                            }
                            else
                            {
                                t.Death();
                            }
                        }
                        t.DeathAction(dun);
                    }
                }
                //基本効果反転
                else
                {
                    t.RecoverHp(damage2);

                    //ヒットエフェクト
                    EffetHitShockWave.CreateObject(t).Play();

                    //ダメージエフェクト
                    EffectDamage d2 = EffectDamage.CreateObject(t);
                    d2.SetText(damage2.ToString(), AttackState.Heal);
                    d2.Play();

                    //ヒットメッセージ
                    DisplayInformation.Info.AddMessage(
                        string.Format(CommonConst.Message.RecoverHp, t.DisplayNameInMessage));
                }
            }

            //状態異常の付与
            EffectAbnormal(targets);

            //火柱があれば火柱を立てる
            if (CommonFunction.HasOptionType(this.Options, OptionType.CatchingFire) == true)
            {
                dun.SetUpTrapMap();
                if (CommonFunction.IsNull(dun.TrapMap.Get(CurrentPoint)) == true)
                {
                    BaseTrap trap = TableTrap.GetTrap(CommonConst.ObjNo.Ember);
                    trap.Options   = CommonFunction.CloneOptions(this.Options);
                    trap.IsVisible = true;
                    trap.SetThisDisplayTrap(CurrentPoint.X, CurrentPoint.Y);
                    dun.AddNewTrap(trap);

                    DisplayInformation.Info.AddMessage(
                        CommonConst.Message.TrapEmber);
                }
            }

            break;

        case BallType.Fumble:
            //対象のレベルが2以上ならレベルを下げる
            if (target.Level > 1)
            {
                if (target.Type == ObjectType.Enemy)
                {
                    BaseEnemyCharacter enemy = ((BaseEnemyCharacter)target);
                    enemy.Level--;
                    TableEnemy.SetLevel(enemy, enemy.Level,
                                        DisplayInformation.Info.Floor,
                                        DungeonInformation.Info.EnemyHpProb,
                                        DungeonInformation.Info.EnemyAtkProb,
                                        DungeonInformation.Info.EnemyExpProb,
                                        DungeonInformation.Info.StartProbHp,
                                        DungeonInformation.Info.StartProbAtk,
                                        DungeonInformation.Info.StartProbExp);

                    DisplayInformation.Info.AddMessage(
                        string.Format(CommonConst.Message.LevelDownPlayer, enemy.DisplayNameInMessage));

                    EffectBadSmoke.CreateObject(enemy).Play();
                }
            }

            break;

        case BallType.Winning:

            if (target.Type == ObjectType.Enemy)
            {
                BaseEnemyCharacter enemy = ((BaseEnemyCharacter)target);
                enemy.Level++;
                TableEnemy.SetLevel(enemy, enemy.Level,
                                    DisplayInformation.Info.Floor,
                                    DungeonInformation.Info.EnemyHpProb,
                                    DungeonInformation.Info.EnemyAtkProb,
                                    DungeonInformation.Info.EnemyExpProb,
                                    DungeonInformation.Info.StartProbHp,
                                    DungeonInformation.Info.StartProbAtk,
                                    DungeonInformation.Info.StartProbExp);

                DisplayInformation.Info.AddMessage(
                    string.Format(CommonConst.Message.LevelUpPlayer, enemy.DisplayNameInMessage));

                EffectFlareCore.CreateObject(enemy).Play();
            }
            break;

        case BallType.Four:

            if (target.Type == ObjectType.Enemy)
            {
                BaseEnemyCharacter enemy = ((BaseEnemyCharacter)target);

                if (enemy.IsFourBallCount() == true)
                {
                    int dam = Mathf.CeilToInt(enemy.MaxHp);

                    AttackState atstate = target.AddDamage(dam);
                    //ボールエフェクト
                    EffetHitShockWave.CreateObject(enemy).Play();

                    //ダメージエフェクト
                    EffectDamage dt = EffectDamage.CreateObject(target);
                    dt.SetText(dam.ToString(), AttackState.Hit);
                    dt.Play();

                    //ヒットメッセージ
                    DisplayInformation.Info.AddMessage(
                        target.GetMessageAttackHit(dam));

                    SoundInformation.Sound.Play(SoundInformation.SoundType.AttackHit);

                    //対象が死亡したら
                    if (atstate == AttackState.Death)
                    {
                        if (target.Type == ObjectType.Player)
                        {
                            ScoreInformation.Info.CauseDeath =
                                string.Format(CommonConst.DeathMessage.Item, this.DisplayNameNormal);

                            ScoreInformation.Info.CauseDeathType = DeathCouseType.Item;
                        }
                        DisplayInformation.Info.AddMessage(
                            target.GetMessageDeath(target.HaveExperience));

                        player.Death(target, player.AttackInfo);
                        target.DeathAction(dun);
                    }
                }
                else
                {
                    SoundInformation.Sound.Play(SoundInformation.SoundType.AttackHit);
                    //ボールエフェクト
                    EffetHitShockWave.CreateObject(enemy).Play();
                }
            }

            break;

        case BallType.Emery:

            if (target.Type == ObjectType.Enemy)
            {
                BaseEnemyCharacter enemy = ((BaseEnemyCharacter)target);

                if (enemy.IsBoss() == false)
                {
                    GameStateInformation.Info.EmeryTarget = target.ObjNo;

                    DisplayInformation.Info.AddMessage(
                        string.Format(CommonConst.Message.EmeryCharacter, target.DisplayNameInMessage));

                    List <BaseCharacter> emeryies = dun.Characters.FindAll(i => i.ObjNo == target.ObjNo);

                    SoundInformation.Sound.Play(SoundInformation.SoundType.Summon);

                    foreach (BaseCharacter c in emeryies)
                    {
                        EffectSmoke.CreateObject(c, false).Play();

                        dun.RemoveCharacter(c);
                        ManageDungeon.KillObjectNow(c);
                    }
                }
            }
            break;
        }
        Options = null;

        return(true);
    }
Example #17
0
    private void OnCollision(BallBase ball, RaycastHit2D rayHit, CollisionSide colSide, CollisionType colType, float totalDistance, float endSpeed, int safe, ICollider collidingObject, out float distanceAfterHit)
    {
        if (totalDistance <= 0)
        {
            rayHits = new RaycastHit2D[0];
            Debug.LogWarning("TOTAL DISTNANCE <= 0!");
            distanceAfterHit = 0;
            return;
        }

        Vector2 lastFramePos  = ball.LastFrameCenterPoint;
        Vector2 velocity      = LastFrameVelocity;
        Vector2 actualPos     = currentCenterPoint;
        Vector2 centroidPoint = rayHit.centroid;

        float colRadius           = Collider.radius / 2;
        float distanceToCollision = rayHit.distance;

        distanceAfterHit = totalDistance - distanceToCollision;
        // Debug.LogFormat("[{3}] distanceToCollision: {0}, total distance: {1} distanceAfterHit: {2}", distanceToCollision, totalDistance, distanceAfterHit, safe);

        Debug.DrawLine(centroidPoint, rayHit.point, Color.blue, 2);
        Debug.DrawLine(actualPos, lastFramePos, safe == 0 ? Color.black : Color.yellow, 2);
        Debug.DrawLine(actualPos, centroidPoint, Color.green, 2);

        Vector2 newPos;
        bool    overlapping = distanceToCollision == 0;

        Debug.LogFormat("Collision. side: {0} type: {1} overlap: {2}, last framePos: {3} actualPos: {4}", colSide, colType, overlapping, lastFramePos, actualPos);
        if (overlapping)
        {
            Debug.LogWarningFormat("OVERLAPPING! To collision: {0} total distance: {1}", distanceToCollision, totalDistance);
            overlapping      = true;
            newPos           = GetNewPositionWhenOverlaping(colType, colSide, collidingObject, rayHit, actualPos, colRadius);
            distanceAfterHit = totalDistance - (newPos - lastFramePos).magnitude;
            Debug.Log("new distance after hit: " + distanceAfterHit);
            if (distanceAfterHit <= -100)
            {
                Debug.Log("FAIL");
            }
            // newPos = GetNewPositionBasedOnCollisionType(colType, colSide, newPos, velocity, distanceAfterHit);
            // Debug.LogFormat("Pos changed: {0} to {1}", lastFramePos, newPos);
        }
        else
        {
            newPos = GetNewPositionBasedOnCollisionType(colType, colSide, centroidPoint, velocity, collidingObject, distanceAfterHit);

            Vector2 endVel = SetVelocityBasedOnCollisionType(colType, colSide, collidingObject, endSpeed, LastFrameVelocity);
            LastFrameVelocity = endVel;
            Debug.Log("change velocity to " + (endVel.y < 0 ? "DOWN" : "UP"));
        }

        ball.transform.position = newPos;
        Debug.DrawLine(centroidPoint, newPos, safe == 0 ? Color.red : Color.grey, 2);
        currentCenterPoint = newPos;

        if (overlapping)
        {
            rayHit.centroid = newPos;
            rayHit.distance = distToMoveOnOverlap;
            //rayHits = new RaycastHit2D[1] { rayHit };
            //rayHits = Physics2D.CircleCastAll(newPos, colRadius, newPos - actualPos, distanceAfterHit, ColliderLayerMask);
            OnCollision(ball, rayHit, colSide, colType, distanceAfterHit, endSpeed, safe, collidingObject, out distanceAfterHit);
            LastFrameCenterPoint = newPos;
        }
        else
        {
            rayHits = Physics2D.CircleCastAll(centroidPoint, colRadius, newPos - centroidPoint, distanceAfterHit, ColliderLayerMask);
            LastFrameCenterPoint = rayHit.centroid;
            rayHits = rayHits.Remove(rayHit);
        }


        // Debug.LogFormat("col Y: {0}, end Y: {1}", centroidPoint.y, newPos.y);
        //  Debug.LogFormat("start vel: {0} end vel: {1}", velocity.normalized, endVel.normalized);
    }