※J.Y Chen 的個人部落格 ※

Just Follow Our Heart And We will shine!

721 瀏覽人次

【程式碼分享】用Unity 實作小遊戲— 打磚塊 (Breakout clone)

Published: (Updated: ) in Code by .

打磚塊是一種電子遊戲

螢幕上部有若干層磚塊,一個球在螢幕上方的磚塊和牆壁、螢幕下方的移動短板和兩側牆壁之間來回彈,當球碰到磚塊時,球會反彈,而磚塊會消失。玩家要控制螢幕下方的板子,讓「球」通過撞擊消去所有的「磚塊」,球碰到螢幕底邊就會消失,所有的球消失則遊戲失敗。把磚塊全部消去就可以破關。

(維基百科: https://zh.wikipedia.org/wiki/%E6%89%93%E7%A3%9A%E5%A1%8A )

以下為遊戲影片:

環境 (Environment)

遊戲製作引擎: Unity
程式語言:C#
image 素材公開分享(皆為原創):

程式碼分享 Open Source

@GameManager 遊戲控制中心

功能(Function)

  1. 得分系統 (Score)
  2. 陷阱系統(Trap)
  3. 球(Ball)
  4. 遊戲中心管理(GameManager)
  5. 倒數計時開始系統
  6. 球拍系統(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 彈到下面那一條陷阱 即往下一格且反彈球 (注意球拍不要擋住)

陷阱系統

球拍系統 (可上下左右鍵操控)

以上為我的程式實作教學 並稍微紀錄一下
開放程式原始碼給大家 如果有問題在留言!!

©2019 - 2024 Henry Chen