Racquet AlphaZone Part 4: Technical Design Document

Introduction

“Racquet AlphaZone” is a Pong clone featuring a user against an AI opponent, enhanced with Power-Ups. The game will harness Unity’s integrated systems and will be complemented by custom C# scripting.

Software Architecture

Platform: Unity (2021.3.19f1)

Language: C#

Scene Management

Use Unity’s SceneManager to switch between the different scenes: Start Scene, Main Scene, and End Game Scene.

User Input Handling

Utilize Unity’s Input System to detect key presses (‘W’, ‘S’) for controlling the player’s paddle.

AI Opponent Behavior

Implement predictive tracking for the AI opponent to anticipate the ball’s direction.

Game Physics

Attach a Rigidbody2D component to the ball to enable physics-driven movement. Use a Physics Material 2D to adjust bounciness and friction.

Power-ups

Utilize coroutines to manage the time-dependent duration of power-ups.

Rendering and Graphics

Attach SpriteRenderer components (which are typically associated with sprites by default) to display game objects such as paddles, ball, and power-ups.

Animations

Lightning bolt power-up animation: Animate the x and y positions of the lightning bolt power-up to simulate a dynamic shaking movement.

Split Ball power-up: Animate the z-axis rotation of the split ball power-up to create a spinning effect.

Barrier power-up: Animate the x and y scaling values of the barrier power-up to simulate a zoom effect.

Canvas & UI

Utilize Unity’s native UI elements to design menus, showcase scores, and so forth.

Sound

Use distinct audio sources for background music and sound effects. Employ various audio clips for different in-game events.

Game State Management

GameState

A static class that houses game data and provides the required functionality.

The GameState class holds the following variables:

PlayerScore: An integer representing the player’s score.

AIScore: An integer representing the opponent’s score.

WinScore: An integer that defines the winning score.

LightningBoltDuration: A float representing the duration, in seconds, of the lightning bolt power-up.

BarrierDuration: A float representing the duration, in seconds, of the lightning bolt power-up.

SecondBallDuration: A float representing the duration, in seconds, of the lightning bolt power-up.

SpeedMultiplier: A float representing the speed multiplier applied by the lightning bolt power-up.

PointsPerGoal: An integer that denotes the points a player earns for each goal.

EasyDifficultyPointBonus: A float representing the point multiplier for easy difficulty.

NormalDifficultyPointBonus: A float representing the point multiplier for normal difficulty.

HardDifficultyPointBonus: A float representing the point multiplier for easy difficulty.

PlayerTotalScore: An integer keeping track of the total score of the player.

AITotalScore: An integer keeping track of the total score of the AI opponent.

Difficulty: An integer representing the current game difficulty (Easy=0, Normal=1, Hard=2).

PlayerSpeed: A float that represents the speed of the player’s racquet.

BallSpeed: A float that represents the speed of the ball.

AISpeed: A float that represents the speed of the opponent’s racquet.                   

AIError: A float indicating the margin of error in the AI’s prediction.      

AIPerceptionInterval: A float that denotes how frequently the AI assesses the environment.

SoundFxOn: A Boolean representing whether the sound effects are on or off.

SoundFxVolume: A float that defines the volume level of the sound effects.

MusicOn: A Boolean representing whether the music is on or off.

MusicVolume: A float indicating the volume level of the background music.

The GameState statc class contains four functions:

GetDifficulty: A function that takes no parameters and returns the current difficulty level as a string.

GetBonus: A function that accepts no parameters and returns the point bonus associated with the current difficulty level.

Save: A function that takes no parameters and has a void return type. It stores the game data in PlayerPrefs.

Load: A function that takes no parameters and has a void return type. It loads the game data from PlayerPrefs.

Scripting Details

MainMenuFunctions Pseudo-Code

Variables:

MainMenu, SettingsMenu as CanvasGroup

SoundFxToggle, MusicToggle as Toggle

SoundFXSlider, MusicSlider as Slider

Function Play:

Load scene with index 1

Function OpenSettings:

Hide MainMenu

Show SettingsMenu

Function Exit:

Save game data using GameState

Log “Exit”

Quit application

Function SetEasyDifficulty:

Set game difficulty to easy

Configure game parameters (PlayerSpeed, BallSpeed, etc.)

Function SetNormalDifficulty:

Set game difficulty to normal

Configure game parameters (PlayerSpeed, BallSpeed, etc.)

Function SetHardDifficulty:

Set game difficulty to hard

Configure game parameters (PlayerSpeed, BallSpeed, etc.)

Function SetSoundFx using toggle:

Update GameState’s sound effect setting based on the toggle state

Function SetSoundFxVolume using slider:

Update GameState’s sound effect volume based on the slider value

Function SetMusic using toggle:

Update GameState’s music setting based on the toggle state

Function SetMusicVolume using slider:

Update GameState’s music volume based on the slider value

Function ExitSettings:

Save game data using GameState

Hide SettingsMenu

Show MainMenu

Function OpenProgressSavedLink:

Open the URL “https://ProgressSaved.com”

Function Awake (called when the script is initialized):

Load game data from GameState

Update UI elements (toggles, sliders) based on the loaded data

UpdateTotalScore Pseudo-Code

A script to refresh the total score displayed in the start scene.

Class UpdateTotalScore:

Variables:

PlayerTotalText, AITotalText as Text

Function Start (called when the script instance is being loaded):

Set PlayerTotalText to display GameState’s PlayerTotalScore

Set AITotalText to display GameState’s AITotalScore

EndGameMenuFunctions Pseudo-Code

A script that facilitates the functions for the end-game menu in the end scene.

Class EndGameMenuFunctions:

Variables:

EndGamePanel as CanvasGroup

EndGameTitle, GameScore as Text

Function Play:

Reset Player’s and AI’s scores to 0

Load scene with index 1

Function ExitToMainMenu:

Reset Player’s and AI’s scores to 0

Load scene with index 0

Function Start (called when the script instance is being loaded):

If Player’s score is greater than or equal to the winning score, Player Wins

Else If AI’s score is greater than or equal to the winning score, AI Wins

Else Nobody Wins

Function PlayerWins:

Set EndGameTitle to “Player Wins!”

Update GameScore with the calculated score

Function AIWins:

        Set EndGameTitle to “AI Wins!”

        Update GameScore with the calculated score

Function NobodyWins:

Set EndGameTitle to “Nobody Wins!”

Set GameScore to “Score: 0”

Function CalculateScore returns a string:

Calculate score based on the difference between Player’s and AI’s scores, multiplied by points per goal and any bonus

If Player’s score is greater than or equal to the winning score, increase Player’s total score with the calculated score

Else increase AI’s total score with the calculated score

Save game data

Return the calculated score as a string

MusicManager Pseudo-Code

A script that orchestrates the playback of background music.

Class MusicManager

Variables:

backgroundMusic: AudioClip – Holds the reference to the background music clip

audioSource: AudioSource – Reference to the AudioSource component attached to the game object

Precondition:

This class requires an AudioSource component to be attached to the GameObject it’s on

Procedure StopSound

// Stop playing the sound from the audioSource if it’s currently playing

If the audioSource is playing:

Stop the audioSource

Procedure Start

// This procedure is called automatically before the game starts rendering its first frame

// Set up the audioSource component and play the background music

// Get the AudioSource component attached to this GameObject

Set audioSource to the AudioSource component of this GameObject

// Assign the background music to the audioSource’s clip

Set audioSource’s clip to backgroundMusic

// Enable or disable the audioSource based on the global game state setting

Set audioSource’s enabled status to the value of GameState.MusicOn

// Set the volume of the audioSource based on the global game state setting

Set audioSource’s volume to the value of GameState.MusicVolume

// Start playing the background music

Play audioSource

UpdateUI Pseudo-Code

A script to modify the score and adjust difficulty settings.

Class UpdateUI:

Variables:

PlayerScoreText, AIScoreText, DifficultyText as Text

Function Start (called when the script instance is being loaded):

Set DifficultyText to display the difficulty from GameState

Function FixedUpdate (called regularly at fixed intervals):

Update PlayerScoreText with the current player’s score from GameState

Update AIScoreText with the current AI’s score from GameState

SoundManager Pseudo-Code

A script to trigger various sound effects during gameplay.

Class SoundManager:

Variables:

ballBounceClip: AudioClip – Holds the reference to the ball bounce sound

powerUpClip: AudioClip – Holds the reference to the power-up sound

playerScoreClip: AudioClip – Holds the reference to the player score sound

aiScoreClip: AudioClip – Holds the reference to the AI score sound

countDownClip: AudioClip – Holds the reference to the countdown sound

audioSource: AudioSource – Reference to the AudioSource component attached to the game object

Precondition:

This class requires an AudioSource component to be attached to the GameObject it’s on

Procedure StopSound

// Stop playing the sound from the audioSource if it’s currently playing

If the audioSource is playing:

Stop the audioSource

Procedure PlayBallBounce

Play the sound with the index 0 (ball bounce sound)

Procedure PlayPowerUp

Play the sound with the index 1 (power-up sound)

Procedure PlayPlayerScore

Play the sound with the index 2 (player score sound)

Procedure PlayAIScore

Play the sound with the index 3 (AI score sound)

Procedure PlayCountDown

Play the sound with the index 4 (countdown sound)

Procedure Start

// This procedure is called automatically before the game starts rendering its first frame

// Set up the audioSource component

// Get the AudioSource component attached to this GameObject

Set audioSource to the AudioSource component of this GameObject

// Enable or disable the audioSource based on the global game state setting

Set audioSource’s enabled status to the value of GameState.SoundFx

// Set the volume of the audioSource based on the global game state setting

Set audioSource’s volume to the value of GameState.SounFxVolume

Private Procedure PlaySound(soundIdx: int)

// Stop playing any sound from the audioSource if it’s currently playing

If the audioSource is playing:

Stop the audioSource

// Select the sound to play based on the provided index

Switch on soundIdx:

Case 0:

Set audioSource’s clip to ballBounceClip

Case 1:

Set audioSource’s clip to powerUpClip

Case 2:

Set audioSource’s clip to playerScoreClip

Case 3:

Set audioSource’s clip to aiScoreClip

Case 4:

Set audioSource’s clip to countDownClip

Default:

Do nothing

End Switch

// Play the selected sound

Play audioSource

PauseManager Pseudo-Code

A script that offers the ability to pause and restart the game.

Class PauseManager

Variables:

PausedCanvas: CanvasGroup – Represents the UI element showing the pause message

soundManager: Reference to the SoundManager

isPaused: Boolean – Flag to check if the game is paused

Procedure Awake

// When the object is initialized, immediately pause the game

Call PauseGame method

Procedure Start

// At the start of the game, find the SoundManager

Set soundManager to FindAnyObjectByType of type SoundManager

If soundManager is null:

Print Error “SoundManager not found!”

Procedure Update

// Check for player input each frame

If space key is pressed:

Toggle the pause state

Procedure HidePauseMessage

// Hide the pause message

Set PausedCanvas alpha to 0

Procedure TogglePause

// Switch between paused and unpaused state

If the game is paused:

Resume the game

Else:

Pause the game

Procedure PauseGame

// Pause the game and show the pause message

Set time scale to 0 (stops game time)

Set isPaused flag to true

Set PausedCanvas alpha to 1 (showing the canvas)

Procedure ResumeGame

// Prepare to resume the game and hide the pause message

Set isPaused flag to false

Set PausedCanvas alpha to 0 (hiding the canvas)

Play countdown sound using soundManager

Start the ResumeGameCoroutine with a delay of 3 seconds

Procedure ResumeGameCoroutine(duration: float)

// After the given duration, resume the game time

Wait for ‘duration’ seconds in real time (ignores time scale)

Set time scale to 1 (resumes game time)

InGameMenuFunctions Pseudo-Code

A script that manages the functions for the in-game menu in the main scene.

Class InGameMenuFunctions:

Variables:

InGameMenu as CanvasGroup

pauseManager as PauseManager

isOpen as boolean (default = false)

Function Start:

Get reference to pauseManager in the current scene

If pauseManager is not found:

Display an error message “PauseManager is not found.”

Function Update (called every frame):

If Escape key is pressed:

Call ToggleMenu function

Function ToggleMenu:

If menu is open:

Call HideInGameMenu function

Else:

Call ShowInGameMenu function

Function ShowInGameMenu:

Set InGameMenu’s transparency to fully opaque (alpha = 1)

Make InGameMenu interactable and block raycasts

Pause the game using pauseManager

Set isOpen to true

Function HideInGameMenu:

Set InGameMenu’s transparency to fully transparent (alpha = 0)

Make InGameMenu non-interactable and not block raycasts

Resume the game using pauseManager

Set isOpen to false

Function ResumeGame:

Call HideInGameMenu function

Function ExitToMainMenu:

Pause the game using pauseManager

Save current game state

Reset the game scores

Load the main menu scene (index 0)

Function ResetGame:

Reset Player’s score to 0

Reset AI’s score to 0

SecondBallController Pseudo-Code

A script to guide the movement of balls introduced by the split ball power-up.

Class SecondBallController:

Variables:

rb: Reference to Rigidbody2D component

soundManager: Reference to SoundManager instance

Procedure Start

// Get the Rigidbody2D component from the current object

rb = Get Rigidbody2D component from this object

// If Rigidbody2D component is not found, log an error

If rb is null:

Log an error “Rigidbody2D not found!”

// Find the instance of the SoundManager

soundManager = Find instance of SoundManager in the scene

// If SoundManager is not found, log an error

If soundManager is null:

Log an error “SoundManager not found!”

Procedure Update

// If the ball’s speed is less than 2, destroy the ball object

If magnitude of rb’s velocity is less than 2:

Destroy this object

Procedure OnTriggerEnter2D (takes other as Collider2D)

// Switch based on the tag of the collided object

Switch on other’s game object tag:

Case “PlayerGoalpost”:

Call AddToAIScore method

Break

Case “AIGoalpost”:

Call AddToPlayerScore method

Break

Default:

Do nothing

Procedure AddToAIScore

// Play the AI scoring sound

Call soundManager’s PlayAIScore method

// Increment the AI’s score by 1

Increase GameState’s AIScore by 1

// Destroy the second ball object

Destroy this object

Procedure AddToPlayerScore

// Play the Player scoring sound

Call soundManager’s PlayPlayerScore method

// Increment the Player’s score by 1

Increase GameState’s PlayerScore by 1

// Destroy the second ball object

Destroy this object

PowerUpSpawner Pseudo-Code

A script that orchestrates the spawning of power-ups.

Class PowerUpSpawner

Variables:

powerUpPrefabs: Array of GameObjects – References to PowerUp prefabs

spawnInterval: Time duration (default to 5.0f) – Time interval between power-up spawns

spawnAreaMin: Vector2 – Minimum (bottom-left) corner of the spawn area

spawnAreaMax: Vector2 – Maximum (top-right) corner of the spawn area

powerUpLifeDuration: Time duration (default to 10.0f) – Duration for which a power-up remains in the scene

nextSpawnTime: Timestamp – Next time a power-up will spawn

Procedure Start

// Set the initial spawn time

nextSpawnTime = Current time + spawnInterval

Procedure Update

// If the current time is beyond the next spawn time

If current time >= nextSpawnTime:

// Spawn a power-up

Call SpawnPowerUp method

// Update the next spawn time

nextSpawnTime = Current time + spawnInterval

Procedure SpawnPowerUp

// Determine a random spawn position within the defined area

Vector2 spawnPosition:

x is a random value between spawnAreaMin.x and spawnAreaMax.x

y is a random value between spawnAreaMin.y and spawnAreaMax.y

// Randomly select a power-up prefab from the array

GameObject selectedPowerUp = Random power-up from powerUpPrefabs

// Create the selected power-up in the game at the spawn position

GameObject spawnedPowerUp = Instantiate selectedPowerUp at spawnPosition

// Destroy the spawned power-up after the defined life duration

Destroy spawnedPowerUp after powerUpLifeDuration seconds

PowerUpDisplayManager Pseudo-Code

A script to visually represent the active power-up in the UI.

Class PowerUpDisplayManager

Variables:

powerUpIcon: Image UI component – to show the power-up icon

defaultSprite: Sprite – Default icon when no power-up is active

boltSprite: Sprite – Icon for the lightning bolt power-up

barrierSprite: Sprite – Icon for the barrier power-up

splitSprite: Sprite – Icon for the split ball power-up

Procedure Start

// Initialize with the default icon

Call SetSprite method with index 0

Procedure SetDefaultSprite

// Set the default icon

Call SetSprite method with index 0

Procedure SetBoltSprite

// Set the bolt icon

Call SetSprite method with index 1

Procedure SetBarrierSprite

// Set the barrier icon

Call SetSprite method with index 2

Procedure SetSplitSprite

// Set the split icon

Call SetSprite method with index 3

Procedure SetSprite(spriteIdx: Integer)

// Depending on the provided index, set the respective sprite

Switch spriteIdx:

Case 0:

Set powerUpIcon sprite to defaultSprite

Break

Case 1:

Set powerUpIcon sprite to boltSprite

Break

Case 2:

Set powerUpIcon sprite to barrierSprite

Break

Case 3:

Set powerUpIcon sprite to splitSprite

Break

Default:

Do nothing

End Switch

PlayerController Pseudo-Code

A script responsible for controlling the player’s paddle.

Class PlayerController:

Variables:

mainCamera as Camera

speed as float

topBoundary as float

bottomBoundary as float

halfRacquetHeight as float

rb as Rigidbody2D

Function Initialize:

Set speed to the value from GameState’s PlayerSpeed

Function ResetPlayerPosition:

Set rb’s y-position to 0 while keeping the x-position unchanged

Function Start:

Call Initialize function

Get reference to the Rigidbody2D component of the current object and assign to rb

Calculate halfRacquetHeight as half of the current object’s y-scale

Calculate the topBoundary as:

mainCamera’s orthographic size minus halfRacquetHeight

Calculate the bottomBoundary as: negative value of topBoundary

Function FixedUpdate (called on fixed time intervals):

Get vertical input (from W and S keys or Up and Down arrow keys) and assign to verticalInput

Calculate newY as: Clamp the value of:

rb’s y-position added with (verticalInput multiplied by speed and Time.deltaTime)                             to range between bottomBoundary and topBoundary

Set rb’s position to new Vector with unchanged x and newY for y

AIPredictiveTracking Pseudo-Code

A script designed to enact the AI logic overseeing the opponent’s paddle.

Class AIPredictiveTracking:

Variables:

ball as Transform

rb, ballRb as Rigidbody2D

speed, error, selectedBallDirection, perceptionElapsedTime, perceptionInteval as float

Function Initialize:

Set speed from GameState’s AISpeed

Set error from GameState’s AIError

Set perceptionInteval from GameState’s AIPerceptionInteval

Function ResetPlayerPosition:

Set rb’s position with unchanged x and y set to 0

Function Start:

Call Initialize

If ball is not assigned:

Show error message “Ball not found.”

Get Rigidbody2D component of current object and assign to rb

If rb is null:

Show error message “AI player Rigidbody2D not found.”

Get Rigidbody2D component of ball and assign to ballRb

If ballRb is null:

Show error message “Ball Rigidbody2D not found.”

Function FixedUpdate:

Increment perceptionElapsedTime by the fixed time interval

If perceptionElapsedTime surpasses perceptionInteval:

Select a ball to chase and assign to ballToChase

Predict the ballToChase’s Y position and assign to predictedY

Determine the direction of the ballToChase based on predictedY compared to the AI’s current y-position. Set to 1 or -1 and assign to selectedBallDirection

Calculate desired velocity using selectedBallDirection and speed, and smooth the transition between current and desired velocities

Reset perceptionElapsedTime to 0

Function SelectBall returns Transform:

Get all instances of SecondBallController and assign to otherBalls

If otherBalls is null or has no elements:

Return main ball

Initialize minDistance with a very large number and closestBall as null

For each ball in otherBalls:

If ball is not null:

Calculate the distance between current object and ball and assign to distance

If distance is less than minDistance:

Update minDistance and closestBall with current ball

If closestBall is not null:

Calculate distances between AI and main ball, and AI and closestBall

If the AI is closer to closestBall than main ball:

Return closestBall’s Transform

Return main ball’s Transform

Function PredictBallYPosition returns float:

Calculate time for the ball to reach the AI based on ball’s x-position, AI’s x-position, and ball’s x-velocity

Calculate predicted Y position of ball at that time based on ball’s current y-velocity and the calculated time

Introduce randomness to the predicted Y position using the error range

Return the final predictedY

BallController Pseudo-Code

A script to guide the movement of the ball.

Imports required libraries

Class BallController extends MonoBehaviour:

Declare required game objects and variables

// Game objects that are public and can be set in the editor

Declare PlayerBarrier as GameObject

Declare ballPrefab as GameObject

// Private variables for internal logic and references

Declare rb as Rigidbody2D (for physics operations)

Declare soundManager for handling sound operations

Declare musicManager for handling music operations

Declare pauseManager for handling game pause logic

Declare powerUpDisplayManager for handling power-up UI display

Declare player for controlling player’s operations

Declare aiPlayer for controlling AI’s operations

// Private variables for game logic and properties

Declare ballSpeed as float (for setting the speed of the ball)

Declare lightningBoltDuration as float (duration of lightning bolt power-up effect)

Declare barrierDuration as float (duration of barrier power-up effect)

Declare secondBallDuration as float (duration before the second ball disappears)

Declare speedMultiplier as float (multiplier for ball’s speed under certain conditions)

Declare initialDirection as Vector2 (direction in which the ball initially moves)

Declare currentSpeed as float (current speed of the ball)

Declare HasGameSEnded as boolean (tracks if the game has ended or not) and set it to false initially

Method Initialize:

Set ballSpeed to the value of GameState’s BallSpeed

Set lightningBoltDuration to the value of GameState’s LightningBoltDuration

Set barrierDuration to the value of GameState’s BarrierDuration

Set secondBallDuration to the value of GameState’s SecondBallDuration

Set speedMultiplier to the value of GameState’s SpeedMultiplier

Method Start:

Call Initialize method

Set currentSpeed to the value of ballSpeed

Call RandomizeDirection method

Assign musicManager by finding an object of type MusicManager in the scene

If musicManager is not assigned (null) then

Display error message “MusicManager not found!”

Assign soundManager by finding an object of type SoundManager in the scene

If soundManager is not assigned (null) then

Display error message “SoundManager not found!”

Assign pauseManager by finding an object of type PauseManager in the scene

If pauseManager is not assigned (null) then

Display error message “PauseManager not found!”

Assign powerUpDisplayManager by finding an object of type PowerUpDisplayManager in the scene

If powerUpDisplayManager is not assigned (null) then

Display error message “PowerUpDisplayManager not found!”

Assign player by finding an object of type PlayerController in the scene

If player is not assigned (null) then

Display error message “PlayerController not found!”

Assign aiPlayer by finding an object of type AIPredictiveTracking in the scene

If aiPlayer is not assigned (null) then

Display error message “AIPredictiveTracking not found!”

Assign rb to the Rigidbody2D component attached to this object

Call LaunchBall method

Method RandomizeDirection

Generate a random number between 0 and 2

If the random number is less than 0.5 then

Set initialDirection to (1, 0)

Else

Set initialDirection to (-1, 0)

End If

Method LaunchBall

Call RandomizeDirection to determine the ball’s initial direction

Set the ball’s velocity to initialDirection multiplied by currentSpeed

Method OnCollisionEnter2D with parameter collision:

If the collided object has the tag “Racquet”:

Call BallBounceOnRacquet with collision as argument

Method OnTriggerEnter2D with parameter other

Get the tag of the “other” object

Based on the tag value, do the following:

If tag is “LightningBolt”:

Call ApplyLightningBolt method with “other” as argument

Else if tag is “Barrier”:

Call EnableBarrier method with “other” as argument

Else if tag is “BallSplit”:

Call ApplyBallSplit method with “other” as argument

Else if tag is “PlayerGoalpost”:

Call AddToAIScore method

Else if tag is “AIGoalpost”:

Call AddToPlayerScore method

Else:

Do nothing

Method Update:

IF game has ended THEN

Exit the method

IF absolute value of ball’s horizontal position is greater than 10 (ball goes off-screen) OR ball’s velocity magnitude is less than 2f (ball loses its speed) THEN

Call ResetBall method

IF player’s score is greater than or equal to win score OR AI’s score is greater than or equal to win score THEN

Mark the game as ended

Call PauseManager’s method to hide pause message

Call SoundManager’s method to stop sound

Call MusicManager’s method to stop music

Wait for 1 second and then call EndGame method

Coroutine Method EndGame (taking duration as parameter):

Wait for the specified ‘duration’ in real-world time

Load the scene with index 2

Method ResetBall:

Set the ball’s position to the origin (0,0)

Set the ball’s velocity to zero

Call the LaunchBall method to re-launch the ball

Method BallBounceOnRacquet(collision):

Play the ball bounce sound using soundManager

Calculate the hit factor using: ball’s position, collision’s position, and the height of the collision collider

Set the reflection direction:

x-coordinate is the negative of initialDirection’s x-coordinate

y-coordinate is the previously calculated hit factor value

Normalize this reflection direction

Set the ball’s velocity as the reflection direction multiplied by the current speed

Function HitFactor(ballPosition, racquetPosition, racquetHeight) returns float:

Calculate the difference in y-coordinate between ball’s position and racquet’s position

Divide the result by the racquet’s height

Return the quotient

Function ApplyLightningBolt(other)

Play the sound for power-up using soundManager

Set the lightning bolt sprite on the powerUpDisplayManager

Set currentSpeed to ballSpeed multiplied by speedMultiplier

Update the ball’s velocity by multiplying it with currentSpeed

Start the ResetLightningBolt coroutine with lightningBoltDuration as its argument

Destroy the “other” game object

Coroutine ResetLightningBolt(duration):

Wait for seconds equal to “duration”

Set the default sprite on the powerUpDisplayManager

Set currentSpeed to ballSpeed

Update the ball’s velocity to its normalized value multiplied by currentSpeed

Function EnableBarrier(other):

Play the power-up sound using soundManager

Set the barrier sprite on the powerUpDisplayManager

Set PlayerBarrier to active

Start Coroutine ResetBarrier with duration set to “barrierDuration”

Destroy the other game object

Function ResetBarrier(duration):

Wait for seconds equal to duration

Set the default sprite on the powerUpDisplayManager

Set PlayerBarrier to inactive

Function ApplyBallSplit(other):

Play power-up sound using soundManager

Update UI with split ball sprite using powerUpDisplayManager

Create newBall at current ball’s position from ballPrefab template

Get the Rigidbody component of the newBall into newBallRb

Get the normalized velocity of the current ball as currentDirection

Calculate newDirection1 by rotating currentDirection 45 degrees clockwise

Calculate newDirection2 by rotating currentDirection 45 degrees counter-clockwise

Set the velocity of the current ball as newDirection1 multiplied by ballSpeed

Set the velocity of the newBall as newDirection2 multiplied by ballSpeed

Wait for a duration equivalent to secondBallDuration then reset the split ball effect using newBall

Destroy the “other” game object

Function ResetSplitBall(duration, secondBall):

Wait for “duration” seconds

Update UI to default sprite using powerUpDisplayManager

Schedule the destruction of the “secondBall” gameObject after “secondBallDuration” seconds

Schedule the destruction of the “secondBall” itself after “secondBallDuration” seconds

Function RotateVectorByDegrees(vector v, angle degrees):

// Convert angle from degrees to radians

radians = degrees * conversion factor to radians

// Calculate sine and cosine of the radians

sin = sine of radians

cos = cosine of radians

// Store vector’s x and y components temporarily

tx = x-component of v

ty = y-component of v

// Calculate the new x and y components after rotation

newX = (cos * tx) – (sin * ty)

newY = (sin * tx) + (cos * ty)

// Return the rotated vector

Return new vector with components (newX, newY)

Procedure AddToAIScore

Call soundManager’s PlayAIScore method

Increase GameState’s AIScore by 1

Call player’s ResetPlayerPosition method

Call aiPlayer’s ResetPlayerPosition method

Call pauseManager’s PauseGame method

Procedure AddToPlayerScore

Call soundManager’s PlayPlayerScore method

Increase GameState’s PlayerScore by 1

Call player’s ResetPlayerPosition method

Call aiPlayer’s ResetPlayerPosition method

Call pauseManager’s PauseGame method

Technical Design Document and Game Design Document From Study Tonight