第三十九節(jié) 實現(xiàn)關(guān)卡功能

注意:這個卡讀成“qi?!?。

如果至始至終都是一樣的速度,那也太無聊了。所以增加關(guān)卡就很有必要了。

01.制作關(guān)卡對象

直接復(fù)制一個場景中的“HighScore”,重命名為Level,調(diào)整坐標(biāo):(206, 97, 0)。
刪除最后一個數(shù)字,修改中間的數(shù)字:除了“Middle”,全部隱藏。
然后將03重命名為Line,04,05重命名為03,04:



然后移除該對象上的ScoreScreen腳本組件。

02.添加關(guān)卡類

添加一個關(guān)卡類腳本:Level。該類只需4個數(shù)字,前兩個數(shù)字為主關(guān)卡,后兩個為次關(guān)卡:

using UnityEngine;

public class Level : MonoBehaviour
{
    public GameObject Number01;
    public GameObject Number02;
    public GameObject Number03;
    public GameObject Number04;

    public void SetLevel(int mainLevel, int MinorLevel)
    {
        // 設(shè)置主關(guān)卡
        Number01.GetComponent<Number>().SetNumber(mainLevel % 100 / 10);
        Number02.GetComponent<Number>().SetNumber(mainLevel % 10);

        // 設(shè)置次關(guān)卡
        Number03.GetComponent<Number>().SetNumber(MinorLevel % 100 / 10);
        Number04.GetComponent<Number>().SetNumber(MinorLevel % 10);
    }
}
03.添加關(guān)卡腳本

將腳本添加至關(guān)卡對象上,并綁定場景中的數(shù)字對象:


除此之外,還要將關(guān)卡對象拖放到導(dǎo)演對象的“Level Obj”上。

04.添加成員和初始化

準(zhǔn)備工作都做好了,接下來實現(xiàn)功能。

首先要添加成員,關(guān)卡腳本的引用和關(guān)卡值:

Level _levelScript;
int _level;                 // 關(guān)卡

本游戲沒有主次關(guān)卡之分,所以只需要一個關(guān)卡值就夠了。
然后就是初始化:

_level = 0;
// 初始化關(guān)卡
_levelScript = LevelObj.GetComponent<Level>();
if (_levelScript == null) return false;
_levelScript.SetLevel(0, _level);
05.如何實現(xiàn)變速

僅僅是實現(xiàn)變速的話,將定時器的時間間隔修改下即可:

InvokeRepeating("GameCore", 0, 1 - (_level - 1) * 0.1f);

按照這個公式,那么關(guān)卡1~10的速度分別為:
1 - 1s下落1格
2 - 0.9s下落1格
3 - 0.8s下落1格
4 - 0.7s下落1格
5 - 0.6s下落1格
6 - 0.5s下落1格
7 - 0.4s下落1格
8 - 0.3s下落1格
9 - 0.2s下落1格
10 - 0.1s下落1格,這個是最快的速度,一秒下落10格

計算速度并不難,關(guān)鍵是變速的時機(jī)。
首先,當(dāng)方塊處于加速下落時(按下下方向鍵但不松開),肯定不能變更速度,否則按鍵還沒松開,速度突然變慢了(加速的速度大于所有關(guān)卡的速度)算怎么回事?
然后消除方塊后如果正好使分?jǐn)?shù)達(dá)到了提升關(guān)卡的條件,那么就需要變速,也就是說,在消除方塊階段結(jié)束后,需要啟動一個更快的定時器來驅(qū)動GameCore()。但如果在這里啟動定時器,就會重現(xiàn)第32節(jié)中出現(xiàn)的Bug,不過有一個比較不錯的解決方案,就是在Invoke Repeating()之前先調(diào)用CancleInvoke():

CancelInvoke("GameCore");
InvokeRepeating("GameCore", 0, 1 - (_level - 1) * 0.1f);

雖然還是會有問題(多線程的問題),不過應(yīng)該能大大減少觸發(fā)Bug的概率。之前的Bug是因為我沒有調(diào)用CanlInvoke():



調(diào)用CancleInvoke()之后:



不過還是會有問題,因為有可能會出現(xiàn)這種順序:

只是概率非常低,因為停止和啟動兩行代碼是寫在一起的,要觸發(fā)Bug需要你松開按鍵的時機(jī)必須剛剛好卡在線程一的這兩行代碼之間。就算觸發(fā)了,按一下加速就恢復(fù)了。
然后因為不能在加速狀態(tài)中變速,所以需要加一個標(biāo)記來判斷是否處于加速狀態(tài)中:

bool _InQuickDown = false;          // 記錄是否正在快速下落

在按下下方向鍵時設(shè)置為true,松開后設(shè)置為false,順便修改啟動核心邏輯的定時器代碼,根據(jù)關(guān)卡來計算時間間隔:

// 按鍵 - 下方向鍵
if (Input.GetKeyDown(KeyCode.DownArrow))
{
    _InQuickDown = true;
    CancelInvoke("GameCore");
    InvokeRepeating("GameCore", 0, 0.03f);
}
if (Input.GetKeyUp(KeyCode.DownArrow))
{
    _InQuickDown = false;
    CancelInvoke("GameCore");
    InvokeRepeating("GameCore", 0, 1 - (_level - 1) * 0.1f);
}

然后需要在消除階段結(jié)束后變更速度前添加一個判斷:

// 如果未處于加速中
if (!_InQuickDown)
{
    CancelInvoke("GameCore");
    InvokeRepeating("GameCore", 0, 1 - (_level - 1) * 0.1f);
}

好了,現(xiàn)在變速的幾個地方都添加好代碼了,最后一件事就是根據(jù)分?jǐn)?shù)計算關(guān)卡。
我的關(guān)卡提升規(guī)則是,每增加2500分提升一個Level:

// 更新關(guān)卡
int newLevel = _currentScore / 2500 + 1;
if (newLevel > 10) newLevel = 10;
if (newLevel > _level)
{
    _level = newLevel;
    _levelScript.SetLevel(0, _level);
}

為了方便測試提升關(guān)卡后是否會提升速度,你可以將2500改成一個很小的值,比如200分。

1秒下落10格真的反應(yīng)不過來:


代碼鏈接:https://pan.baidu.com/s/1eIYPXNIL6V8i-aJ6ncmcXQ
提取碼:at6a

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容