【程式碼分享】用Unity 實作小遊戲— 打磚塊 (Breakout clone)
Published: (Updated: )
by .打磚塊是一種電子遊戲。
螢幕上部有若干層磚塊,一個球在螢幕上方的磚塊和牆壁、螢幕下方的移動短板和兩側牆壁之間來回彈,當球碰到磚塊時,球會反彈,而磚塊會消失。玩家要控制螢幕下方的板子,讓「球」通過撞擊消去所有的「磚塊」,球碰到螢幕底邊就會消失,所有的球消失則遊戲失敗。把磚塊全部消去就可以破關。
(維基百科: https://zh.wikipedia.org/wiki/%E6%89%93%E7%A3%9A%E5%A1%8A )
以下為遊戲影片:
環境 (Environment)
遊戲製作引擎: Unity
程式語言:C#
image 素材公開分享(皆為原創):
程式碼分享 Open Source
@GameManager 遊戲控制中心
功能(Function)
- 得分系統 (Score)
- 陷阱系統(Trap)
- 球(Ball)
- 遊戲中心管理(GameManager)
- 倒數計時開始系統
- 球拍系統(Player)
@gamemanger
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class GameManager : MonoBehaviour
{
[Header("可打破的磚塊初始數量")]
public static int brickCount;
static GameObject nextLevelBotton;
public static void ReloadThisScene ()
{
Scene current = SceneManager.GetActiveScene();
SceneManager.LoadScene(current.name);
}
public static bool LevelClear
{
get {
if (brickCount <= 0)
{
return true;
}
return false;
}
}
public static void checkLevelClearOrNot ()
{
if (LevelClear)
{
showNextLevelButton();
}
}
public void GotoScene (string next)
{
SceneManager.LoadScene(next);
}
void Start()
{
nextLevelBotton = GameObject.FindGameObjectWithTag(tags.下一關按鈕.ToString());
nextLevelBotton.SetActive(false);
brickCount = GameObject.FindGameObjectsWithTag(tags.磚塊.ToString()).Length;
Debug.Log("一開始有 " + brickCount + "個可打破的磚塊");
}
static void showNextLevelButton ()
{
nextLevelBotton.SetActive(true);
}
// Update is called once per frame
void Update()
{
}
}
enum tags
{
磚塊,
背景,
球拍,
球,
下一關按鈕
}
@Trap 陷阱系統
@trap
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Trap : MonoBehaviour
{
[Header("被撞到時候的位移")]
public Vector3 offset;
public int life;
private void OnCollisionEnter2D(Collision2D other)
{
if (other.gameObject.CompareTag(tags.球.ToString()))
{
life--;
gameObject.transform.position += offset;
}
if (life <= 0 && !GameManager.LevelClear)
{
GameManager.ReloadThisScene();
}
}
}
@time 時間系統
@time
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class time : MonoBehaviour
{
int time_int = 3;
public Text time_UI;
// Start is called before the first frame update
void Start()
{
InvokeRepeating("timer", 1, 1);
Invoke("disappear", (float)3.2);
//一秒後,每秒重複呼叫timer函式。(開始倒數計時)。
//InokeRepeating 重複呼叫(“函式名”,第一次間隔幾秒呼叫,每幾秒呼叫一次)。
}
void disappear ()
{
this.gameObject.SetActive(false);
}
void timer ()
{
time_int -= 1;
time_UI.text = time_int + "";
if (time_int == 0)
{
time_UI.text = "Go";
CancelInvoke("timer"); }
}
}
@ball 球系統
@Ball
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Ball : MonoBehaviour
{
public Text ScoreText;
int score;
Rigidbody2D ballRigidbody2D;
CircleCollider2D ballCircleCollider2D;
[Header("水平速度")]
public float speedX;
[Header("垂直速度")]
public float speedY;
[Header("實際水平速度")]
public float velocityX;
[Header("實際垂直速度")]
public float velocityY;
void Start()
{
ballRigidbody2D = GetComponent<Rigidbody2D>();
ballCircleCollider2D = GetComponent<CircleCollider2D>( );
Invoke("ballStart", 3);
ScoreText.text = "目前分數:";
}
// Update is called once per frame
void Update()
{
velocityX = ballRigidbody2D.velocity.x;
velocityY = ballRigidbody2D.velocity.y;
if (Input.GetKey(KeyCode.Space))
{
ballStart();
}
}
void ballStart ()
{
if (isStop())
{
ballCircleCollider2D.enabled = true;
transform.SetParent(null);
ballRigidbody2D.velocity = new Vector2(speedX, speedY); //velocity 速度
}
}
bool isStop()
{
return ballRigidbody2D.velocity == Vector2.zero;
}
void OnCollisionEnter2D (Collision2D other)
{
lockSpeed();
if (other.gameObject.CompareTag("磚塊"))
{
GameManager.brickCount--;
Debug.Log("目前磚塊數量:" + GameManager.brickCount);
GameManager.checkLevelClearOrNot();
other.gameObject.SetActive(false);
score += 10;
ScoreText.text = "目前分數:" + score;
}
}
void lockSpeed()
{
Vector2 lockSpeed = new Vector2(resetSpeedX( ), resetSpeedY());
ballRigidbody2D.velocity = lockSpeed;
}
float resetSpeedX () //鎖定速度
{
float currentSpeedX = ballRigidbody2D.velocity.x;
if ( currentSpeedX <0 )
{
return -speedX; // speedX是自己設定的
}
else
{
return speedX;
}
}
float resetSpeedY()
{
float currentSpeedY = ballRigidbody2D.velocity.y;
if (currentSpeedY < 0)
{
return -speedY;
}
else
{
return speedY;
}
}
}
@球拍系統 Player
@player
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour
{
[Header("水平移動速度(不能為0)")]
public float speedX;
Rigidbody2D playerRigidbody2D;
Rigidbody2D body;
void Start() {
playerRigidbody2D = GetComponent<Rigidbody2D> ( );
Invoke("playerStart", 3);
Invoke("delay", 3); //Invoke(method,time(sec))
}
void delay ()
{
transform.GetComponent<Rigidbody2D>().constraints = ~RigidbodyConstraints2D.FreezePositionX;
}
void Update()
{
moveLeftOrRight(); //偵測玩家按鍵 (向左/右)
}
float LeftOrRight ()
{
return Input.GetAxis("Horizontal"); // 玩家輸入水平按鍵 向左按到底 回傳-1 向右反之(+1)
}
void moveLeftOrRight ()
{
playerRigidbody2D.velocity = LeftOrRight() * new Vector2(speedX, 0);//玩家的方向 乘以 速度(水平速度才有效)
}
}
遊戲畫面截圖分享
倒數計時系統
得分系統
切換地圖功能 — 方塊全部打完自己跳出來
陷阱系統
簡介: 當 ball 彈到下面那一條陷阱 即往下一格且反彈球 (注意球拍不要擋住)
球拍系統 (可上下左右鍵操控)
以上為我的程式實作教學 並稍微紀錄一下
開放程式原始碼給大家 如果有問題在留言!!