注意:这个卡读成“qiǎ”。
如果至始至终都是一样的速度,那也太无聊了。所以增加关卡就很有必要了。
01.制作关卡对象
直接复制一个场景中的“HighScore”,重命名为Level,调整坐标:(206, 97, 0)。
删除最后一个数字,修改中间的数字:除了“Middle”,全部隐藏。
然后将03重命名为Line,04,05重命名为03,04:
然后移除该对象上的ScoreScreen脚本组件。
02.添加关卡类
添加一个关卡类脚本:Level。该类只需4个数字,前两个数字为主关卡,后两个为次关卡:
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)
{
// 设置主关卡
Number01.GetComponent<Number>().SetNumber(mainLevel % 100 / 10);
Number02.GetComponent<Number>().SetNumber(mainLevel % 10);
// 设置次关卡
Number03.GetComponent<Number>().SetNumber(MinorLevel % 100 / 10);
Number04.GetComponent<Number>().SetNumber(MinorLevel % 10);
}
}
03.添加关卡脚本
将脚本添加至关卡对象上,并绑定场景中的数字对象:
除此之外,还要将关卡对象拖放到导演对象的“Level Obj”上。
04.添加成员和初始化
准备工作都做好了,接下来实现功能。
首先要添加成员,关卡脚本的引用和关卡值:
Level _levelScript;
int _level; // 关卡
本游戏没有主次关卡之分,所以只需要一个关卡值就够了。
然后就是初始化:
_level = 0;
// 初始化关卡
_levelScript = LevelObj.GetComponent<Level>();
if (_levelScript == null) return false;
_levelScript.SetLevel(0, _level);
05.如何实现变速
仅仅是实现变速的话,将定时器的时间间隔修改下即可:
InvokeRepeating("GameCore", 0, 1 - (_level - 1) * 0.1f);
按照这个公式,那么关卡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格
计算速度并不难,关键是变速的时机。
首先,当方块处于加速下落时(按下下方向键但不松开),肯定不能变更速度,否则按键还没松开,速度突然变慢了(加速的速度大于所有关卡的速度)算怎么回事?
然后消除方块后如果正好使分数达到了提升关卡的条件,那么就需要变速,也就是说,在消除方块阶段结束后,需要启动一个更快的定时器来驱动GameCore()。但如果在这里启动定时器,就会重现第32节中出现的Bug,不过有一个比较不错的解决方案,就是在Invoke Repeating()之前先调用CancleInvoke():
CancelInvoke("GameCore");
InvokeRepeating("GameCore", 0, 1 - (_level - 1) * 0.1f);
虽然还是会有问题(多线程的问题),不过应该能大大减少触发Bug的概率。之前的Bug是因为我没有调用CanlInvoke():
调用CancleInvoke()之后:
不过还是会有问题,因为有可能会出现这种顺序:
只是概率非常低,因为停止和启动两行代码是写在一起的,要触发Bug需要你松开按键的时机必须刚刚好卡在线程一的这两行代码之间。就算触发了,按一下加速就恢复了。
然后因为不能在加速状态中变速,所以需要加一个标记来判断是否处于加速状态中:
bool _InQuickDown = false; // 记录是否正在快速下落
在按下下方向键时设置为true,松开后设置为false,顺便修改启动核心逻辑的定时器代码,根据关卡来计算时间间隔:
// 按键 - 下方向键
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);
}
然后需要在消除阶段结束后变更速度前添加一个判断:
// 如果未处于加速中
if (!_InQuickDown)
{
CancelInvoke("GameCore");
InvokeRepeating("GameCore", 0, 1 - (_level - 1) * 0.1f);
}
好了,现在变速的几个地方都添加好代码了,最后一件事就是根据分数计算关卡。
我的关卡提升规则是,每增加2500分提升一个Level:
// 更新关卡
int newLevel = _currentScore / 2500 + 1;
if (newLevel > 10) newLevel = 10;
if (newLevel > _level)
{
_level = newLevel;
_levelScript.SetLevel(0, _level);
}
为了方便测试提升关卡后是否会提升速度,你可以将2500改成一个很小的值,比如200分。
1秒下落10格真的反应不过来:
代码链接:https://pan.baidu.com/s/1eIYPXNIL6V8i-aJ6ncmcXQ
提取码:at6a
网友评论