上一节完成了最佳分数功能,这一节完成点对点错计分功能,暂不实现倒计时计分

功能 规则 实现
最佳分数 存储并记录最佳分数
倒计时 游戏倒计时10秒
计分 点错一次扣5分,点对一次得10分,结束时倒计时每剩余1秒得10分
金币 每次点击正确的方块,有一定概率获得1~3金币
商店 游戏开始前可以在商店购买,能够抵消点击错误的次数
成就 百分成就、手残成就(分数为负数)、零失误成就、
重开 游戏结束后回到首页再来一次

点击计分纸上设计

在游戏中添加一个背景墙,点击到方块则加分,点击到背景墙则减分

背景墙外框

我们在Command中执行计分,点对的计分操作可以写在之前实现过的KillEnemyCommand里,点错的计分操作我们新实现一个MissCommand

计分的时候肯定是修改GameModel里面的Score,我们可以想到的有两种计分方法:

  • 一种是直接在KillEnemyCommandMissCommand修改GameModel
  • 另一种是声明两个事件,在ScoreSystem里面监听这两个事件,在KillEnemyCommand发送KillEnemy事件,在MissCommand里面发送Miss事件

很明显第二种方法可以让我们的分数加减逻辑都集中在ScoreSystem里,方便后期修改查阅。

纸上设计事件

实现

先在《点点点》场景中添加一个背景板,我们先在Hierarchy窗口中激活Enemies,再在其中添加一个Plane,命名为ErrorArea,在FrameworkDesign——Example文件夹内添加一个默认材质,改为蓝色,让ErrorArea使用这个材质

背景板

在FrameworkDesign——Example——Scripts——Game文件夹内新建一个脚本,命名为ErrorArea,挂载在ErrorArea上。这个脚本是后期用来发送Command用的。

实现事件

我们先实现点击的两个事件,在FrameworkDesign——Example——Scripts——Event文件夹内新建两个脚本,分别是OnEnemyKillEventOnMissEvent,在TypeEventSystem中,这两个类仅仅是为了提供Type。

1
2
3
4
5
6
7
namespace FrameWorkDesign.Example
{
public class OnEnemyKillEvent
{

}
}
1
2
3
4
5
6
7
namespace FrameWorkDesign.Example
{
public class OnMissEvent
{

}
}

实现Command

然后实现发送事件的两个Command,先修改KillEnemyCommand

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
namespace FrameWorkDesign.Example
{
public class KillEnemyCommand : AbstractCommand
{
protected override void OnExecute()
{
var gameModel = this.GetModel<IGameModel>();
gameModel.KillCount.Value++;

this.SendEvent<OnEnemyKillEvent>();//

if (gameModel.KillCount.Value == 9)
{
this.SendEvent<GameEndEvent>();
}
}
}
}

MissCommand还没有被创建,我们先在FrameworkDesign——Example——Scripts——Command文件夹内创建它,

1
2
3
4
5
6
7
8
9
10
namespace FrameWorkDesign.Example
{
public class MissCommand : AbstractCommand
{
protected override void OnExecute()
{
this.SendEvent<OnMissEvent>();
}
}
}

ScoreSystem监听事件

修改IScoreSystem监听OnEnemyKillEventOnMissEvent,同时删除掉之前用随机数生成的分数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
using UnityEngine;

namespace FrameWorkDesign.Example
{
public interface IScoreSystem : ISystem
{

}
public class ScoreSystem : AbstractSystem, IScoreSystem
{
protected override void OnInit()
{
var gameModel = this.GetModel<IGameModel>();

this.RegisterEvent<GameEndEvent>(e =>
{
Debug.Log("Score: "+gameModel.Score.Value);
Debug.Log("BestScore: "+gameModel.BestScore.Value);

if (gameModel.Score.Value > gameModel.BestScore.Value)
{
gameModel.BestScore.Value = gameModel.Score.Value;
Debug.Log("新纪录");
}
});

this.RegisterEvent<OnEnemyKillEvent>(e =>
{
gameModel.Score.Value += 10;
Debug.Log("得10分");
Debug.Log("当前分数:" + gameModel.Score.Value);
});

this.RegisterEvent<OnMissEvent>(e =>
{
gameModel.Score.Value -= 5;
Debug.Log("减5分");
Debug.Log("当前分数:" + gameModel.Score.Value);
});
}
}
}

Controller发送Command

接下来只剩下在表现层发送Command了

修改ErrorArea

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
using UnityEngine;

namespace FrameWorkDesign.Example
{
public class ErrorArea : MonoBehaviour,IController
{
IArchitecture IBelongToArchitecture.GetArchitecture()
{
return PointGame.Interface;
}

private void OnMouseDown()
{
this.SendCommand<MissCommand>();
}
}
}

Enemy脚本已经有发送Command的代码了

测试结果

输出结果