命令模式

Tulenber 29 May, 2020 ⸱ Beginner ⸱ 3 min ⸱ 2019.3.14f1 ⸱

让我们再给 储钱罐添加一个模式,看看一个名为“ Command”的设备如何使我们的生活更轻松。

控制是游戏不可或缺的一部分。消除控制,充其量,该游戏将变成电影。尽管最近,即使是电影,也开始提供控制屏幕上正在发生的事情的功能,例如,斯蒂芬·索德伯格(Stephen Soderberg)的《黑镜:布兰达希米格》或《马赛克》。就像编程中的几乎所有内容一样,游戏中控件的基本创建并不复杂。您只需要向调用检查该鼠标左键单击功能的函数添加一个调用,即可设置好镜头。然后调用另一个功能,然后通过按键盘上的空格键,您的角色开始跳跃。在整个代码中传播了十几个调用,我们可以开始生产了。将控制设置添加到游戏中?现在可以在iO中使用Xbox / DualShock控制器了,增加它们的支持会很好吗?您需要将游戏移植到控制台吗?不,我们不同意这一点。因此,很明显,由于需求的微小变化,简单的任务总会变成困难的任务,在设置控件的情况下,“命令”模式可以帮助您消除复杂性的增长。

理论

模板的官方描述说,命令是调用的包装对象。此方法使您可以轻松地在对象之间传输命令,重新配置它们的行为以及从中创建序列。为了更深入地了解理论部分,您可以参考Robert Nystrom书或此文章

与策略比较

在本质和基本实现上,命令与我们在本 周期上一篇文章中讨论的有关模板的策略非常相似,但是它们的用法在范围上有所不同。 该命令将各种动作变成对象;结果,您可以与他们自由互动;例如,用于取消操作。策略通常描述特定实体内部行为的变化。

命令序列

使用命令对象可以轻松地从中创建序列,该序列可用于按步骤撤消/重做操作,您要做的就是向命令对象添加有关反向操作的数据。它不适用于动作游戏;但是,它可以在基于回合的策略或创建用于配置某些游戏元素的编辑器时派上用场。

实践

作为一个实际示例,我们将使用上一篇文章中有关策略的展示,并通过命令模式将控件添加到魔术师中。 让我们创建三个命令:使用一个咒语,在咒语之间切换以及生成敌人。

实作

  1. 命令的基类:
1
2
3
4
5
// 命令的基类
public abstract class Command
{
    public abstract void Execute();
}
  1. 命令:
  1. 咒语用法:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
// 拼写用法命令
public class FireSpellCommand : Command
{
    private Mage _mage = null;

    public FireSpellCommand(Mage mage)
    {
        _mage = mage;
    }
    
    public override void Execute()
    {
        _mage.FireSpell();
    }
}
  1. 拼写切换:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
// 拼写切换命令
public class ChangeSpellCommand : Command
{
    private Mage _mage = null;

    public ChangeSpellCommand(Mage mage)
    {
        _mage = mage;
    }
    
    public override void Execute()
    {
        _mage.ChangeSpell();
    }
}
  1. 敌人产生:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
// 敌人生成命令
public class SpawnEnemyCommand : Command
{
    private EnemyHandler _enemyHandler;

    public SpawnEnemyCommand(EnemyHandler enemyHandler)
    {
        _enemyHandler = enemyHandler;
    }
    
    public override void Execute()
    {
        _enemyHandler.SpawnEnemy();
    }
}
  1. 命令管理:
 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
43
44
45
using UnityEngine;

public class InputHandler : MonoBehaviour
{
    // 控制法师和敌人的物体
    public Mage mage = null;
    public EnemyHandler enemyHandler = null;

    // 将动作链接到命令
    private Command _leftMouseClick = null;
    private Command _rightMouseClick = null;
    private Command _spaceKeyboardPush = null;

    // 在第一帧更新之前调用开始
    void Start()
    {
        // 命令创建
        _leftMouseClick = new FireSpellCommand(mage);
        _rightMouseClick = new SpawnEnemyCommand(enemyHandler);
        _spaceKeyboardPush = new ChangeSpellCommand(mage);
        
    }

    // 每帧调用一次更新
    void Update()
    {
        // 点击鼠标左键
        if (Input.GetMouseButtonDown(0))
        {
            _leftMouseClick.Execute();
        }

        // 点击鼠标右键
        if (Input.GetMouseButtonDown(1))
        {
            _rightMouseClick.Execute();
        }

        // 按下空格键
        if (Input.GetKeyDown(KeyCode.Space))
        {
            _spaceKeyboardPush.Execute();
        }
    }
}

结果

很容易看出动作是从调用代码中抽象出来的。 这简化了设置的创建或控制方法的扩展。

结论

我们生活在一个时代,移动设备除了通过触摸屏进行标准且通常不方便的控制外,还获得对可访问游戏(不仅是)控制器的支持,并且游戏发行很少仅在一个平台上进行。同样,控制设置一直是玩家友好性的要素。为了帮助应对这些挑战,我们研究的命令模式非常合适。但是,不要忘记过度使用模式会使您的代码变成千层面。下次见!^_^


如果您喜欢这篇文章,可以为它提供支持



Privacy policyCookie policyTerms of service
Tulenber 2020