如何实现命令模式和键绑定

本文关键字:模式 绑定 命令 何实现 实现 | 更新日期: 2023-09-27 18:37:12

我正在使用 .NET 开发一个视频游戏,但我正在努力了解如何正确实现命令队列,然后立即执行它们。

我的电子游戏很简单,它是一架会移动的飞机。我的命令模式实现如下,然后在 Player 类上实现这些命令的管理:

public abstract class ICommand {
        Category CategoryProperty { get; set; }
        public abstract void Execute();
    }
public class MoveAircraftCommand : ICommand
    {
        private Vector2f _velocity;
        Aircraft aircraft;
        public Category CategoryProperty {
            get {
                return Category.PlayerAircraft;
            }
        }
        public MoveAircraftCommand (float vx, float vy, Aircraft v_aircraft) {
            _velocity = new Vector2f(vx, vy);
            aircraft = v_aircraft;
        }
        public override void Execute()
        {
            aircraft.Accelerate(_velocity);
        }
    }
//Then, There is the Player class that binds keys to actions, and actions to Commands.
public class Player
    {
public enum ActionMove {
            MoveLeft,
            MoveRight,
            MoveUp,
            MoveDown,
            ActionCount
        }
private IDictionary<Keyboard.Key, ActionMove> _keyBinding;
private IDictionary<ActionMove,ICommand> _actionBinding;
public Player()
        {
            _keyBinding = new Dictionary<Keyboard.Key, ActionMove>();
            _keyBinding.Add(Keyboard.Key.Left,ActionMove.MoveLeft);
            _keyBinding.Add(Keyboard.Key.Right,ActionMove.MoveRight);
            _keyBinding.Add(Keyboard.Key.Up,ActionMove.MoveUp);
            _keyBinding.Add(Keyboard.Key.Down,ActionMove.MoveDown);
/** Dunno how to bind the actions to commands without instantiating the command, Hard-Coding the parameters at start. Also Yet I don't have instantiated the aircraft object**/
float playerSpeed = 200f;
            _actionBinding.Add(ActionMove.MoveRight,new MoveAircraftCommand(+playerSpeed,0f,aircraft));
            _actionBinding.Add(ActionMove.MoveUp,new MoveAircraftCommand(0f,-playerSpeed, aircraft));
            _actionBinding.Add(ActionMove.MoveDown,new MoveAircraftCommand(0f,+playerSpeed,aircraft));
/** **/
/**This function pushes the Commands to a queue, in order to process them in order at once**/
public void HandleRealTimeInput(CommandQueue commands) {
            foreach (KeyValuePair<Keyboard.Key,ActionMove> entry in _keyBinding) {
                if (Keyboard.IsKeyPressed(entry.Key) && isRealTimeAction(entry.Value)) {
                    commands.Push(_factory.GetCommand(_keyBinding[entry.Key]));
                }
            }
        }

如何正确实现命令模式并在需要时正确实例化这些命令及其所有参数?

谢谢

如何实现命令模式和键绑定

这里的关键是要意识到呈现命令模式的"标准"方式是准则,而不是规则。C# 内置了委托和 lambda,因此无需定义 ICommand 等。通过摆脱命令类,可以大大简化 Player 类。以下内容远非完整,但希望能说明我的意思:

public class Player
{
    private Aircraft _aircraft;
    private float _playerSpeed = 200f;
    private readonly IDictionary<Keyboard.Key, ActionMove> _keyBinding =
        new Dictionary<Keyboard.Key, ActionMove>
        {
            { Keyboard.Key.Left,ActionMove.MoveLeft },
            { Keyboard.Key.Right,ActionMove.MoveRight },
            { Keyboard.Key.Up,ActionMove.MoveUp },
            { Keyboard.Key.Down,ActionMove.MoveDown }
        };
    private readonly IDictionary<ActionMove,ICommand> _actionBinding =
        new Dictionary<ActionMove,Action>
        {
            { ActionMove.MoveRight, () => MoveAircraft(_playerSpeed, 0f, _aircraft) },
            { ActionMove.MoveUp, () => MoveAircraft(0f, -_playerSpeed, _aircraft) },
            ...
        };
    public MoveAircraft(float vx, float vy, Aircraft v_aircraft) 
    {
        var velocity = new Vector2f(vx, vy);
        aircraft.Accelerate(_velocity);
    }
    ...
}

关键更改是将 MoveAircraft 方法移动到类中,然后通过_actionBinding字典中的闭包 lambda 调用它。Dictionary<ActionMove,Action>定义了一个以 ActionMove 为键的字典和一个没有参数作为值的 void 方法。然后 eg () => MoveAircraft(_playerSpeed, 0f, _aircraft) 表达式指定一个没有参数的匿名 void 方法,该方法将当前值 _playerSpeed_aircraft传递给 MoveAircraft

要调用这些方法,您只需执行例如_actionBinding[ActionMove.MoveRight]();