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