/// <summary>
        /// フェンスの位置によって、ボールの位置を補正する
        /// (人の位置を補正する場合にも使用できる。ゴロと同じ扱いのため、isFlyをfalseで指定する)
        /// </summary>
        /// <param name="basePoint">ボール位置</param>
        /// <param name="move">移動するVector</param>
        /// <param name="isFly">フライか</param>
        /// <param name="fenseReflect">外野フェンスに当たったか</param>
        /// <param name="fenseOver">外野フェンスを超えたか</param>
        /// <returns>補正後の位置</returns>
        private static MPoint ChangePointByFense(MPoint basePoint, Vector move, bool isFly, 
												out bool fenseReflect, out bool fenseOver)
        {
            fenseReflect = false;
            fenseOver = false;
            MPoint result = basePoint + move;

            // 捕逸か後方にファウルした場合、画面外にでないように補正
            // (フライの場合は補正せず、呼び出し元で判定)
            if (!isFly && result.Y < Constants.MinScreenPoint.Y)
            {
                return new MPoint(result.X, Constants.MinScreenPoint.Y);
            }

            // フェンスの手前であれば何もせずに値を返す
            // (後方のフェンスをフライで超える場合もそのまま返す)
            if ((result - Constants.PointHomeBase).Length < Constants.BaseToFenceDistance ||
                result.Y < Constants.MinScreenPoint.Y)
            {
                return result;
            }

            // 以下、フェンスを超える場合

            // フライでフェンス超えた場合はホームラン
            if (isFly)
            {
                fenseOver = true;
                return result;
            }

            // 以下、フェンスを超えるゴロの場合

            // フェンスを超える判定結果を設定
            fenseReflect = true;

            // フェンスを超える場合、フェンスまでで止める
            result = basePoint;
            do
            {
                // 超えるまで少しずつ足す
                result = result + new Vector(move.X * 0.1, move.Y * 0.1);
            }
            while ((result - Constants.PointHomeBase).Length < Constants.BaseToFenceDistance);

            // 最後に少しだけ超えた分の距離を戻す
            result = result - new Vector(move.X * 0.1, move.Y * 0.1);

            // フェンスの手前に補正した座標を返す
            return result;
        }
        /// <summary>
        /// 送球開始から完了までの時間を取得
        /// </summary>
        /// <param name="targetBase">送球先ベース</param>
        /// <param name="memberAbility">送球メンバ能力</param>
        /// <param name="startPoint">送球開始位置</param>
        /// <param name="runTargetBase">送球先に自分が走ってベースカバーに行くか</param>
        /// <returns>送球が届くまでの時間</returns>
        public static int GetThrowBollReachTime(int targetBase, GameMemberAbility memberAbility, MPoint startPoint, bool runTargetBase)
        {
            // 送球速度
            double bollSpeed;
            if (!runTargetBase)
            {
                // 通常の送球速度の設定
                bollSpeed = memberAbility.Throw * Constants.ThrowBollSpeedOffSet;
                if (DefensePositionHelper.IsOutFielder(memberAbility.DefensePosition))
                {
                    // 外野の場合は送球速度低下
                    bollSpeed *= Constants.ThrowBollSpeedOffSetByOutFileder;
                }
            }
            else
            {
                // ベースカバーが遅れており、自分でベースを踏む場合は自分の走力が送球速度になる
                bollSpeed = memberAbility.RunSpeed;
            }

            // 送球が届くまでの時間(0割を防ぐ意味でも必ず1秒以上かかる)
            MPoint targetPoint = GameData.GetBasePoint(targetBase);
            double distance = (targetPoint - startPoint).Length;
            return Math.Max((int)(Math.Ceiling(distance / bollSpeed)), 1);
        }
 /// <summary>
 /// フェンスの位置によって、守備メンバの位置を補正する
 /// </summary>
 /// <param name="basePoint">元の位置</param>
 /// <param name="move">移動ベクトル</param>
 /// <returns>移動後の位置</returns>
 private static MPoint ChangePointByFense(MPoint basePoint, Vector move)
 {
     bool fenseReflect;
     bool fenseOver;
     // isFlyをfalseで実行することで、ゴロ扱いし、フェンスを超えないように移動する
     return ChangePointByFense(basePoint, move, false, out fenseReflect, out fenseOver);
 }
 /// <summary>
 /// 送球前の回転にかかる時間を取得する
 /// </summary>
 /// <param name="position">送球する守備位置</param>
 /// <param name="targetBase">送球先ベース</param>
 /// <param name="throwStartPoint">送球開始位置</param>
 /// <returns>かかる時間</returns>
 private int GetTurningForThrowTime(DefensePosition position, int targetBase, MPoint throwStartPoint)
 {
     GameMemberAbility throwMemberAbility = GameData.GetDefenseMemberAbility(position);
     if (NeedTurnForThrow(throwMemberAbility, targetBase, throwStartPoint))
     {
         return Constants.TurnForThrowTime;
     }
     else
     {
         return 0;
     }
 }
        /// <summary>
        /// 送球前の回転が必要か判定
        /// </summary>
        /// <param name="throwMemberAbility">送球メンバ能力</param>
        /// <param name="targetBase">送球先</param>
        /// <param name="throwStartPoint">送球開始位置</param>
        /// <returns>余分に時間がかかるか</returns>
        private bool NeedTurnForThrow(GameMemberAbility throwMemberAbility, int targetBase, MPoint throwStartPoint)
        {
            // 回転が必要ない野手であれば不要を返す
            // (投手と内野のみが対象で、捕手は反対を向いているため回転不要)
            if (throwMemberAbility.DefensePosition != DefensePosition.Pitcher &&
                throwMemberAbility.DefensePosition != DefensePosition.First &&
                throwMemberAbility.DefensePosition != DefensePosition.Second &&
                throwMemberAbility.DefensePosition != DefensePosition.Third &&
                throwMemberAbility.DefensePosition != DefensePosition.Short)
            {
                return false;
            }

            // 左投げで一塁送球時に回転が必要
            if (throwMemberAbility.GameMember.Player.IsLeftThrow && targetBase == 1)
            {
                return true;
            }

            // 前にダッシュして後ろ(二塁)に送球する場合は回転が必要
            // (二塁へのバントを成功させやすくするための処置のため、バントで二塁送球時に必ず発生する)
            if (GameData.CurrentBattingBunt && targetBase == 2)
            {
                return true;
            }

            // 右投げで三塁送球時に回転が必要
            // (二塁手/遊撃手/三塁手をむやみに回転させたくないため、投手と一塁手のみ発生する)
            if (throwMemberAbility.GameMember.Player.IsLeftThrow == false && targetBase == 3 &&
                (throwMemberAbility.DefensePosition == DefensePosition.Pitcher ||
                 throwMemberAbility.DefensePosition == DefensePosition.First))
            {
                return true;
            }

            // 上記の条件を満たさなければ回転不要
            return false;
        }
        /// <summary>
        /// ランナーの論理位置からUIとしてのマージン位置を算出する
        /// </summary>
        /// <param name="point"></param>
        /// <returns></returns>
        private Thickness GetRunnerMargin(MPoint point)
        {
            // スケールの違いを算出
            // (このコントロールでは70がベース間距離)
            double scaleOffset = 70.0 / Constants.BaseCoord;

            double left = point.X * scaleOffset + this.Width / 2 - BatterRunner.Width / 2;
            double top = - point.Y * scaleOffset + 200 + BatterRunner.Height / 2;
            double right = this.Width - (left + BatterRunner.Width);
            double bottom = this.Height - (top + BatterRunner.Height);

            return new Thickness(left, top, right, bottom);
        }
Exemple #7
0
 /// <summary>
 /// 2点の中間地点に対するベクトルの角度を取得
 /// </summary>
 /// <param name="point1"></param>
 /// <param name="point2"></param>
 /// <returns></returns>
 public static double GetAngle(MPoint point1, MPoint point2)
 {
     MPoint interLevel = new MPoint((point1.X + point2.X) / 2, (point1.Y + point2.Y) / 2);
     return Math.Atan2(interLevel.X, interLevel.Y) * (180 / Math.PI);
 }
        /// <summary>
        /// 送球開始から完了までの時間を取得
        /// </summary>
        /// <param name="targetBase">送球先ベース</param>
        /// <param name="throwPosition">送球ポジション</param>
        /// <param name="startPoint">送球開始位置</param>
        /// <returns>送球が届くまでの時間</returns>
        private int GetThrowBollReachTime(int targetBase, DefensePosition throwPosition, MPoint startPoint)
        {
            // 送球中の時間
            int throwBollReachTime = GetThrowBollReachTime(targetBase, throwPosition, startPoint, false);

            // 送球中の時間
            return throwBollReachTime;
        }
        /// <summary>
        /// 送球開始から完了までの時間を取得
        /// </summary>
        /// <param name="targetBase">送球先ベース</param>
        /// <param name="throwPosition">送球ポジション</param>
        /// <param name="startPoint">送球開始位置</param>
        /// <param name="runTargetBase">送球先に自分が走ってベースカバーに行くか</param>
        /// <returns>送球が届くまでの時間</returns>
        private int GetThrowBollReachTime(int targetBase, DefensePosition throwPosition, MPoint startPoint, bool runTargetBase)
        {
            // 送球メンバ能力の取得
            GameMemberAbility memberAbility = GameData.GetDefenseMemberAbility(throwPosition);

            // 送球が届くまでの時間を取得
            return GetThrowBollReachTime(targetBase, memberAbility, startPoint, runTargetBase);
        }
        /// <summary>
        /// 送球を実行する
        /// (送球先を決定済みで、送球前の回転も完了済みであることを前提とする)
        /// (ベースカバーを待つ場合は何もしない)
        /// </summary>
        private void ExecuteThrow()
        {
            // 自分が走って送球先に行くかの変数を定義
            bool runToTargetBase = false;

            // ベースカバーがまだ完了していない場合に待つか自分で走るかを判定
            if (FinishedBaseCover(ThrowTargetBase) == false)
            {
                // 送球のための回転から送球完了までの時間を取得
                // (送球前の回転は実施済みのため、送球開始以降の時間を取得する)
                int targetBase = ThrowTargetBase;
                DefensePosition throwPosition = GameData.BollKeepingPosition;
                MPoint startPoint = GameData.BollPoint;
                int throwTime = GetThrowBollReachTime(targetBase, throwPosition, startPoint);

                // ベースカバー完了までの時間を算出
                int baseCoverTime = BaseCoverRemainingTime[ThrowTargetBase];
                if (baseCoverTime > throwTime)
                {
                    // ベースカバー完了の方が遅ければ、それが送球完了時間となる
                    // (送球完了時にベースカバー完了するタイミングまで送球開始を待つため)
                    throwTime = baseCoverTime;

                    // 自分でベースまで走った場合と比較してどちらが速いか検証する
                    int throwTimeByRun = GetThrowBollReachTime(targetBase, throwPosition, startPoint, true);
                    if (throwTimeByRun < throwTime)
                    {
                        // 自分でベースまで走った方が早ければ、そのフラグを立てる
                        runToTargetBase = true;

                        // ベースカバーの設定も更新する
                        SetBaseCoverPosition(ThrowTargetBase, GameData.BollKeepingPosition);
                    }
                    else
                    {
                        // 自分で走るよりベースカバーが入るまで待った方が早い場合は何もせず待つ
                        return;
                    }
                }
            }

            // 送球野手
            ThrowPosition = GameData.BollKeepingPosition;

            // 送球開始位置
            ThrowStartPoint = GameData.BollPoint;

            // 送球が届くまでの時間を設定
            ThrowReachTime = GetThrowBollReachTime(ThrowTargetBase, GameData.BollKeepingPosition, ThrowStartPoint, runToTargetBase);

            // 送球先位置
            ThrowTargetPoint = GameData.GetBasePoint(ThrowTargetBase);

            // 守備動作種別の変更
            GameData.DefenseTermKind = DefenseTermKind.Throwing;

            // 進塁停止していたランナーの進塁の再判断
            foreach (RunnerStatus runnerStatus in GameData.AllRunnerStatus)
            {
                if (runnerStatus.IsStop)
                {
                    UpdateRunnerStatusForForwardOrBack(runnerStatus);
                }
            }

            // 送球開始のイベント発行
            if (ThrowBoll != null)
            {
                ThrowBoll();
            }
        }
        /// <summary>
        /// 指定時間後の守備メンバの位置を返す
        /// </summary>
        /// <param name="memberAbility">対象メンバ</param>
        /// <param name="goalPoint">目標位置位置</param>
        /// <param name="fitureSecond">指定時間</param>
        /// <returns>指定時間後の守備メンバの位置</returns>
        private MPoint GetDefenseMovePoint(GameMemberAbility memberAbility, MPoint goalPoint, int fitureSecond)
        {
            // 指定時間後の守備メンバの移動距離を取得
            double moveDistance = GetDefenseMoveDistance(memberAbility, fitureSecond);

            // 指定秒数後のメンバ位置を取得
            MPoint fitureMemberPoint;
            {
                MPoint memberPoint = GameData.GetDefensePoint(memberAbility.DefensePosition);

                // 目的位置とメンバの位置関係から進行方向のベクトルを取得
                Vector memberToGoalVector = (goalPoint - memberPoint);

                if (memberToGoalVector.Length > moveDistance)
                {
                    // ベクトルを正規化
                    double normalizing = memberToGoalVector.Length > 0 ? memberToGoalVector.Length : 1;
                    memberToGoalVector = new Vector(memberToGoalVector.X / normalizing, memberToGoalVector.Y / normalizing);

                    // 正規化したベクトルと移動距離から移動ベクトルを算出
                    Vector moveVector = new Vector(moveDistance * memberToGoalVector.X, moveDistance * memberToGoalVector.Y);

                    // フェンスによる位置の補正
                    fitureMemberPoint = ChangePointByFense(memberPoint, moveVector);
                }
                else
                {
                    // 目標位置までの距離が移動可能距離より小さい場合は、目標位置がそのまま最終位置になる
                    fitureMemberPoint = goalPoint;
                }

            }
            return fitureMemberPoint;
        }
 /// <summary>
 /// 指定したコントロールの位置変更のアニメーションを実行する
 /// </summary>
 /// <param name="toPoint"></param>
 /// <param name="control"></param>
 private void MoveControl(MPoint toPoint, FrameworkElement control)
 {
     Thickness toMargin = UIUtility.GetMargin(toPoint, control);
     UIUtility.MoveControlByMargin(toMargin, control, TimeSpan.Zero);
 }
        /// <summary>
        /// 捕球アニメーションの実行
        /// </summary>
        /// <param name="beforeDefensePoint">捕球直前位置</param>
        public void ExecuteBollCatchAnimation(MPoint beforeDefensePoint)
        {
            // 捕球直前位置とボール位置がほとんど変わらなければ何もしない
            if ((beforeDefensePoint - GameData.BollPoint).Length < UIConstants.LengthOfShowCatchAnime)
            {
                return;
            }

            // コントロールの初期値設定
            CatchAnime.SetGroudPictureMargin(beforeDefensePoint);

            // フェードアウトアニメーションの実行
            UIUtility.FadeOutControl(CatchAnime, TimeSpan.Zero, UIConstants.ShowCatchAnimeDuration);

            // コントロールの移動はなぜか正常に動作しないため実施せず
            {
                // コントロールの移動アニメーションの実行(Canvas方式)
                //MPoint bollUIPoint = UIUtility.GetControlPoint(GameData.BollPoint);
                //UIUtility.MoveControlInCanvas(new Point(bollUIPoint.X, bollUIPoint.Y), CatchAnime, new TimeSpan(0, 0, 0, 0, 100), new TimeSpan(0, 0, 0, 0, 500), true, new Point(beforeUIPoint.X, beforeUIPoint.Y));
                // コントロールの移動アニメーションの実行(Margin方式)
                //Thickness toMargin = UIUtility.GetMargin(GameData.BollPoint, CatchAnime);
                //UIUtility.MoveControlByMargin(toMargin, CatchAnime, new TimeSpan(0, 0, 0, 0, 500), true);
            }
        }
Exemple #14
0
 /// <summary>
 /// 指定した守備位置の現在位置を設定する
 /// </summary>
 /// <param name="defensePosition">指定する守備</param>
 /// <param name="point">設定値</param>
 public void SetDefensePoint(DefensePosition defensePosition, MPoint point)
 {
     switch (defensePosition)
     {
         case DefensePosition.Pitcher:
             Defense1Point = point;
             break;
         case DefensePosition.Catcher:
             Defense2Point = point;
             break;
         case DefensePosition.First:
             Defense3Point = point;
             break;
         case DefensePosition.Second:
             Defense4Point = point;
             break;
         case DefensePosition.Third:
             Defense5Point = point;
             break;
         case DefensePosition.Short:
             Defense6Point = point;
             break;
         case DefensePosition.Left:
             Defense7Point = point;
             break;
         case DefensePosition.Center:
             Defense8Point = point;
             break;
         case DefensePosition.Right:
             Defense9Point = point;
             break;
         default:
             throw new Exception("Invalid DefensePosition");
     }
 }
        /// <summary>
        /// 打球速度が減速する場合は減速後の打球速度を返す
        /// </summary>
        /// <param name="isFly">フライか</param>
        /// <param name="passedSecond">経過時間</param>
        /// <param name="bollPoint">ボール位置</param>
        /// <param name="bollSpeed">現在の打球速度</param>
        /// <returns>減速後の打球速度</returns>
        private static double GetBollSpeed(bool isFly, int passedSecond, MPoint bollPoint, double bollSpeed)
        {
            // 打球速度の低下(一定時間経過後か一定距離到達後に減速)
            if (passedSecond >= Constants.BattedBollAttenuationStartTime ||
                (bollPoint - Constants.PointHomeBase).Length >= Constants.BattedBollAttenuationDistance)
            {
                if (isFly)
                {
                    // フライの場合
                    return bollSpeed * Constants.BattedBollAttenuationByFly;
                }
                else
                {
                    // ゴロの場合
                    return bollSpeed * Constants.BattedBollAttenuationByGround;
                }
            }

            // 減速がなければ元の値を返す
            return bollSpeed;
        }
        /// <summary>
        /// 送球のための回転開始から送球完了までの時間を取得
        /// </summary>
        /// <param name="targetBase">送球先ベース</param>
        /// <param name="throwPosition">送球ポジション</param>
        /// <param name="startPoint">送球開始位置</param>
        /// <param name="memberAbility">送球メンバ能力</param>
        /// <returns>かかる時間時間</returns>
        private int GetThrowBollReachTimeFromTurn(int targetBase, DefensePosition throwPosition, MPoint startPoint, GameMemberAbility memberAbility)
        {
            // 送球開始から完了までの時間を取得
            int throwTime = GetThrowBollReachTime(targetBase, throwPosition, startPoint);

            // 送球前の回転が必要な場合は余分に時間を加算
            if (NeedTurnForThrow(memberAbility, targetBase, startPoint))
            {
                throwTime += Constants.TurnForThrowTime;
            }

            return throwTime;
        }
        /// <summary>
        /// 指定時間後の守備メンバがボールを捕球できるか
        /// </summary>
        /// <param name="memberAbility">対象メンバ</param>
        /// <param name="bollPoint">指定時間後のボール位置</param>
        /// <param name="fitureSecond">指定時間</param>
        /// <returns>捕球できるか</returns>
        private bool CatchedBoll(GameMemberAbility memberAbility, MPoint bollPoint, int fitureSecond)
        {
            // エラー発生後の再判定時、ベースカバーの野手は捕球できない
            if (IsError && IsBaseCover(memberAbility.GameMember.DefensePosition))
            {
                return false;
            }

            // 残り硬直時間を取得
            int stiffSecond = GetStiffSecond(memberAbility);
            if (fitureSecond < stiffSecond)
            {
                // 硬直時間中はボールを捕球できない
                return false;
            }

            // メンバとボールの距離
            double defenseToBollDistanse = (GameData.GetDefensePoint(memberAbility.DefensePosition) - bollPoint).Length;

            // 指定時間後の守備メンバの移動距離を取得
            double moveDistance = GetDefenseMoveDistance(memberAbility, fitureSecond);

            // 捕球範囲を取得
            double catchArea = GetCatchArea(memberAbility);

            // 捕球できるかを返す
            return moveDistance + catchArea >= defenseToBollDistanse;
        }
        /// <summary>
        /// 送球開始の回転からタッチアウトまでにかかる時間を取得
        /// (ベースカバーが遅れて自分でベースまで走る場合も考慮)
        /// </summary>
        /// <param name="targetBase">送球先ベース</param>
        /// <param name="throwPosition">送球ポジション</param>
        /// <param name="startPoint">送球開始位置</param>
        /// <param name="memberAbility">送球メンバ能力</param>
        /// <param name="passedTime">送球開始までに現在時刻からさらに経過している時間(捕球前の予測で使用)</param>
        /// <returns>かかる時間時間</returns>
        private int GetThrowTimeFromTurnToTouch(int targetBase, DefensePosition throwPosition, MPoint startPoint, GameMemberAbility memberAbility, int passedTime)
        {
            // 送球前の回転から送球完了までの時間の算出
            int throwTime = GetThrowBollReachTimeFromTurn(targetBase, throwPosition, startPoint, memberAbility);

            // ベースカバー完了までの時間を算出(送球開始までにさらに経過している時間は減算)
            int baseCoverTime = BaseCoverRemainingTime[targetBase] - passedTime;
            if (baseCoverTime > throwTime)
            {
                // ベースカバー完了の方が遅ければ、それが送球完了時間となる
                // (送球完了時にベースカバー完了するタイミングまで送球開始を待つため)
                throwTime = baseCoverTime;

                // 自分でベースまで走った場合と比較してどちらが速いか検証する
                int throwTimeByRun = GetThrowBollReachTime(targetBase, throwPosition, startPoint, true);
                if (throwTimeByRun < throwTime)
                {
                    // 自分でベースまで走った方が早ければ、その時間を送球時間とする
                    throwTime = throwTimeByRun;
                }
            }

            // フォースアウトでも帰塁ランナーのアウトでもなければ
            // タッチアウト体制への準備時間を加算する
            if (!IsForceOut(targetBase) && GetBackRunRunner(targetBase) == null)
            {
                throwTime += Constants.ReadyingTouchSecond;
            }

            // かかる時間を返す
            return throwTime;
        }
        /// <summary>
        /// 捕球ハンドラ
        /// </summary>
        /// <param name="beforeDefensePoint">捕球直前の守備位置</param>
        private void m_GameManager_CatchBoll(MPoint beforeDefensePoint)
        {
            // 高速試合モードであれば何もしない
            if (m_GameManager.HighSpeedGameMode)
            {
                return;
            }

            // 捕球アニメーションの実行
            m_DefenseActionView.ExecuteBollCatchAnimation(beforeDefensePoint);
            SoundManager.PlayEffect(SoundEffectKind.Catch);
        }
Exemple #20
0
 /// <summary>
 /// 捕球ハンドラ
 /// </summary>
 /// <param name="beforeDefensePoint">捕球直前の守備位置</param>
 private void DefenseActionManger_CatchBoll(MPoint beforeDefensePoint)
 {
     if (CatchBoll != null)
     {
         CatchBoll(beforeDefensePoint);
     }
 }