diff --git a/Assets/Source/Scripts/Pong/Ball/PongBall.cs b/Assets/Source/Scripts/Pong/Ball/PongBall.cs index 42b4d53..cbb774a 100644 --- a/Assets/Source/Scripts/Pong/Ball/PongBall.cs +++ b/Assets/Source/Scripts/Pong/Ball/PongBall.cs @@ -18,7 +18,7 @@ namespace Pong.Ball { //* After scoring, it goes: DestroyBall() -> [tiny delay] -> Reset() -> [small delay] -> Serve() public partial class PongBall { public readonly ControlledGameObject ballSprite; // it won't actually be destroyed; it will just vanish and look like it was destroyed - private readonly Stack<(float, bool)> serveAngles = new Stack<(float, bool)>(); // float is in radians, and the int is the attackerDesire + private readonly Stack<(float, bool, float)> serveAngles = new Stack<(float, bool, float)>(); // float is in radians, and the int is the attackerDesire, float is speed // Player on the offensive private Player attacker; // "lastTouchedBy"; the initial trajectory will also set this as the player opposite to where it is traveling @@ -28,6 +28,8 @@ public partial class PongBall { private readonly Action OnScore; private readonly Action OnRebound; + // private int speed_factor = 1; + public PongBall(GameObject sprite) { OnScore = () => { //* Attacker Scored Goal @@ -68,6 +70,12 @@ public static PongBall FromPrefab(GameObject prefab) { return pongBall; } + /// + /// Initialize ball's behavior, including who to serve to first, left or right player. + /// Serve angle is also initialized for all the rounds possible for the game, from Round 0 to max round + /// Serve angles are pushed onto stack to and used when Serve() is called. + /// + /// void public void Initialize(Player server) { // First, reset the ball (just in case) Reset(); @@ -88,6 +96,7 @@ public void Initialize(Player server) { for (uint i = 0; i < maxRounds; ++i) { float angle = UnityEngine.Random.Range(-BALL_SERVE_MAX_ANGLE, BALL_SERVE_MAX_ANGLE); // base; works for if server is on left bool desire; + float speed = BALL_SPEED_VP * UnityEngine.Random.Range(0, 5); // (i % 2 == 0) => first server is to the right => the right server is on even rounds to serve left // (i % 2 == 1) => first server is to the left => the right server is on odd rounds to serve left @@ -101,7 +110,7 @@ public void Initialize(Player server) { } //Debug.Log(angle); - serveAngles.Push((angle, desire)); + serveAngles.Push((angle, desire, speed)); //TODO: debug /*if (i == 10) { @@ -113,10 +122,16 @@ public void Initialize(Player server) { SetAttacker(server); } + /// + /// Serve te ball to the non attacking player. Swap attacker if current attacker and server + /// desire are not equal. Finally, change the ball's velocity and motion in the viewport to + /// have serve shown on screen. + /// + /// void // serve the ball public void Serve() { - (float angle, bool serverDesire) = serveAngles.Pop(); - float speed = BALL_SPEED_VP; // in terms of viewport x percentage + (float angle, bool serverDesire, float speed) = serveAngles.Pop(); + // float speed = BALL_SPEED_VP; // in terms of viewport x percentage bool otherPlayerServingInstead = attackerDesire != serverDesire; if (otherPlayerServingInstead) { @@ -126,6 +141,9 @@ public void Serve() { Vector2 direction = new Vector2(Mathf.Cos(angle), Mathf.Sin(angle)); // unit vector Vector2 viewportVelocity = speed * direction; + // viewportVelocity *= speed_factor; + // speed_factor *= 2; + ballSprite.controller.ViewportVelocity = viewportVelocity; // set velocity ballSprite.controller.BeginTrajectory(); // start the timer for y'(t) } diff --git a/Assets/Source/Scripts/Pong/Ball/_Pong-Ball.cs b/Assets/Source/Scripts/Pong/Ball/_Pong-Ball.cs index 44ec914..84ec317 100644 --- a/Assets/Source/Scripts/Pong/Ball/_Pong-Ball.cs +++ b/Assets/Source/Scripts/Pong/Ball/_Pong-Ball.cs @@ -11,6 +11,10 @@ namespace Pong.Ball { * Player lastTouchedBy * Destroys the ball and increments points */ + /// + /// class dictating ball behavior in the context of gameplay such as scoring, + /// whos on offensive, ball behavior on serve and score. + /// public partial class PongBall {} /* @@ -18,6 +22,9 @@ public partial class PongBall {} speedX = GameCache.BALL_SPEED_VP velocityY = ForceAdjustment => Equation (due to possible derivatives) */ + /// + /// actual movement of the ball across the viewport. angles on rebounds, general trajectory + /// public partial class PongBallController : MonoBehaviour {} /*public static class BallStatus { @@ -37,10 +44,15 @@ public static bool IsGoal(int ballStatus) { } }*/ + /// + /// set condition of whether it is the left players turn to serve or right players turn + /// public static class BallGoal { public const bool LEFT = true; public const bool RIGHT = false; + // public const bool RIGHT = true; + // Note: we don't even need an INVERT() function because the ! operator already does that with bools! } } \ No newline at end of file diff --git a/Assets/Source/Scripts/Pong/GameManager.cs b/Assets/Source/Scripts/Pong/GameManager.cs index 56fea0c..987096e 100644 --- a/Assets/Source/Scripts/Pong/GameManager.cs +++ b/Assets/Source/Scripts/Pong/GameManager.cs @@ -38,6 +38,12 @@ void Awake() //Debug.Log(GameConstants.LEFT_PADDLE_START_POSITION); } + /// + /// Initialization of the game when it is first run. Caches global variables such as win score, + /// ball speed, max angle, etc. Paddles are initialized, ball object is created and served in a + /// random direction. + /// + /// void void Start() { // Cache Desired Global Variables @@ -64,6 +70,11 @@ void Start() ball.Serve(); } + /// + /// Update player and ball objects every frame. Player paddle movement is + /// updated on the screen every frame. + /// + /// void // Update is called once per frame void Update() { diff --git a/Assets/Source/Scripts/Pong/GamePlayer/PlayerController.cs b/Assets/Source/Scripts/Pong/GamePlayer/PlayerController.cs index 16e5098..fbd973a 100644 --- a/Assets/Source/Scripts/Pong/GamePlayer/PlayerController.cs +++ b/Assets/Source/Scripts/Pong/GamePlayer/PlayerController.cs @@ -31,6 +31,13 @@ void Start() } + /// + /// Update() is called to update the player paddle movement in the viewport. + /// At a high level, it gets the current motion of the paddles, and sets the + /// next position of the paddles in the viewport. + /// + /// void + // Update is called once per frame void Update() { @@ -54,6 +61,12 @@ void Update() viewportMotion.Y_Acceleration = viewportYAcceleration; } + /// + /// RespondToInput() takes the keybord input and sets new change in + /// paddle position in the Unity GameObject. It calculates the change in + /// position through the function DeltaY(). + /// + /// a float representing the change in y value for the paddle protected float RespondToInput() { float dy = 0f; @@ -79,6 +92,12 @@ protected float DeltaY() { return dy_dt * Time.deltaTime; } + /// + /// takes a float deltaY that was calculated from DeltaY(), to change the + /// paddle position in Unity GameObject. It accounts for changes that causes + /// object to move out of bounds. + /// + /// void public void MoveY(float deltaY) { // origin is in the center float MAX_Y_POS = BG_TRANSFORM.localScale.y / 2f; diff --git a/Assets/Source/Scripts/Pong/GamePlayer/_Pong-GamePlayer.cs b/Assets/Source/Scripts/Pong/GamePlayer/_Pong-GamePlayer.cs index f92133c..e68127a 100644 --- a/Assets/Source/Scripts/Pong/GamePlayer/_Pong-GamePlayer.cs +++ b/Assets/Source/Scripts/Pong/GamePlayer/_Pong-GamePlayer.cs @@ -5,13 +5,28 @@ using UnityEngine; namespace Pong.GamePlayer { + + /// + /// Class to hold player data and functions such as moving the controls, score, etc. + /// To be implemented in Player.cs. + /// public partial class Player {} + /// + /// Class to hold player data history such as paddle movement and ball location to train + /// AI to control paddle better. + /// public partial class PlayerData : ScriptableObject {} //public partial class AIPlayerData : PlayerData {} + /// + /// Class to control player paddle movement such as moving paddle up and down when user presses up and down keys. + /// public partial class PlayerController : MonoBehaviour {} + /// + /// sets up controls players can make - up and down keys + /// public class PlayerControls { public readonly KeyCode Up, Down; public PlayerControls(KeyCode up, KeyCode down) { diff --git a/Assets/Source/Scripts/Pong/_Pong.cs b/Assets/Source/Scripts/Pong/_Pong.cs index 699b313..4fd670c 100644 --- a/Assets/Source/Scripts/Pong/_Pong.cs +++ b/Assets/Source/Scripts/Pong/_Pong.cs @@ -7,6 +7,12 @@ using Pong.GamePlayer; namespace Pong { + + /// + /// GameConstants class defines the constants needed for gameplay setup such as default score to win, + /// initial positions of the paddles, initial position of the ball, etc. This class also sets up the + /// control keys for each player to move the paddles. + /// public static class GameConstants { // must be >= 1 because velocity is required public const uint BALL_Y_MAX_DERIVATIVE = 3; // velocity + (acceleration, acceleration') @@ -40,6 +46,10 @@ public static class GameConstants { public static readonly char[] WINDOWS_BANNED_CHARS = {'\\', '/', ':', '*', '?', '\"', '<', '>', '|'}; } + /// + /// Class stores the saved settings of the last gameplay session such as ball speed, + /// serve angle, win score, etc. + /// public static class GameCache { // cached at the beginning of GameManager public static Transform BG_TRANSFORM; @@ -55,6 +65,9 @@ public static class GameCache { public static bool MUTE_SOUNDS = false; // when turned on, audio won't be played } + /// + /// Helper class for converting 3d vectors to 2d vectors and viewport vectors, and viewport vectors to local vectors + /// public static class GameHelpers { public static Vector2 ToVector2(Vector3 vector) { return new Vector2(vector.x, vector.y); @@ -79,6 +92,9 @@ public static Vector2 ToViewport(Vector3 localVec) { } } + /// + /// declare gameplay manager class for implementation later + /// public partial class GameManager : MonoBehaviour {} //public partial class GameContext {} diff --git a/WriteupTemplate.md b/WriteupTemplate.md index 0c193ec..8ed6e9b 100644 --- a/WriteupTemplate.md +++ b/WriteupTemplate.md @@ -4,75 +4,104 @@ ### Header Files **`Pong/_Pong.cs`** -Purpose & Importance: +Purpose & Importance: + +Holds all necessary information to make Pong run, such as start up cache, gameplay constants,and helper functions for vector conversions. Important Classes & Variables: -- `static class GameConstants`: -- `static class GameCache`: -- `static class GameHelpers`: -- `class GameManager`: +- `static class GameConstants`: holds all the constants needed for gameplay setup such as default win score, starting positions, paddle control keys +- `static class GameCache`: holds all the cached settings of gameplay such as ball speed, angle, and win score. +- `static class GameHelpers`: helper class containing helper functions for converting vectors (3d to 2d, 2d to local, 3d to viewport). +- `class GameManager`: class declaration for implementation in GameManager.cs. To hold methods to control gameplay of Pong **`Pong/GamePlayer/_Pong-GamePlayer.cs`** Purpose & Importance: +Holds all player information including controls, scoring, data. File contains all neccessary player functions to run the game. + Important Classes & Variables: -- `class Player`: -- `class PlayerData`: -- `class PlayerController`: -- `class PlayerControls`: +- `class Player`: creates player, including: controller object, player score, paddle rebounding +- `class PlayerData`: player movement history to train AI model +- `class PlayerController`: controller class to control player paddle movement on the viewport +- `class PlayerControls`: sets keys for player paddle movement -**`Pong/Ball/Pong-Ball.cs`** +**`Pong/Ball/_Pong-Ball.cs`** Purpose & Importance: +File contains all ball information such as movement, ball behavior. Pong Ball declares all the neccessary methods needed for the ball object including ball movement logic and ball display on the viewport. + Important Classes & Variables: -- `class PongBall`: -- `class PongBallController`: -- `static class BallGoal`: +- `class PongBall`: class containing ball behavior in cases such as initialization and scoring +- `class PongBallController`: class controlling ball movement on the viewport. Specifies how the ball should animate on the screen. +- `static class BallGoal`: class to set left player or right player serve status. ### Non-Header Files -**`File Path 1`** +**`/Pong/GameManager.cs`** -Purpose & Importance: +Purpose & Importance: + +File contols. initialization of Pong Gameplay - startup and update to every frame. Important Methods & Variables: -**`File Path 2`** +- `void Start()`: starts up Pong - initializes player and ball objects. +- `void Update()`: updates player and ball state: including location, score, movement. +- `Player player1`, player2: Player objects to hold each player. +- `PongBall ball`: Ball object to hold the pong ball. -Purpose & Importance: +**`Pong/GamePlayer/PlayerController.cs`** + +Purpose & Importance: + +Handles player keyboard inputs and changes paddle position in game viewport and unity game object. Important Methods & Variables: -**`File Path 3`** +- `void Update()`: Update() updates player paddle position. It sets the change in position of the paddles given the user inputs, and updates it in the viewport. +- `void RespondToInput()`: takes in keybaord input (up arrow key or down key) and sets deltaY accordingly. +- `void MoveY(float deltaY)`: MoveY() takes in deltaY calculated by RespondToInput and updates paddle motion in viewport. +- `Motion2D viewportMotion`: Motion2D object holding physics of paddle motion, including acceleration and velocity of paddle. +- `PlayerControls controls`: PlayerControl object holding controls for the paddles - up & down keys. + +**`Pong/Ball/PongBall.cs`** Purpose & Importance: Important Methods & Variables: +- `void Initialize()`: Initialize sets up all necessary ball behaviors, mainly, the serve angles and direction (left, right) of each round for the ball. The angles and "player desire" are all initialized by random, and pushed onto a stack for use each round. +- `void Serve()`: Serve actually serves the ball each round: including popping a serve angle and desire from the stack, using it to set the balls trajectory in the viewport, and swapping attackers if necessary. +- `Stack<(float, bool)> serveAngles`: variable is a stack that holds all serve angles for every round. All angles (serve angle and left/right direction) are initialized at the start and popped off the stack each round. +- `Action OnScore`: OnScore is an Action variable that holds a callback function to handle whenever a player scores a point. The ball is destroyed, the score is updated, round is reset, and the ball is served again. + ## Testing **Example #1** -- Modification/Addition: -- Effect: +- Modification/Addition: Created a speed multiplier that doubled everytime Serve() was called + +- Effect: Everytime the ball was served after scoring, the speed would double. This led to an increasingly fast end to the game as the ball would travel way too fast. + - [optional] What I learned: **Example #2** -- Modification/Addition: -- Effect: -- [optional] What I learned: +- Modification/Addition: Changed both BallGoal.LEFT and BallGoal.RIGHT to true. +- Effect: scoring would malfunction. when ball was scored on right goal, right's score would increase even if +it was left's point. +- [optional] What I learned: BallGoal.LEFT and BallGoal.RIGHT are used to keep track of which opponent is attacking when the ball is served. Since there's a mismatch between the ball desire and attacker, the point system will malfunction. This also shows that the scores are independent of what's viewed on the screen. **Example #3** -- Modification/Addition: -- Effect: +- Modification/Addition: Added speed to variable to serveAngles stack, set speed to a random number from 0 - 5. +- Effect: Speed would vary for rounds. Some rounds faster/slower than others. - [optional] What I learned: ## Documentation -- Non-header file #1: `` -- Non-header file #2: `` -- Non-header file #3: `` -- Header file #1: `` -- Header file #2: `` -- Header file #3: `` +- Non-header file #1: `Pong/GameManager.cs` +- Non-header file #2: `Pong/GamePlayer/PlayerController.cs` +- Non-header file #3: `Pong/Ball/PongBall.cs` +- Header file #1: `Pong/_Pong.cs` +- Header file #2: `Pong/GamePlayer/_Pong-GamePlayer.cs` +- Header file #3: `Pong/Ball/_Pong-Ball.cs`