private MoveResult MoveDiscoids() { if (!started) return null; MoveResult moveResult = new MoveResult() { DiscoidPositions = new List<DiscoidPosition>(), IsTurnOver = false }; //Flag indicating that the program is still calculating //the positions, that is, the balls are still in an inconsistent state. calculatingPositions = true; foreach (Discoid discoid in discoids) { if (Math.Abs(discoid.Position.X) < 5 && Math.Abs(discoid.Position.Y) < 5 && Math.Abs(discoid.TranslateVelocity.X) < 10 && Math.Abs(discoid.TranslateVelocity.Y) < 10) { discoid.Position.X = discoid.Position.Y = 0; discoid.TranslateVelocity = new Vector2D(0, 0); } } bool conflicted = true; //process this loop as long as some balls are still colliding while (conflicted) { conflicted = false; bool someCollision = true; while (someCollision) { foreach (Goal goal in goals) { bool inGoal = goal.IsBallInGoal(ball); } someCollision = false; foreach (Discoid discoidA in discoids) { if (discoidA is Player) { if (!((Player)discoidA).IsPlaying) break; } //Resolve collisions between balls and each of the 6 borders in the table RectangleCollision borderCollision = RectangleCollision.None; foreach (TableBorder tableBorder in tableBorders) { borderCollision = tableBorder.Colliding(discoidA); //if (borderCollision != RectangleCollision.None && !discoidA.IsBallInGoal) if (borderCollision != RectangleCollision.None) { someCollision = true; tableBorder.ResolveCollision(discoidA, borderCollision); } } //Resolve collisions between players foreach (Discoid discoidB in discoids) { if (discoidB is Player) { if (!((Player)discoidB).IsPlaying) break; } if (discoidA != discoidB) { //if (discoidA.Colliding(discoidB) && !discoidA.IsBallInGoal && !discoidB.IsBallInGoal) if (discoidA.Colliding(discoidB)) { if ((discoidA is Player && discoidB is Ball) || (discoidB is Player && discoidA is Ball)) { Player p = null; Ball b = null; if (discoidA is Player) { p = (Player)discoidA; b = (Ball)discoidB; } else { p = (Player)discoidB; b = (Ball)discoidA; } turnEvents.Add(new PlayerToBallContact(currentGame.PlayingTeamID, p, new Point(ball.Position.X, ball.Position.Y))); } else if (discoidA is Player && discoidB is Player) { if ( (((Player)discoidA).Team.TeamID != currentGame.PlayingTeamID) || ((Player)discoidB).Team.TeamID != currentGame.PlayingTeamID) { PlayerToPlayerContact p2p = new PlayerToPlayerContact(currentGame.PlayingTeamID, (Player)discoidA, (Player)discoidB, new Point(discoidA.Position.X, discoidA.Position.Y)); var q = from te in turnEvents where te is PlayerToBallContact where ((PlayerToBallContact)te).Player.Team.TeamID == currentGame.PlayingTeamID select te; if (!q.Any()) { turnEvents.Add(p2p); Player p = null; if (((Player)discoidA).Team.TeamID == currentGame.PlayingTeamID) { p = (Player)discoidA; } else { p = (Player)discoidB; } } } } if (discoidA.Points == 0) { strokenPlayers.Add(discoidB); } else if (discoidB.Points == 0) { strokenPlayers.Add(discoidA); } while (discoidA.Colliding(discoidB)) { someCollision = true; discoidA.ResolveCollision(discoidB); } } } } //Calculate ball's translation velocity (movement) as well as the spin velocity. //The friction coefficient is used to decrease ball's velocity if (discoidA.TranslateVelocity.X != 0.0d || discoidA.TranslateVelocity.Y != 0.0d) { double signalXVelocity = discoidA.TranslateVelocity.X >= 0.0f ? 1.0f : -1.0f; double signalYVelocity = discoidA.TranslateVelocity.Y >= 0.0f ? 1.0f : -1.0f; double absXVelocity = Math.Abs(discoidA.TranslateVelocity.X); double absYVelocity = Math.Abs(discoidA.TranslateVelocity.Y); Vector2D absVelocity = new Vector2D(absXVelocity, absYVelocity); Vector2D normalizedDiff = new Vector2D(absVelocity.X, absVelocity.Y); normalizedDiff.Normalize(); absVelocity.X = absVelocity.X * (1.0f - discoidA.Friction) - normalizedDiff.X * discoidA.Friction; absVelocity.Y = absVelocity.Y * (1.0f - discoidA.Friction) - normalizedDiff.Y * discoidA.Friction; if (absVelocity.X < 0f) absVelocity.X = 0f; if (absVelocity.Y < 0f) absVelocity.Y = 0f; double vx = absVelocity.X * signalXVelocity; double vy = absVelocity.Y * signalYVelocity; if (double.IsNaN(vx)) vx = 0; if (double.IsNaN(vy)) vy = 0; discoidA.TranslateVelocity = new Vector2D(vx, vy); } //Calculate ball's translation velocity (movement) as well as the spin velocity. //The friction coefficient is used to decrease ball's velocity if (discoidA.VSpinVelocity.X != 0.0d || discoidA.VSpinVelocity.Y != 0.0d) { double signalXVelocity = discoidA.VSpinVelocity.X >= 0.0f ? 1.0f : -1.0f; double signalYVelocity = discoidA.VSpinVelocity.Y >= 0.0f ? 1.0f : -1.0f; double absXVelocity = Math.Abs(discoidA.VSpinVelocity.X); double absYVelocity = Math.Abs(discoidA.VSpinVelocity.Y); Vector2D absVelocity = new Vector2D(absXVelocity, absYVelocity); Vector2D normalizedDiff = new Vector2D(absVelocity.X, absVelocity.Y); normalizedDiff.Normalize(); absVelocity.X = absVelocity.X - normalizedDiff.X * discoidA.Friction / 1.2f; absVelocity.Y = absVelocity.Y - normalizedDiff.Y * discoidA.Friction / 1.2f; if (absVelocity.X < 0f) absVelocity.X = 0f; if (absVelocity.Y < 0f) absVelocity.Y = 0f; discoidA.VSpinVelocity = new Vector2D(absVelocity.X * signalXVelocity, absVelocity.Y * signalYVelocity); } } //Calculate the ball position based on both the ball's translation velocity and vertical spin velocity. foreach (Discoid discoid in discoids) { discoid.Position.X += discoid.TranslateVelocity.X + discoid.VSpinVelocity.X; discoid.Position.Y += discoid.TranslateVelocity.Y + discoid.VSpinVelocity.Y; } } conflicted = false; } double totalVelocity = 0; foreach (Discoid discoid in discoids) { totalVelocity += discoid.TranslateVelocity.X; totalVelocity += discoid.TranslateVelocity.Y; } calculatingPositions = false; bool isTurnOver = false; if (Math.Abs(totalVelocity) < 0.005 && Math.Abs(lastTotalVelocity) > 0) { totalVelocity = 0; foreach(Discoid d in discoids) { d.TranslateVelocity = new Vector2D(0, 0); } //MoveDiscoids(); //poolState = PoolState.AwaitingShot; if (!goals[0].IsBallInGoal(ball) && !goals[1].IsBallInGoal(ball)) { ball.IsBallInGoal = false; } if (Math.Abs(lastTotalVelocity) > 0 && hasPendingGoalResolution) { //ResetPlayerPositions(currentGame.Teams[currentGame.Team1ID], currentGame.Teams[currentGame.Team2ID], rootCanvas, discoids, goalPost00Point.X, goalPost10Point.X, rowTopEscapeArea.Height.Value, fieldHeight - rowTopEscapeArea.Height.Value); //ball.X = (goalPost00Point.X + goalPost10Point.X) / 2; //ball.Y = (rowTopEscapeArea.Height.Value + fieldHeight - rowTopEscapeArea.Height.Value) / 2; } ProcessAfterTurn(); isTurnOver = true; GameHelper.Instance.IsMovingDiscoids = false; if (scoreControl.Time > totalTime) { Team selectedTeam = currentGame.Team1; currentGame = GetNextGame(selectedTeamID, currentGame.Date); LoadPlayerFaces(); ResetPlayerPositions(currentGame.Teams[currentGame.Team1ID], currentGame.Teams[currentGame.Team2ID], rootCanvas, discoids, goalPost00Point.X, goalPost10Point.X, rowTopEscapeArea.Height.Value, fieldHeight - rowTopEscapeArea.Height.Value); scoreControl.Team1Name = currentGame.Team1ID; scoreControl.Team1Score = currentGame.Scores[currentGame.Team1ID]; scoreControl.Team2Name = currentGame.Team2ID; scoreControl.Team2Score = currentGame.Scores[currentGame.Team2ID]; scoreControl.PlayingTeamID = currentGame.PlayingTeamID; scoreControl.Time = new DateTime(1, 1, 1, 0, 0, 1); ball.ResetPosition(); bf.SetValue(Canvas.LeftProperty, ball.Position.X - ball.Radius); bf.SetValue(Canvas.TopProperty, ball.Position.Y - ball.Radius); } } lastTotalVelocity = totalVelocity; //playerPositionList = GetBallPositionList(); return new MoveResult() { DiscoidPositions = moveResult.DiscoidPositions, IsTurnOver = isTurnOver }; }
public MainPage(Dictionary<string, object> parameters) : base(parameters) { InitializeComponent(); GameHelper.Instance.IsMovingDiscoids = false; clockTimer.Tick += new EventHandler(clockTimer_Tick); clockTimer.Interval = new TimeSpan(0, 0, 0, 1, 0); movementTimer.Tick += new EventHandler(movementTimer_Tick); movementTimer.Interval = new TimeSpan(0, 0, 0, 0, 10); movementTimer.Start(); clockTimer.Start(); groups = GameHelper.Instance.Groups; teamsDictionary = GameHelper.Instance.TeamsDictionary; LoadTeamPlayers(teamPlayers); LoadGameTable(gameTable); selectedTeamID = Parameters["TeamID1"].ToString(); DateTime lastGameDate = new DateTime(2010,06,01); LoadBall(); currentGame = GetNextGame(selectedTeamID, lastGameDate); strengthPointNW = new Point ( this.colLeftEscapeArea.Width.Value + this.colLeftPosts.Width.Value + this.colLeftGoalArea.Width.Value + this.colLeftPenaltyArea.Width.Value + this.colHalfWay.Width.Value + this.colRightPenaltyArea.Width.Value + this.colRightGoalArea.Width.Value + this.colRightPosts.Width.Value, this.rowTopEscapeArea.Height.Value + this.rowTopFieldLine.Height.Value + this.rowTopPenaltyArea.Height.Value + this.rowTopGoalArea.Height.Value ); strengthPointSE = new Point ( strengthPointNW.X + colMenu.Width.Value, strengthPointNW.Y + rowBottomGoalArea.Height.Value + rowBottomPenaltyArea.Height.Value ); fieldWidth = this.colLeftEscapeArea.Width.Value + this.colLeftPosts.Width.Value + this.colLeftGoalArea.Width.Value + this.colLeftPenaltyArea.Width.Value + this.colHalfWay.Width.Value + this.colRightPenaltyArea.Width.Value + this.colRightGoalArea.Width.Value + this.colRightPosts.Width.Value; fieldHeight = this.rowTopEscapeArea.Height.Value + this.rowTopFieldLine.Height.Value + this.rowTopPenaltyArea.Height.Value + this.rowTopGoalArea.Height.Value + this.rowBottomGoalArea.Height.Value + this.rowBottomPenaltyArea.Height.Value + this.rowBottomFieldLine.Height.Value; goalPost00Point = new Point( this.colLeftEscapeArea.Width.Value, this.rowTopEscapeArea.Height.Value + this.rowTopFieldLine.Height.Value + this.rowTopPenaltyArea.Height.Value); goalPost01Point = new Point(goalPost00Point.X, goalPost00Point.Y + rowTopGoalArea.Height.Value); goalPost10Point = new Point( this.colLeftEscapeArea.Width.Value + this.colLeftPosts.Width.Value + this.colLeftGoalArea.Width.Value + this.colLeftPenaltyArea.Width.Value + this.colHalfWay.Width.Value + this.colRightPenaltyArea.Width.Value + this.colRightGoalArea.Width.Value, goalPost00Point.Y); goalPost11Point = new Point(goalPost10Point.X, goalPost10Point.Y + rowTopGoalArea.Height.Value); discoids.Add(new GoalPost(new Vector2D(goalPost00Point.X, goalPost00Point.Y), new Vector2D(8, 8), "1001")); discoids.Add(new GoalPost(new Vector2D(goalPost01Point.X, goalPost01Point.Y), new Vector2D(8, 8), "1002")); discoids.Add(new GoalPost(new Vector2D(goalPost10Point.X, goalPost10Point.Y), new Vector2D(8, 8), "1003")); discoids.Add(new GoalPost(new Vector2D(goalPost11Point.X, goalPost11Point.Y), new Vector2D(8, 8), "1004")); goals.Add(new Goal(this, 1, new Point(0, goalPost00Point.Y), goalPost00Point, new Point(0, goalPost01Point.Y), goalPost01Point)); goals.Add(new Goal(this, 2, goalPost10Point, new Point(goalPost10Point.X + colRightGoalArea.Width.Value, goalPost10Point.Y), goalPost11Point, new Point(goalPost11Point.X + colRightGoalArea.Width.Value, goalPost11Point.Y))); ball = new Ball(new Vector2D(550, 310), new Vector2D(36, 36), "9"); ball.X = (goalPost00Point.X + goalPost10Point.X) / 2; ball.Y = (rowTopEscapeArea.Height.Value + fieldHeight - rowTopEscapeArea.Height.Value) / 2; rootCanvas.Children.Add(bf); discoids.Add(ball); LoadPlayerFaces(); ResetPlayerPositions(currentGame.Teams[currentGame.Team1ID], currentGame.Teams[currentGame.Team2ID], rootCanvas, discoids, goalPost00Point.X, goalPost10Point.X, rowTopEscapeArea.Height.Value, fieldHeight - rowTopEscapeArea.Height.Value); LayoutRoot.Background = new ImageBrush() { ImageSource = new BitmapImage(new Uri("../Images/Grass.png", UriKind.Relative)) }; tableBorders.Add(new TableBorder(0, -20, (int)fieldWidth, 20)); tableBorders.Add(new TableBorder(0, (int)fieldHeight, (int)fieldWidth, 200)); tableBorders.Add(new TableBorder(-20, 0, 20, (int)fieldHeight)); tableBorders.Add(new TableBorder((int)fieldWidth, 0, 20, (int)fieldHeight)); tableBorders.Add(new TableBorder(0, (int)goalPost00Point.Y, (int)colLeftEscapeArea.Width.Value, 10)); tableBorders.Add(new TableBorder(0, (int)goalPost01Point.Y, (int)colLeftEscapeArea.Width.Value, 10)); tableBorders.Add(new TableBorder((int)goalPost10Point.X, (int)goalPost10Point.Y, (int)colRightPosts.Width.Value, 10)); tableBorders.Add(new TableBorder((int)goalPost11Point.X, (int)goalPost11Point.Y, (int)colRightPosts.Width.Value, 10)); scoreControl.SetValue(Grid.ColumnProperty, 1); scoreControl.SetValue(Grid.RowProperty, 0); scoreControl.SetValue(Grid.ColumnSpanProperty, 3); scoreControl.SetValue(Grid.RowSpanProperty, 1); LayoutRoot.Children.Add(scoreControl); scoreControl.Team1Name = currentGame.Team1ID; scoreControl.Team1Score = currentGame.Scores[currentGame.Team1ID]; scoreControl.Team2Name = currentGame.Team2ID; scoreControl.Team2Score = currentGame.Scores[currentGame.Team2ID]; scoreControl.PlayingTeamID = currentGame.PlayingTeamID; this.Background = new SolidColorBrush(Colors.Black); sbStadiumScreen = new Storyboard() { Duration = new Duration(new TimeSpan(0, 0, 0, 10)) }; DoubleAnimation translateAnimation = new DoubleAnimation() { From = 800, To = 0, Duration = new Duration(new TimeSpan(0, 0, 0, 3)) }; Storyboard.SetTarget(translateAnimation, lettersXTranslate); Storyboard.SetTargetProperty(translateAnimation, new PropertyPath("X")); DoubleAnimation lettersOpacityAnimation = new DoubleAnimation() { From = 0.8, To = 1.0, Duration = new Duration(new TimeSpan(0, 0, 0, 0, 500)), AutoReverse = true, RepeatBehavior = RepeatBehavior.Forever }; Storyboard.SetTarget(lettersOpacityAnimation, grdBrightness); Storyboard.SetTargetProperty(lettersOpacityAnimation, new PropertyPath("Opacity")); DoubleAnimation screenOpacityAnimation = new DoubleAnimation() { From = 1.0, To = 0.0, BeginTime = new TimeSpan(0, 0, 0, 0), Duration = new Duration(new TimeSpan(0, 0, 0, 4)) }; sbStadiumScreen.Children.Add(translateAnimation); sbStadiumScreen.Children.Add(lettersOpacityAnimation); sbStadiumScreen.Children.Add(screenOpacityAnimation); Storyboard.SetTarget(screenOpacityAnimation, grdStadiumScreen); Storyboard.SetTargetProperty(screenOpacityAnimation, new PropertyPath("Opacity")); Storyboard sbBallStrength = new Storyboard() { RepeatBehavior = RepeatBehavior.Forever }; DoubleAnimation ballStrengthAngle = new DoubleAnimation() { From = 0.0, To = 360, Duration = new Duration(new TimeSpan(0, 0, 0, 3, 0)), RepeatBehavior = RepeatBehavior.Forever }; sbBallStrength.Children.Add(ballStrengthAngle); Storyboard.SetTarget(ballStrengthAngle, rtBallStrength); Storyboard.SetTargetProperty(ballStrengthAngle, new PropertyPath("Angle")); sbBallStrength.Begin(); }