命令模式demo-一个简单的动画回放功能

最近突然又想去学习下怎么写游戏了,所以呢,这篇博客是来水的。。。顺便记录一下设计模式中命令模式的典型用法,以及推荐一个学习游戏的教程,说到写游戏那最好的教程肯定是萧大的啦,萧井陌-B站直播视频库,初始的几个游戏都是比较简单的游戏,但最重要的是要看它的重构过程,重要的事情说3遍,要看重构过程,要看重构过程 ,要看重构过程,你会认识到什么叫函数式编程、什么叫命令模式、什么叫工厂模式等等,好的,下面是一个我的粗糙例子,请不要模仿~

// replay.html
  <canvas class="box" id="canvas" width="500" height="500"></canvas>
  <div>
    <button type="button" id="start">start</button>
    <button type="button" id="over">over</button>
    <button type="button" id="replay">replay</button>
  </div>
// replay.js
     // 初始化相关数据
      var rect  = {
            x: 225,
            y: 225,
            w: 50,
            h: 50
          },
          delay = 0,
          commandStack = [],
          ctx = document.getElementById('canvas').getContext('2d');

      // 创建角色动作集合
      var role = {
        clear: function (x, y, w, h) {
          ctx.clearRect(x, y, w, h);
        },
        drawInit: function (x, y, w, h) {
          rect = {
            x: x,
            y: y,
            w: w,
            h: h
          };
          this.clear(0, 0, 500, 500);
          ctx.fillStyle = "#bcf";
          ctx.strokeStyle = "#888";
          ctx.fillRect(x, y, w, h);
        },
        up: function (range) {
          rect.y -= range;
          this.drawInit(rect.x, rect.y, rect.w, rect.h);
        },
        down: function (range) {
          rect.y += range;
          this.drawInit(rect.x, rect.y, rect.w, rect.h);
        },
        left: function (range) {
          rect.x -= range;
          this.drawInit(rect.x, rect.y, rect.w, rect.h);
        },
        right: function (range) {
          rect.x += range;
          this.drawInit(rect.x, rect.y, rect.w, rect.h);
        }
      }

      // 创建任务集合, 抽象为可携带参数
      var commands = {
        '119': {
          fn: 'up',
          args: [2]
        },
        '115': {
          fn: 'down',
          args: [2]
        },
        '97': {
          fn: 'left',
          args: [2]
        },
        '100': {
          fn: 'right',
          args: [2]
        },
        'drawInit': {
          fn: 'drawInit',
          args: [rect.x, rect.y, rect.w, rect.h]
        },
        'clear': {
          fn: 'clear',
          args: [0, 0, 500, 500]
        }
      }

      // 利用闭包存储任务并赋予角色动作
      var makeCommand = function (receiver, state) {
        return function () {
          receiver[state].apply(role, arguments)
        }
      }

      // 执行角色任务及将存储的任务压入回放任务队列
      function runAndPushStack (key) {
        var command = makeCommand(role, commands[key]['fn']),
            args = commands[key]['args'];

        if (command) {
          commandStack.push({
            fn: command,
            args: args || [],
            delay: (new Date()).getTime() - delay // 传入每次动作距离开始时间延迟
          });
          command.apply(role, args);
        }
      }

      // 初始化数据函数
      function initConfig () {
        delay = (new Date()).getTime();
        commandStack = [];
        rect  = {
          x: 225,
          y: 225,
          w: 50,
          h: 50
        };
      }

      // 监控键盘事件
      document.onkeypress = function (e) {
        var keyCode = e.keyCode;
        runAndPushStack(keyCode);
      }

      // 开始录制
      document.getElementById('start').onclick = function () {
        initConfig();
        document.getElementById('over').disabled = false;
        runAndPushStack('drawInit');
      }

      // 结束录制
      document.getElementById('over').onclick = function () {
        this.disabled = true;
        commandStack.push({
          fn: function () {
            alert('Thanks your watch, this play have over!');
          },
          delay: (new Date()).getTime() - delay // 传入每次动作距离开始时间延迟
        });
      }
      // 开始回放
      document.getElementById('replay').onclick = function () {
        if (!document.getElementById('over').disabled) {
          alert('请先停止录制');
          return 0;
        }
        var command;
        for (var i = 0; i < commandStack.length; i++) {
          (function (command) {
            setTimeout(function () {
              command.fn.apply(role, command.args);
            }, command.delay || 0);
          })(commandStack[i]);
        }
      }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值