public IEnumerator ActualTimeToContactAndInitialRadiusOfBallIsRandom() { ISet <float> actualTimesToContact = new HashSet <float>(); ISet <float> ballInitialRadiuses = new HashSet <float>(); foreach (var _ in Enumerable.Range(1, CatchTheBall.NUMBER_OF_ROUNDS)) { // Wait for soccer player to load, kick ball, and then ball to be spawned yield return(new WaitUntil(() => Object.FindObjectOfType <SoccerPlayer>() != null)); SoccerPlayer soccerPlayer = Object.FindObjectOfType <SoccerPlayer>(); yield return(new WaitUntil(() => soccerPlayer.PlayerHasKickedBall())); yield return(new WaitUntil(() => Object.FindObjectOfType <BallProjectile>() != null)); BallProjectile ball = Object.FindObjectOfType <BallProjectile>(); actualTimesToContact.Add(ball.ActualTimeToContact); ballInitialRadiuses.Add(ball.BallInitialRadius); Press(keyboard.aKey); } int numberOfUniqueActualTimesToContact = actualTimesToContact.Count; int numberOfUniqueBallInitialRadiuses = ballInitialRadiuses.Count; Assert.AreNotEqual(1, numberOfUniqueActualTimesToContact); Assert.AreNotEqual(1, numberOfUniqueBallInitialRadiuses); }
public IEnumerator WHEN_BallsKicked_THEN_BallPositionsDoNotChange() { // Wait for soccer player to load, kick ball, and then ball to be spawned yield return(new WaitUntil(() => Object.FindObjectOfType <SoccerPlayer>() != null)); SoccerPlayer soccerPlayer = Object.FindObjectOfType <SoccerPlayer>(); yield return(new WaitUntil(() => soccerPlayer.PlayerHasKickedBall())); yield return(new WaitUntil(() => Object.FindObjectOfType <BallProjectile>() != null)); BallProjectile[] balls = Object.FindObjectsOfType <BallProjectile>(); BallProjectile ball1 = balls[0]; BallProjectile ball2 = balls[1]; float endingTime = Time.time + Math.Max(ball1.ActualTimeToContact, ball2.ActualTimeToContact); float currentTime = Time.time; Vector3 ball1StartingPosition = ball1.transform.position; Vector3 ball2StartingPosition = ball2.transform.position; // For every frame before the last ball arrives, their positions should be // unchanged. while (endingTime - currentTime > 0) { Assert.AreEqual(ball1StartingPosition, ball1.transform.position); Assert.AreEqual(ball2StartingPosition, ball2.transform.position); yield return(new WaitForSeconds(0.05f)); currentTime = Time.time; } }
public IEnumerator WHEN_BallKicked_THEN_BallPositionDoesNotChange() { // Wait for soccer player to load, kick ball, and then ball to be spawned yield return(new WaitUntil(() => Object.FindObjectOfType <SoccerPlayer>() != null)); SoccerPlayer soccerPlayer = Object.FindObjectOfType <SoccerPlayer>(); yield return(new WaitUntil(() => soccerPlayer.PlayerHasKickedBall())); yield return(new WaitUntil(() => Object.FindObjectOfType <BallProjectile>() != null)); BallProjectile ball = Object.FindObjectOfType <BallProjectile>(); Vector3 startingPosition = ball.transform.position; float endingTime = Time.time + ball.ActualTimeToContact; float currentTime = Time.time; // For every frame before the ball arrives, its position should be // unchanged. while (endingTime - currentTime > 0) { Assert.AreEqual(startingPosition, ball.transform.position); yield return(new WaitForSeconds(0.05f)); currentTime = Time.time; } }
public void ThrowBall() { if (_enemyTarget && _isHoldingBall) { if (Vector3.Distance(_holdPosition.position, _enemyTarget.transform.position) < Vector3.Distance(_secondaryThrowPosition.position, _enemyTarget.transform.position)) { // hold ball in hold position _currentBallTarget.transform.position = _holdPosition.position; } else { // hold ball in secondary position _currentBallTarget.transform.position = _secondaryThrowPosition.position; } // get referemce to ball script BallProjectile currentBall = _currentBallTarget.GetComponent <BallProjectile>(); //currentBall.SetIsHeld(false); // determining accuracy float accuracy = Random.Range(0.6f, 1.4f); currentBall._lastThrower = this; currentBall.ThrowBall(_enemyTarget.gameObject.GetComponent <BasicVelocity>(), accuracy); _isHoldingBall = false; _currentBallTarget = null; //ScanForObjects(); } }
public IEnumerator BallMovesAtConstantVelocity() { // Wait for soccer player to load, kick ball, and then ball to be spawned yield return(new WaitUntil(() => Object.FindObjectOfType <SoccerPlayer>() != null)); SoccerPlayer soccerPlayer = Object.FindObjectOfType <SoccerPlayer>(); yield return(new WaitUntil(() => soccerPlayer.PlayerHasKickedBall())); yield return(new WaitUntil(() => Object.FindObjectOfType <BallProjectile>() != null)); BallProjectile ball = Object.FindObjectOfType <BallProjectile>(); Vector3 startingPosition = ball.transform.position; float endingTime = Time.time + ball.ActualTimeToContact; float currentTime = Time.time; // For every frame before the ball arrives, its position should be // unchanged. List <double> ballScales = new List <double>(); while (endingTime - currentTime > 0) { ballScales.Add(ball.transform.localScale.x); yield return(new WaitForSeconds(0.05f)); currentTime = Time.time; } // Utility method for calculating standard deviation // Credit: https://stackoverflow.com/a/6252351 double StandardDeviation(IEnumerable <double> values) { double avg = values.Average(); return(Math.Sqrt(values.Average(v => Math.Pow(v - avg, 2)))); } // Find the absolute difference between two any // ball scales. IEnumerable <double> ballScaleDifferences = Enumerable.Zip(ballScales, ballScales.Skip(1), (x1, x2) => Math.Abs(x2 - x1)); // If the data is linear, then // (ballScale(i+1) - ballScale(i)) = (ballScale(j+1) - ballScale(j)) // for any frame i and j. Thus, we can take the standard deviation // of the ball scale differences. If it is close to 0, then // the ball scale differences are all almost the same, thus indicating // a linear relationship. double standardDeviation = StandardDeviation(ballScaleDifferences); // Check if the standard deviation is equal to 0 with a possible error // of ± 0.1. Assert.AreEqual(0, standardDeviation, 0.1); }
// Start is called before the first frame update private void Awake() { if (instance != null) { Destroy(instance); } else { instance = this; } }
/// <summary> /// Instantiates a ball projectile that will appear to approach the player. /// </summary> /// <param name="ballPosition">The position of the ball in the scene.</param> /// <param name="targetRingRadius">The radius of the target ring, which /// also serves as the final radius of the ball.</param> /// <param name="ballInitialRadius">The radius of the ball before /// it has been "kicked".</param> /// <param name="actualTimeToContact">How long it actually takes /// the ball to reach the target ring from its original radius.</param> /// <param name="ballTimeBeforeDisappearance">The duration of time before the ball /// disappears from the screen.</param> /// <returns>The instantiated ball projectile with the given parameters.</returns> public BallProjectile InstantiateBallProjectile(Vector3 ballPosition, float targetRingRadius, float ballInitialRadius, float actualTimeToContact, float?ballTimeBeforeDisappearance) { BallProjectile ballProjectile = Instantiate(BallProjectilePrefab, ballPosition, Quaternion.identity, gameObject.GetComponent <Canvas>().transform) .GetComponent <BallProjectile>(); ballProjectile.TargetRingRadius = targetRingRadius; ballProjectile.BallInitialRadius = ballInitialRadius; ballProjectile.ActualTimeToContact = actualTimeToContact; ballProjectile.BallTimeBeforeDisappearance = ballTimeBeforeDisappearance; return(ballProjectile); }
public override IEnumerator StartRound() { BallRound ballRound = GenerateDataForRound(ballStorage.TargetRadius); Vector3 leftBallPosition = LeftTargetRing.transform.position; Vector3 rightBallPosition = RightTargetRing.transform.position; SoccerPlayer leftSoccerPlayer = InstantiateSoccerPlayer(leftBallPosition, ballRound.InitialLeftBallRadius); SoccerPlayer rightSoccerPlayer = InstantiateSoccerPlayer(rightBallPosition, ballRound.InitialRightBallRadius); yield return(new WaitUntil(() => leftSoccerPlayer.PlayerHasKickedBall() && rightSoccerPlayer.PlayerHasKickedBall() )); BallProjectile leftBallProjectile = InstantiateBallProjectile(leftBallPosition, ballStorage.TargetRadius, ballRound.InitialLeftBallRadius, ballRound.LeftActualTimeToContact, // Ball doesn't disappear in Save One Ball ballTimeBeforeDisappearance: null ); BallProjectile rightBallProjectile = InstantiateBallProjectile(rightBallPosition, ballStorage.TargetRadius, ballRound.InitialRightBallRadius, ballRound.RightActualTimeToContact, // Ball doesn't disappear in Save One Ball ballTimeBeforeDisappearance: null ); // Record the time at which the "kick" takes place float beginTime = Time.time; // Make round end when the user hits any // key, or when they have waited too long (2 times the actual // time to contact) yield return(StartCoroutine( WaitForInputOrTimeExpires( beginTime: beginTime, maxTimeToWait: 2 * Math.Min(ballRound.LeftActualTimeToContact, ballRound.RightActualTimeToContact), inputReceived: () => Keyboard.current[LEFT_BALL_KEY].isPressed || Keyboard.current[RIGHT_BALL_KEY].isPressed, ballProjectiles: new List <BallProjectile> { leftBallProjectile, rightBallProjectile }, ballRound: ballRound ) )); }
public override IEnumerator StartRound() { BallRound ballRound = GenerateDataForRound(ballStorage.TargetRadius); // The ball is at the centre of the screen in this round Vector3 ballPosition = new Vector3(0, 0, 0); SoccerPlayer soccerPlayer = InstantiateSoccerPlayer(ballPosition, ballRound.InitialBallRadius); yield return(new WaitUntil(() => soccerPlayer.PlayerHasKickedBall())); BallProjectile ballProjectile = InstantiateBallProjectile(ballPosition, ballStorage.TargetRadius, ballRound.InitialBallRadius, ballRound.ActualTimeToContact, // Balls don't disappear in Catch The Ball ballTimeBeforeDisappearance: null); // Record the time at which the "kick" takes place float beginTime = Time.time; // Make round end when the user hits any // key, or when they have waited too long (2 times the actual // time to contact) yield return(StartCoroutine( WaitForInputOrTimeExpires( beginTime: beginTime, maxTimeToWait: 2 * ballRound.ActualTimeToContact, inputReceived: () => Keyboard.current.anyKey.isPressed, ballProjectiles: new List <BallProjectile> { ballProjectile }, ballRound: ballRound ) )); }
public GameOptions(ArEnvironment arEnvironment, BallProjectile ballProjectile) { _arEnvironment = arEnvironment; _ballProjectile = ballProjectile; }
public void FireBall() { BallProjectile projectile = Instantiate(ballProjectile, new Vector2(transform.position.x + pointOfFire, transform.position.y), Quaternion.identity); projectile.transform.SetParent(this.transform); }
public override IEnumerator StartRound() { BallRound ballRound = GenerateDataForRound(ballStorage.TargetRadius); Vector3 fastBallPosition = LeftTargetRing.transform.position; Vector3 playerBallPosition = MiddleTargetRing.transform.position; Vector3 slowBallPosition = RightTargetRing.transform.position; SoccerPlayer fastBallPlayer = InstantiateSoccerPlayer(fastBallPosition, ballRound.InitialFastBallRadius); SoccerPlayer playerBallPlayer = InstantiateSoccerPlayer(playerBallPosition, ballRound.InitialPlayerBallRadius); SoccerPlayer slowBallPlayer = InstantiateSoccerPlayer(slowBallPosition, ballRound.InitialSlowBallRadius); yield return(new WaitUntil(() => fastBallPlayer.PlayerHasKickedBall() && playerBallPlayer.PlayerHasKickedBall() && slowBallPlayer.PlayerHasKickedBall() )); BallProjectile fastBallProjectile = InstantiateBallProjectile(fastBallPosition, ballStorage.TargetRadius, ballRound.InitialFastBallRadius, ballRound.FastBallActualTimeToContact, ballRound.TimeBeforeDisappearence ); BallProjectile playerBallProjectile = InstantiateBallProjectile(playerBallPosition, ballStorage.TargetRadius, ballRound.InitialPlayerBallRadius, ballRound.PlayerBallActualTimeToContact, ballRound.TimeBeforeDisappearence ); BallProjectile slowBallProjectile = InstantiateBallProjectile(slowBallPosition, ballStorage.TargetRadius, ballRound.InitialSlowBallRadius, ballRound.SlowBallActualTimeToContact, ballRound.TimeBeforeDisappearence ); // After the balls have disappeared, yield return(new WaitForSeconds(ballRound.TimeBeforeDisappearence)); // Show the slider and submit button Slider.gameObject.SetActive(true); SubmitButton.gameObject.SetActive(true); // Make the lower value of the slider equal to arrival // time of the faster ball; make the upper value of the slider // equal to the arrival time of the slower ball Slider.minValue = ballRound.FastBallActualTimeToContact; Slider.maxValue = ballRound.SlowBallActualTimeToContact; // Move slider to half-way position Slider.value = (Slider.minValue + Slider.maxValue) / 2; bool buttonHasBeenClicked = false; // When the round is about to end, UnityAction whenButtonClicked = () => { // Record the player's predicted time to contact // by seeing how they judged it compared to the reference // first-arriving and last-arriving balls. ballRound.PredictedTimeToContact = Slider.value; // Save data for this round ballStorage.Rounds.Add(ballRound); // Hide the slider and submit button Slider.gameObject.SetActive(false); SubmitButton.gameObject.SetActive(false); buttonHasBeenClicked = true; }; // When the submit button is pressed, the round should end SubmitButton.onClick.AddListener(whenButtonClicked); yield return(new WaitUntil(() => buttonHasBeenClicked)); }