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

我们在Command中执行计分,点对的计分操作可以写在之前实现过的KillEnemyCommand
里,点错的计分操作我们新实现一个MissCommand
计分的时候肯定是修改GameModel
里面的Score
,我们可以想到的有两种计分方法:
- 一种是直接在
KillEnemyCommand
和MissCommand
修改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文件夹内新建两个脚本,分别是OnEnemyKillEvent
和OnMissEvent
,在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
监听OnEnemyKillEvent
和OnMissEvent
,同时删除掉之前用随机数生成的分数
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的代码了
测试结果
