Welcome back to How to Make Video Games! This time I’ll finish up the Pong game. If you’ve watched the previous parts you’ve learned all about : Collision Detection, Animation, AI Controlled Competitors, Physics, Keyboard Input, Unity User Interfaces, Splash Screens, Sound Effects, Background Music, Build Settings and more.
All of the code used can be found below and here are the sounds and artwork used. Up next I’ll make the most profitable arcade game in history Space Invaders!!!
If you like videos like this consider donating $1 on Patreon
[googleplusone]
Code for Pong
AIPaddle.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AIPaddle : MonoBehaviour {
// Reference to the ball
public Ball theBall;
// Default ball speed
public float speed = 30;
// lerp is used to smooth out movement over time
//
public float lerpTweak = 2f;
// Reference to the Rackets Rigidbody component
private Rigidbody2D rigidBody;
// Use this for initialization
void Start () {
// Get reference to the attached Rigidbody
// component
rigidBody = GetComponent<Rigidbody2D> ();
}
void FixedUpdate () {
// Check if the ball y position is > racket y position
if (theBall.transform.position.y > transform.position.y)
{
Vector2 dir = new Vector2(0, 1).normalized;
// Lerp receives 2 vectors and smoothes the movement over time
rigidBody.velocity = Vector2.Lerp(rigidBody.velocity, dir * speed, lerpTweak * Time.deltaTime);
}
else if (theBall.transform.position.y < transform.position.y)
{
Vector2 dir = new Vector2(0, -1).normalized;
rigidBody.velocity = Vector2.Lerp(rigidBody.velocity, dir * speed, lerpTweak * Time.deltaTime);
}
else
{
Vector2 dir = new Vector2(0, 0).normalized;
rigidBody.velocity = Vector2.Lerp(rigidBody.velocity, dir * speed, lerpTweak * Time.deltaTime);
}
}
}
Ball.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// Needed to manipulate the UI
using UnityEngine.UI;
public class Ball : MonoBehaviour {
// Ball default speed
public float speed = 30;
// Reference to the balls Rigidbody component
private Rigidbody2D rigidBody;
// Reference the AudioSource for the Ball
private AudioSource audioSource;
// Use this for initialization
void Start () {
// Get reference to the attached Rigidbody
// component
rigidBody = GetComponent<Rigidbody2D> ();
// Calculate velocity for the ball
rigidBody.velocity = Vector2.right * speed;
}
// Called when the ball collides with anything
void OnCollisionEnter2D(Collision2D col){
// col provides info on the object the ball hit
// If it is the left paddle do this
if ((col.gameObject.name == "LeftPaddle") || (col.gameObject.name == "RightPaddle")) {
handlePaddleHit (col);
}
if ((col.gameObject.name == "WallBottom") || (col.gameObject.name == "WallTop")) {
// Call for SoundManager to play the wall sound
SoundManager.Instance.PlayOneShot (SoundManager.Instance.wallBloop);
}
if ((col.gameObject.name == "LeftGoal") || (col.gameObject.name == "RightGoal")) {
// Call for SoundManager to play the goal sound
SoundManager.Instance.PlayOneShot (SoundManager.Instance.goalBloop);
if (col.gameObject.name == "LeftGoal") {
increaseTextUIScore ("RightScoreUI");
} else if (col.gameObject.name == "RightGoal") {
increaseTextUIScore ("LeftScoreUI");
}
// Change the balls position on the game board to its starting
// position
transform.position = new Vector2(-1.133788f, 0.1743597f);
}
}
// Calculate where the ball hits the paddle by dividing
// the ball's y coordinate by the paddles height
// If the ball hits above the midpoint ricochet up
// and vice versa
float ballHitPaddleWhere(Vector2 ball, Vector2 paddle,
float paddleHeight){
return (ball.y - paddle.y) / paddleHeight;
}
void handlePaddleHit(Collision2D col){
// Pass the balls position, the paddles position,
// the height of the paddle
float y = ballHitPaddleWhere (transform.position,
col.transform.position,
col.collider.bounds.size.y);
// Calculate direction of ball
// A vector is a line pointing from an origin
// to a point x, y
// Magnitude is the length of the line
Vector2 dir = new Vector2();
// If (0,1) is straight up and down is (0, -1),
// normalized would change our vector into a value
// between 0 and 1
if (col.gameObject.name == "LeftPaddle") {
dir = new Vector2 (1, y).normalized;
Vector2 dir2 = dir = new Vector2 (1, y);
Debug.Log ("Dir : " + dir + "Dir2 : " + dir2);
}
if (col.gameObject.name == "RightPaddle") {
dir = new Vector2 (-1, y).normalized;
}
// Change the velocity / direction of the ball
// You assign a vector to velocity here
rigidBody.velocity = dir * speed;
// Call for SoundManager to play paddle sound
SoundManager.Instance.PlayOneShot (SoundManager.Instance.hitPaddleBloop);
}
// Increases the score the the text UI name passed
void increaseTextUIScore(string textUIName){
// Find the matching text UI component
var textUIComp = GameObject.Find(textUIName)
.GetComponent<Text>();
// Get the string stored in it and convert to an int
int score = int.Parse(textUIComp.text);
// Increment the score
score++;
// Convert the score to a string and update the UI
textUIComp.text = score.ToString();
}
}
ContinuePlayingMusic.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ContinuePlayingMusic : MonoBehaviour {
// Update is called once per frame
void Update () {
// Don't destroy the background music when a new
// scene loads
DontDestroyOnLoad(gameObject);
}
}
MovePaddle.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MovePaddle : MonoBehaviour {
// Speed rackets move
public float speed = 30;
void FixedUpdate(){
// GetAxisRaw returns a value representing whether
// W or Up (1), S or Down (-1), or Nothing (0)
// are being pressed
float vertDirection = Input.GetAxisRaw ("Vertical");
// Set the velocity of the racket in the vertical direction
// Velocity will be movement direction * speed
GetComponent<Rigidbody2D> ().velocity = new Vector2 (0, vertDirection) * speed;
}
}
SoundManager.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SoundManager : MonoBehaviour {
// Holds the single instance of the SoundManager that
// you can access from any script
public static SoundManager Instance = null;
// All sound effects in the game
// All are public so you can set them in the Inspector
public AudioClip goalBloop;
public AudioClip lossBuzz;
public AudioClip hitPaddleBloop;
public AudioClip winSound;
public AudioClip wallBloop;
// Refers to the audio source added to the SoundManager
// to play sound effects
private AudioSource soundEffectAudio;
// Use this for initialization
void Start() {
// This is a singleton that makes sure you only
// ever have one Sound Manager
// If there is any other Sound Manager created destroy it
if (Instance == null) {
Instance = this;
} else if (Instance != this) {
Destroy (gameObject);
}
AudioSource theSource = GetComponent<AudioSource> ();
soundEffectAudio = theSource;
}
// Other GameObjects can call this to play sounds
public void PlayOneShot(AudioClip clip) {
soundEffectAudio.PlayOneShot(clip);
}
}
SplashScreen.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// Used to switch scenes
using UnityEngine.SceneManagement;
public class SplashScreen : MonoBehaviour {
// The next scene to load
public string sceneToLoad;
// Time to pause before loading next scene in seconds
public int secTillSceneLoad;
// Use this for initialization
void Start () {
// Call function OpenNextScene after a set number of seconds
Invoke("OpenNextScene", secTillSceneLoad);
}
// Update is called once per frame
void OpenNextScene () {
// Load defined scene
SceneManager.LoadScene(sceneToLoad);
}
}