public Ellipse(Vector centerPt, int radius1, int radius2) { Geometry = new EllipseGeometry(centerPt.ToWindowsPt(), (double)radius1, (double)radius2); DrawMe = true; BoundingRectangle = Geometry.Bounds; CenterPoint = centerPt; }
public static bool CheckForCollisionBetweenCircleAndLine(Vector p, double r, Vector s, Vector e) { var result = false; var d = e - s; var f = s - p; var a = d ^ d; var b = 2 * f ^ d; var c = f ^ f + (-r * r); var discriminant = b * b - 4 * a * c; if (discriminant >= 0) { discriminant = Math.Sqrt(discriminant); var t1 = (-b - discriminant) / (2 * a); var t2 = (-b + discriminant) / (2 * a); if (t1 >= 0 && t1 <= 1) { result = true; } if (t2 >= 0 && t2 <= 1) { result = true; } } return result; }
public Ellipse(Vector centerPt, Tuple<int,int> radii) { Geometry = new EllipseGeometry(centerPt.ToWindowsPt(), (double)radii.Item1, (double)radii.Item2); DrawMe = true; BoundingRectangle = Geometry.Bounds; CenterPoint = centerPt; }
internal static Line Normal(Line line, Vector point) { if (line.K == 0) return new Line(0, 0); var kn = Math.Round(-1f / line.K, 1); var bn = Math.Round(point.Y - kn * point.X, 1); return new Line(kn, bn); }
public void DoAction(Game game, Player self) { var ball = game.Ball; var goal = Field.EnemyGoal.Center; if (ball.Owner == self) { var closestToGoal = goal.GetClosest(game.Enemy); if (closestToGoal.GetDistanceTo(goal) > Field.EnemyGoal.Height*0.7) { self.ActionShootGoal(); return; } var enemyToGoal = game.Enemy.Players .Where(pl => pl.Position.X > self.Position.X - 40) .Select(pl => new { pl, dist = pl.GetDistanceTo(self) }) .OrderBy(tp => tp.dist) .FirstOrDefault(); if (enemyToGoal != null && enemyToGoal.dist < 120) { self.ActionShoot(game.GetSmartShoot(self)); return; } var closestEnemy = self.GetClosest(game.Enemy); if (self.GetDistanceTo(closestEnemy) < 50) { self.ActionShoot(game.GetSmartShoot(self)); return; } self.ActionGo(goal); return; } if (Utility.TryField(game, self)) return; var centerX = goal.X*0.8; IPosition target; if (ball.Position.X > goal.X * 0.6) { var targetX = Math.Max(centerX, ball.Position.X * 0.95); var mul = ball.Position.Y < goal.Y ? 1 : -1; var targetY = goal.Y + Field.EnemyGoal.Height * 0.6 * mul; target = new Vector(targetX, targetY); } else { target = new Vector(centerX, goal.Y); } self.ActionGo(target); }
private FoodElement(Vector position) { var config = ConfigManager.Current; Position = position; Radius = config.FoodElementRadius; HealthPoints = config.FoodElementHealthPoints; }
public LineSegment(Vector start, Angle angle, double length) { this.StartingPos = start; this.magnitude = length; this.angle = angle; components.Add(magnitude * Math.Cos(angle.InRadians())); components.Add(magnitude * Math.Sin(angle.InRadians())); this.EndingPos = new Vector(StartingPos.GetX() + XComponent(), StartingPos.GetY() + YComponent()); this.slope = Slope(); }
public LineSegment(double magnitude, Angle angle, Vector midpoint) { this.magnitude = magnitude; this.angle = angle; this.StartingPos = new Vector( midpoint.GetX() - .5*magnitude *Math.Cos(angle.InRadians()), midpoint.GetY() - .5*magnitude * Math.Sin(angle.InRadians())); this.EndingPos = new Vector(midpoint.GetX() + .5 * magnitude * Math.Cos(angle.InRadians()), midpoint.GetY() + .5 * magnitude * Math.Sin(angle.InRadians())); components.Add(EndingPos.GetX() - StartingPos.GetX()); components.Add(EndingPos.GetY() - StartingPos.GetY()); }
public Angle AngleBetweenPoints(Vector CenterPoint) { Vector endPointToCenter = new LineSegment(EndingPos, CenterPoint).TranlsateToVector(); Vector incomingVector = new LineSegment(EndingPos, StartingPos).TranlsateToVector(); if ((endPointToCenter.Magnitude() * incomingVector.Magnitude() == 0)) throw new DivideByZeroException(); double cosineOfTheAngle = (incomingVector * endPointToCenter) / (endPointToCenter.Magnitude() * incomingVector.Magnitude()); if (cosineOfTheAngle > 1 || cosineOfTheAngle < -1) throw new Exception("Out of range of acos"); Angle angleToReturn = new Angle(Math.Acos(cosineOfTheAngle)); return angleToReturn; }
public Ellipse(Vector centerPt, int radius1, int radius2) { this.CenterPoint = centerPt; this.Radius1 = radius1; this.Radius2 = radius2; this.BoundingRectangle = new System.Drawing.Rectangle((int)CenterPoint.GetX() - Radius1, (int)CenterPoint.GetY() - Radius2, (int)Radius1 * 2, (int)Radius2 * 2); this.Geometry = new System.Windows.Media.EllipseGeometry(CenterPoint.AsWindowsPoint(), (double)Radius1, (double)Radius2); this.DrawMe = true; }
public LineSegment(Vector start, Vector end) { if (start.NumberOfDimensions != end.NumberOfDimensions) throw new Exception("Inconsistent dimensionalities"); this.NumberOfDimensions = start.NumberOfDimensions; this.StartingPos = start; this.EndingPos = end; components.Add(EndingPos.GetX() - StartingPos.GetX()); components.Add(EndingPos.GetY() - StartingPos.GetY()); this.angle = Angle(); this.slope = Slope(); this.magnitude = Magnitude(); }
public float GetDistanceToGoalSquared(Vector position) { // above the goal if (position.Y <= Field.MyGoal.Top.Y) { return (Field.MyGoal.Top - position).LengthSquared; } if (position.Y >= Field.MyGoal.Bottom.Y) { return (Field.MyGoal.Bottom - position).LengthSquared; } var dX = Field.Borders.X - position.X; return dX * dX; }
public static Vector GetNormalToVector(Vector pos, Vector ballPos, Vector ballDirection) { var hypotenuse = (pos - ballPos); var dotProduct = hypotenuse.Dot(ballDirection); var magnitudeH = Math.Sqrt(hypotenuse.X * hypotenuse.X + hypotenuse.Y * hypotenuse.Y); var magnituteD = Math.Sqrt(ballDirection.X * ballDirection.X + ballDirection.Y * ballDirection.Y); var cos = dotProduct / (magnitudeH * magnituteD); //var angle = Math.Acos(cos); var directionLength = hypotenuse.Length * cos; var scaledDirection = ballDirection.Unit() * directionLength; var result = (ballPos + scaledDirection) - pos; return result; }
internal void InitiateRandomWalk(Vector startingPosition = null, double stepSize = 5, int numberOfSteps = 100000) { this.numberOfSteps = numberOfSteps; startingPosition = CurrentPosition; if (startingPosition == null) { CurrentPosition = new Vector(boardBounds.Width / 2, boardBounds.Height / 2); } Vector endingPosition = null; for (stepCounter = 0; stepCounter < numberOfSteps; stepCounter++) { double angleToWalk = newDirectionGenerator(); double x2 = CurrentPosition.GetX() + stepSize * Math.Cos(angleToWalk); double y2 = CurrentPosition.GetY() + stepSize * Math.Sin(angleToWalk); endingPosition = new Vector(x2, y2); LineSegment newPath = new LineSegment(CurrentPosition, endingPosition); pathWalker(newPath, Color.Blue); testForCollisionAndAdd(newPath); } }
public Vector Shoot(Vector source, Vector target, float str) { var vector = target - source; if (vector.Length != 0) { vector.Normalize(); } str = Math.Max(0, Math.Min(Constants.PlayerMaxShootStr, str)); var d = Rnd.NextDouble(); var num2 = Rnd.NextDouble(); var num3 = Math.Sqrt(-2.0 * Math.Log(d)) * Math.Sin(Math.PI * 2.0 * num2); var num4 = ((str / Constants.PlayerMaxShootStr) * Constants.BallMaxStrStd) * num3; vector.X = (float)((vector.X * Math.Cos(num4)) - (vector.Y * Math.Sin(num4))); vector.Y = (float)((vector.X * Math.Sin(num4)) - (vector.Y * Math.Cos(num4))); var result = ((vector * str) * Constants.BallMaxVelocity) / Constants.PlayerMaxShootStr; return result; }
private Agent(World world, Vector position, Vector lookAt) { var config = ConfigManager.Current; World = world; Position = position; LookAt = lookAt; Speed = config.AgentSpeed; EyeAngle = config.AgentEyeAngle; Health = config.AgentInitialHealth; Radius = config.AgentRadius; RotationAngle = config.AgentRotationAngle; HealthFactor = config.AgentHealthFactor; AgeFactor = config.AgentAgeFactor; TickLength = config.TickLength; Brain = new Network(NUMBER_OF_INPUTS, config.NumberOfNeuronsInHiddenLayer, NUMBER_OF_OUTPUTS); }
public BasicFluid2D(int max_x, int max_y) { if (max_x != max_y) throw new ArgumentException(); this.max_x = max_x; this.max_y = max_y; u_x = new double[max_x + 1, max_y]; u_y = new double[max_x, max_y + 1]; cells = new GridCell[max_x, max_y]; A = new SparseMatrix(max_x * max_y); for (int i = 0; i < max_x; i++) for (int j = 0; j < max_y; j++) { A[i * max_x + j, i * max_x + j] = 2 + (i == 0 || i + 1 == max_x ? 1 : 0) + (j == 0 || j + 1 == max_y ? 1 : 0); if (i > 0) A[(i - 1) * max_x + j, i * max_x + j] = A[i * max_x + j, (i - 1) * max_x + j] = -1; if (j > 0) A[i * max_x + j - 1, i * max_x + j] = A[i * max_x + j, i * max_x + j - 1] = -1; if (i < max_x - 1) A[(i + 1) * max_x + j, i * max_x + j] = A[i * max_x + j, (i + 1) * max_x + j] = -1; if (j < max_y - 1) A[i * max_x + j + 1, i * max_x + j] = A[i * max_x + j, i * max_x + j + 1] = -1; cells[i, j] = new GridCell(); //cells[i, j].Adiag = (short)(2 + (i == 0 || i + 1 == max_x ? 1 : 0) + (j == 0 || j + 1 == max_y ? 1 : 0)); //cells[i, j].Aplusi = (short)(i + 1 < max_x ? -1 : 0); //cells[i, j].Aplusj = (short)(j + 1 < max_y ? -1 : 0); if (new Vector2(i - max_x / 2, j - max_y / 2).LengthSquared < max_x * max_y / 16) cells[i, j].ImplicitSurface = 5; } using (TextWriter tw = new StreamWriter("output.txt")) tw.WriteLine(A.ToMatrixString(900, 900)); solver = new MathNet.Numerics.LinearAlgebra.Double.Solvers.Preconditioners.IncompleteLU(); solver.Initialize(A); p = new DenseVector(max_x * max_y); d = new DenseVector(max_x * max_y); }
private void pathWalker(LineSegment path, Color color) { stepCounter++; if (color == null) color = Color.Brown; printToBoard(path, color); fullPathWalked.Add(path); CurrentPosition = path.EndingPos; }
public static bool CheckForCollisionBetweenCircles(Vector p1, double r1, Vector p2, double r2) { return (p2.X - p1.X).Sqr() + (p1.Y - p2.Y).Sqr() <= (r1 + r2).Sqr(); }
private static bool MightCatch(Vector oppoVector, Vector targetVector, float power, float z) { var accuracy = Statistics.GetAccuracy(power, z); return Math.Abs(Theta.Create(oppoVector, targetVector)) < accuracy; }
public void Action(Team myTeam, Team enemyTeam, Ball ball, MatchInfo matchInfo) { foreach (Player player in myTeam.Players) { Player closestEnemy = player.GetClosest(enemyTeam); switch (player.PlayerType) { case PlayerType.Keeper: if (ball.Owner == player) { var partner = player.GetClosestUncovered(myTeam, enemyTeam); if (partner != null) { var power = player.GetDistanceTo(partner) / 10; player.ActionShoot(partner, power); continue; } else { // todo: shoot just to enemy side player.ActionShootGoal(); continue; } } if (player.GetDistanceTo(ball) < 50 && player.CanPickUpBall(ball)) { player.ActionPickUpBall(); continue; } if (ball.GetClosest(myTeam) == player && ball.GetClosest(enemyTeam).GetDistanceTo(ball) < player.GetDistanceTo(ball) && ball.GetDistanceTo(Field.MyGoal.Center) < 400) { player.ActionGo(ball.Position); continue; } var direction = GoalKeeper.ChooseDirection(player, ball); player.ActionGo(direction); continue; default: if (ball.Owner == player) if (player.GetDistanceTo(Field.EnemyGoal.Center) > 400) { var inters = player.GetClosestInterceptors(enemyTeam, 400); if (!inters.Any()) { player.ActionGo(Field.EnemyGoal.Center); continue; } else if (inters.Count() >= 3) { var partner = player.GetClosestUncovered(myTeam, enemyTeam); if (partner != null) player.ActionShoot(partner, 100); } var goalDirect = (Field.EnemyGoal.Center - player.Position).GetDirection(); var direct = (from i in inters select (i.Velocity) + (player.Position - i.Position).GetDirection() * (1 - i.GetDistanceTo(player) / 500)) .Aggregate(Vector.Zero, (acc, v) => acc + v).GetDirection() + goalDirect; var dest = player.Position + direct; //if (direct.X < -50 && partner != null) //{ // player.ActionShoot(partner, 100); // continue; //} //else // if (dest.Y < Field.Borders.Top.Y + 200 // || dest.Y > Field.Borders.Bottom.Y - 200) //{ // player.ActionGo(dest + goalDirect * 2); // continue; //} //else // if (dest.X > Field.Borders.Right.X - 100) //{ // player.ActionGo(Field.Borders.Center); // continue; //} //else //if (Field.Borders.Contains(dest)) //{ player.ActionGo(dest); continue; //} //else //{ // player.ActionGo(Field.EnemyGoal.Center); // continue; //} } else { //var goalkepers = from ep in enemyTeam.InFrontOf(player) // ; player.ActionShootGoal(); } break; } if (ball.Owner == player) //Allways shoots for the enemy goal. { } else if (player.CanPickUpBall(ball)) //Picks up the ball if posible. player.ActionPickUpBall(); else if (player.CanTackle(closestEnemy) && ball.Owner == closestEnemy) //Tackles any enemy that is close. player.ActionTackle(closestEnemy); else if (player == ball.GetClosest(myTeam)) //If the player is closest to the ball, go for it. { var balldirect = ball.Velocity.GetDirection(); var ndirect = new Vector(-balldirect.Y, balldirect.X); var direct = (ball.Position - player.Position).GetDirection() * 10; if (direct.Length < 50) player.ActionGo(ball); else player.ActionGo(direct + ndirect); } else if (player.CanTackle(closestEnemy)) //Tackles any enemy that is close. player.ActionTackle(closestEnemy); else //If the player cannot do anything urgently usefull, move to a good position. { if (player.PlayerType == PlayerType.Keeper) //The keeper protects the goal. { } //The keeper positions himself 50 units out from the goal //at the same height as the ball, although never leaving the goal else if (player.PlayerType == PlayerType.LeftDefender) player.ActionGo(new Vector(Field.Borders.Width * 0.2, ball.Position.Y)); //The left defender helps protect the goal else if (player.PlayerType == PlayerType.RightDefender) player.ActionGo(Field.MyGoal.GetClosest(enemyTeam)); //The right defender chases the enemy closest to myGoal else if (player.PlayerType == PlayerType.RightForward) player.ActionGo((Field.Borders.Center + Field.Borders.Bottom + ball.Position) / 3); //Right forward stays in position on the midline, untill the ball comes close. else if (player.PlayerType == PlayerType.LeftForward) player.ActionGo((Field.Borders.Center + Field.Borders.Top + ball.Position) / 3); //Left forward stays in position on the midline, untill the ball comes close. else if (player.PlayerType == PlayerType.CenterForward) player.ActionGo((Field.Borders.Center + Field.EnemyGoal.Center + ball.Position) / 3); //Center forward stays in position on the enemy side of the field. } } }
/// <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="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); }
internal static double B0(Vector p2, Vector p1) { return Math.Round(p2.Y - K0(p2, p1) * p2.X, 1); }
internal static double K0(Vector p2, Vector p1) { if (p2.X - p1.X == 0) return 0; return Math.Round((p2.Y - p1.Y) / (p2.X - p1.X), 1); }
/// <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; }
internal static Line One(Vector p2, Vector p1) { return new Line(K0(p2, p1), B0(p2, p1)); }
/// <summary> /// 指定時間後の打球のボール位置を取得する /// </summary> /// <param name="battedBoll">打球</param> /// <param name="fitureSecond">指定時間</param> /// <param name="fenseReflect">フェンスに当たったか</param> /// <param name="fenseOver">フェンスを超えたか</param> /// <returns>ボール位置</returns> private MPoint GetFitureBollPoint(BattedBoll battedBoll, int fitureSecond, out bool fenseReflect, out bool fenseOver) { fenseReflect = false; fenseOver = false; double bollSpeed = battedBoll.Speed; MPoint fitureBollPoint = GameData.BollPoint; for (int second = 0; second < fitureSecond; second++) { Vector fitureMove = new Vector(bollSpeed * Math.Sin(battedBoll.SideDirection * Math.PI / 180), bollSpeed * Math.Cos(battedBoll.SideDirection * Math.PI / 180)); // ゴロかフライか bool isFly = GameData.RemainingDropTime - second >= 0; // フェンスの補正 fitureBollPoint = ChangePointByFense(fitureBollPoint, fitureMove, isFly, out fenseReflect, out fenseOver); // 打球速度の減速 bollSpeed = GetBollSpeed(isFly, GameData.DefenseTermPassedSecond + second, fitureBollPoint, bollSpeed); if (isFly) { // フライの場合 // フェンスを超えたらその時点の位置を返す // (ゴロになるまで計算するとフェンスに跳ね返る可能性があるため) if (fenseOver) { return fitureBollPoint; } } else { // ゴロの場合 // フェンスに当たった場合は速度0になるため、その時点の位置を返す if (fenseReflect) { return fitureBollPoint; } } } return fitureBollPoint; }
public void DoAction(Game game, Player self) { var ball = game.Ball; var goal = Field.EnemyGoal.Center; if (ball.Owner == self) { var closestToGoal = goal.GetClosest(game.Enemy); if (closestToGoal.GetDistanceTo(goal) > Field.EnemyGoal.Height * 0.8) { self.ActionShootGoal(); return; } var enemyToGoal = game.Enemy.Players .Where(pl => pl.Position.X > self.Position.X - 40) .Select(pl => new { pl, dist = pl.GetDistanceTo(self) }) .OrderBy(tp => tp.dist) .FirstOrDefault(); if (enemyToGoal != null && enemyToGoal.dist < 120) { self.ActionShoot(game.GetSmartShoot(self)); return; } var closestEnemy = self.GetClosest(game.Enemy); if (self.GetDistanceTo(closestEnemy) < 50) { self.ActionShoot(game.GetSmartShoot(self)); return; } self.ActionGo(Field.EnemyGoal.Bottom); return; } if (Utility.TryField(game, self)) return; IPosition target; if (game.InAttack) { if (ball.Position.X > goal.X * 0.6) { var centerX = goal.X * 0.82; var targetX = Math.Max(centerX, ball.Position.X * 0.95); var targetY = goal.Y - Field.EnemyGoal.Height * 0.75; target = new Vector(targetX, targetY); } else { target = new Vector(Field.Borders.Bottom.X, Field.MyGoal.Height * 0.7); } } else { var closestUpperPlayers = game.Enemy.Players .Where(pl => pl.Position.Y < Field.Borders.Center.Y) .Select(pl => new {pl, dist = pl.GetDistanceTo(Field.MyGoal.Top)}) .OrderBy(tp => tp.dist); if (closestUpperPlayers.Count() > 1) { target = closestUpperPlayers.Skip(1).First().pl; } else { target = new Vector(Field.Borders.Top.X, Field.MyGoal.Height * 0.7); } } self.ActionGo(target); }
/// <summary> /// 送球中のボール位置更新 /// </summary> private void MoveThrowBoll() { // 送球中のボール位置更新 Vector totalMove = ThrowTargetPoint - ThrowStartPoint; Vector bollMove = new Vector(totalMove.X * GameData.DefenseTermPassedSecond / ThrowReachTime, totalMove.Y * GameData.DefenseTermPassedSecond / ThrowReachTime); GameData.BollPoint = ThrowStartPoint + bollMove; // 送球完了したか if (GameData.DefenseTermPassedSecond >= ThrowReachTime) { // 送球完了 // ボール保持メンバの更新 GameData.BollKeepingPosition = GetBaseCoverPosition(ThrowTargetBase); // 送球完了によるフォースアウトとタッチアウトの処理 UpdateByThrowFinish(ThrowTargetBase); } }