注意:這個(gè)卡讀成“qiǔ┞颍”同仆。
如果至始至終都是一樣的速度,那也太無聊了枪向。所以增加關(guān)卡就很有必要了勤揩。
01.制作關(guān)卡對象
直接復(fù)制一個(gè)場景中的“HighScore”,重命名為Level秘蛔,調(diào)整坐標(biāo):(206, 97, 0)陨亡。
刪除最后一個(gè)數(shù)字傍衡,修改中間的數(shù)字:除了“Middle”,全部隱藏负蠕。
然后將03重命名為Line蛙埂,04,05重命名為03遮糖,04:
然后移除該對象上的ScoreScreen腳本組件绣的。
02.添加關(guān)卡類
添加一個(gè)關(guān)卡類腳本:Level。該類只需4個(gè)數(shù)字止吁,前兩個(gè)數(shù)字為主關(guān)卡被辑,后兩個(gè)為次關(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)備工作都做好了,接下來實(shí)現(xiàn)功能俄删。
首先要添加成員宏怔,關(guān)卡腳本的引用和關(guān)卡值:
Level _levelScript;
int _level; // 關(guān)卡
本游戲沒有主次關(guān)卡之分,所以只需要一個(gè)關(guān)卡值就夠了畴椰。
然后就是初始化:
_level = 0;
// 初始化關(guān)卡
_levelScript = LevelObj.GetComponent<Level>();
if (_levelScript == null) return false;
_levelScript.SetLevel(0, _level);
05.如何實(shí)現(xiàn)變速
僅僅是實(shí)現(xiàn)變速的話臊诊,將定時(shí)器的時(shí)間間隔修改下即可:
InvokeRepeating("GameCore", 0, 1 - (_level - 1) * 0.1f);
按照這個(gè)公式,那么關(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格斜脂,這個(gè)是最快的速度抓艳,一秒下落10格
計(jì)算速度并不難,關(guān)鍵是變速的時(shí)機(jī)帚戳。
首先玷或,當(dāng)方塊處于加速下落時(shí)(按下下方向鍵但不松開),肯定不能變更速度片任,否則按鍵還沒松開偏友,速度突然變慢了(加速的速度大于所有關(guān)卡的速度)算怎么回事?
然后消除方塊后如果正好使分?jǐn)?shù)達(dá)到了提升關(guān)卡的條件对供,那么就需要變速位他,也就是說,在消除方塊階段結(jié)束后产场,需要啟動(dòng)一個(gè)更快的定時(shí)器來驅(qū)動(dòng)GameCore()鹅髓。但如果在這里啟動(dòng)定時(shí)器,就會(huì)重現(xiàn)第32節(jié)中出現(xiàn)的Bug京景,不過有一個(gè)比較不錯(cuò)的解決方案迈勋,就是在Invoke Repeating()之前先調(diào)用CancleInvoke():
CancelInvoke("GameCore");
InvokeRepeating("GameCore", 0, 1 - (_level - 1) * 0.1f);
雖然還是會(huì)有問題(多線程的問題),不過應(yīng)該能大大減少觸發(fā)Bug的概率醋粟。之前的Bug是因?yàn)槲覜]有調(diào)用CanlInvoke():
調(diào)用CancleInvoke()之后:
不過還是會(huì)有問題靡菇,因?yàn)橛锌赡軙?huì)出現(xiàn)這種順序:
只是概率非常低,因?yàn)橥V购蛦?dòng)兩行代碼是寫在一起的米愿,要觸發(fā)Bug需要你松開按鍵的時(shí)機(jī)必須剛剛好卡在線程一的這兩行代碼之間厦凤。就算觸發(fā)了,按一下加速就恢復(fù)了育苟。
然后因?yàn)椴荒茉诩铀贍顟B(tài)中變速较鼓,所以需要加一個(gè)標(biāo)記來判斷是否處于加速狀態(tài)中:
bool _InQuickDown = false; // 記錄是否正在快速下落
在按下下方向鍵時(shí)設(shè)置為true,松開后設(shè)置為false违柏,順便修改啟動(dòng)核心邏輯的定時(shí)器代碼博烂,根據(jù)關(guān)卡來計(jì)算時(shí)間間隔:
// 按鍵 - 下方向鍵
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é)束后變更速度前添加一個(gè)判斷:
// 如果未處于加速中
if (!_InQuickDown)
{
CancelInvoke("GameCore");
InvokeRepeating("GameCore", 0, 1 - (_level - 1) * 0.1f);
}
好了,現(xiàn)在變速的幾個(gè)地方都添加好代碼了漱竖,最后一件事就是根據(jù)分?jǐn)?shù)計(jì)算關(guān)卡禽篱。
我的關(guān)卡提升規(guī)則是,每增加2500分提升一個(gè)Level:
// 更新關(guān)卡
int newLevel = _currentScore / 2500 + 1;
if (newLevel > 10) newLevel = 10;
if (newLevel > _level)
{
_level = newLevel;
_levelScript.SetLevel(0, _level);
}
為了方便測試提升關(guān)卡后是否會(huì)提升速度馍惹,你可以將2500改成一個(gè)很小的值躺率,比如200分。
1秒下落10格真的反應(yīng)不過來:
代碼鏈接:https://pan.baidu.com/s/1eIYPXNIL6V8i-aJ6ncmcXQ
提取碼:at6a