基于文言文来实现竞速连连看小游戏

1,632 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第13天,点击查看活动详情

前言

看到题目可能大家就比较好奇了,文言文和游戏他沾边吗?不会是拿中文当变量的标题党吧?


机缘巧合,我在码上掘金模块发现支持的自定义语言里有一门语言叫做文言文,看了下语法还挺有意思,于是基于之前写过的一篇 竞速连连看,拿文言文的语法复刻了一下,大部分逻辑基于文言文都是可以实现的,本文重点是介绍文言文的语法,游戏玩法并没有变化,就不做赘述了。

本文用到的文言文语法

  • 数组的声明方式
吾有一列。名之曰「甲」。 // var a = [];
  • 向数组内填充元素
充「甲」以四。以二。 // a.push(4, 2);
  • 读取数组长度
夫「甲」之長。 // a.length
  • 对象声明,并声明属性
吾有一物。名之曰「甲」。其物如是。物之「「from」」者。言曰'left'是謂「甲」之物也。 // var a ={from: 'left'}
  • 数字的声明
吾有一數。名之曰「结绳计数」。 // var 结绳计数 = 0
  • 函数的声明
吾有一術。名之曰「吸星大法」。是術曰。......是謂「吸星大法」之術也。 // function 吸星大法 () {}
  • 在文言文内写js
施「(()=> {....})」

书归正传,复刻开始

  • 容器 容器是由720x450的盒子拆成的两个350x450的小盒子构成,大盒子通过flex布局水平垂直居中,小盒子也是通过flex布局实现水平拆分。
<div id="box">
    <div class="left"></div>
    <div class="right"></div>
  </div>
#box{
    width: 720px;
    height: 450px;
    display: flex;
    justify-content: space-between;
    align-items: center;
  }
  .left,.right{
    width: 350px;
    height: 450px;
    background: #fff;
    border-radius: 8px;
    overflow: hidden;
    display: flex;
    justify-content: space-around;
    align-items: center;
    flex-wrap: wrap;
    transform-style: preserve-3d;
  }
  • 声明资源
吾有一列。名之曰「圖集」。
充「圖集」以 'https://img01.yzcdn.cn/upload_files/2022/07/20/Fk1rj4gSaia1i8yD-FSO8CWLWlSu.jpg!280x280.jpg''https://img01.yzcdn.cn/upload_files/2022/03/16/Fo3SKNvQG5cIj3IspG_SOs_T216M.png!280x280.jpg''https://img01.yzcdn.cn/upload_files/2022/07/19/FsT754_weL6KZgUC2TuRWxr5zLnG.jpg!280x280.jpg''https://img01.yzcdn.cn/upload_files/2022/05/30/FguIz4XVMqAS3ft_7thNqlJrT0_F.jpg!280x280.jpg''https://img01.yzcdn.cn/upload_files/2022/05/09/FvG5_KInsbyhVq9W6xbygpo9jb9i.jpg!280x280.jpg''https://img01.yzcdn.cn/upload_files/2022/05/30/Fpht4CzextqfHA048FGU8m_t4NP5.jpeg!280x280.jpg''https://img01.yzcdn.cn/upload_files/2022/03/15/FlTBO9tItc9TXslq6wYd87udb-6t.jpg!280x280.jpg''https://img01.yzcdn.cn/upload_files/2022/03/15/Fi77MVQB0xREZRQdzaKHyHNuG-yg.jpg!280x280.jpg''https://img01.yzcdn.cn/upload_files/2022/03/16/FtBQGLwuPQJBuIHs0LjxbaSJVloV.jpg!280x280.jpg''https://img01.yzcdn.cn/upload_files/2022/03/16/FrZxLRso63OS_oKTD6xXk6Ao4Z2C.jpg!280x280.jpg''https://img01.yzcdn.cn/upload_files/2022/05/09/FvpbuQ35dFtL_oOcjJCfgPuPseIY.jpg!280x280.jpg''https://img01.yzcdn.cn/upload_files/2022/05/16/FlvZNZzU96K_d0DzxgFv3mh5IDA3.jpg!280x280.jpg'
  • 元素样式是100x100的小卡片,背景图随机生成,背景图来源于掘金商城,随机生成算法还是通过标记法去重,图片一共12张,所以我们需要生成不重复的随机顺序的12个数字,从0开始。将生成的数字以 自定义属性key记录在对应的dom上, 牌面的翻转覆盖效果通过transition配合transform来实现,不管是添加还是移除,都会应用过渡效果,所以看起来像是在翻转一样
// 样式
.left div, .right div{
    width: 100px;
    height: 100px;
    border-radius: 8px;
    cursor: pointer;
    box-shadow: inset 0 0 15px 3px rgb(12, 133, 215);
    background-position: center;
    background-size: contain;
    background-repeat: no-repeat;
    transform: rotateY(180deg);
    transition: all ease .5s;
  }
  #box .shine{
    transform: rotateZ(360deg) rotateY(360deg);
  }
  • 元素随机算法
// 通过 图长 这个变量保存之前资源 圖集 的 length var 图长 = 圖集.length
夫「圖集」之長。名之曰「图长」。
// 声明一个对象 var 左映射 = {from: 'left'}
吾有一物。名之曰「左映射」。其物如是。物之「「from」」者。言曰'left'是謂「左映射」之物也。
// 声明一个对象 var 右映射 = {from: 'left'}
吾有一物。名之曰「右映射」。其物如是。物之「「from」」者。言曰'right'是謂「左映射」之物也。
// 声明一个函数 function 随机字符 (甲) {...}
吾有一術。名之曰「随机字符」。欲行是術。必先得一數。曰「甲」乃行是術曰。
吾有一數。名之曰「字」。
// 调用箭头函数包裹的js
施「(()=> {
  do {
    字 = Math.floor(Math.random()*图长)
  } while (甲[字])
    let div = $('<div>')
  div.addClass('item')
  div.addClass('shine')
  div.attr('key', 字)
  div.css('background-image', `url(${圖集[字]})`)
  甲[字] = div
  $(`.${甲.from}`).append(div)
  })」
  // 函数结束关键字
是謂「随机字符」之術也。
  • 循环产生卡牌
// for循环 for (let i =0;i<图长;i++) {...}
為是「图长」遍。
// 随机字符(左映射) 函数调用
施「随机字符」於「左映射」。
施「随机字符」於「右映射」。
云云。
  • 核心游戏实现

因为文言文不支持for in 语法,所以核心的开始游戏是通过施「(()=> {})」语法来直接调用js 的

吾有一術。名之曰「初始化」。是術曰。
			施「(()=>{
      setTimeout(function () {
      for (let i in 左映射) {
        if (i !== 'from') {

        左映射[i].removeClass('shine')
        左映射[i].css('background-image', `url(https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/0a4ce25d48b8405cbf5444b6195928d4~tplv-k3u1fbpfcp-no-mark:0:0:0:0.awebp)`)
      }
      }
      for (let i in 右映射) {
       if (i !== 'from') {
        右映射[i].removeClass('shine')
        右映射[i].css('background-image', `url(https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/0a4ce25d48b8405cbf5444b6195928d4~tplv-k3u1fbpfcp-no-mark:0:0:0:0.awebp)`)
      }
      }
      let time = new Date().getTime()
      let timer = setInterval(() => {
        计时数 = (new Date().getTime() - time) / 1000
        $('#time').text(计时数 + '秒')
      }, 10)
      $('.item').click(function () {
        if ($(this).hasClass('shine')) {
          return false
        }
        let key = Number($(this).attr('key'))
        $(this).addClass('shine')
        $(this).css('background-image', `url(${圖集[key]})`)
        if (緩存.length === 1) {
          if (緩存.find(v => v === key) !== undefined) {
            緩存 = []
            结绳计数++
            console.log(结绳计数)
            if (结绳计数 >= 12) {
              clearInterval(timer)
              $('#time').text('游戏结束,用时' + 计时数 + '秒')
            }
            return false
          } else {
            let self = this
            let inx = 緩存[0]
            緩存 = []
            let tm = setTimeout(function () {
              $(`.item[key=${inx}]`).removeClass('shine')
              $(`.item[key=${inx}]`).css('background-image', `url(https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/0a4ce25d48b8405cbf5444b6195928d4~tplv-k3u1fbpfcp-no-mark:0:0:0:0.awebp)`)
              $(self).removeClass('shine')
              $(self).css('background-image', `url(https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/0a4ce25d48b8405cbf5444b6195928d4~tplv-k3u1fbpfcp-no-mark:0:0:0:0.awebp)`)

            }, 500)
          }
        } else {
          緩存.push(key)
        }

      })
    }, 3000)
      })」。
    是謂「初始化」之術也。
    施「(()=>{
            setTimeout(function () {
                    初始化()
            },3000)
    })」。

码上掘金

文言文想要在码上掘金正常运行,需要添加文言文依赖

  • Script Tab 下选择 Custom 语言
  • 第一行粘贴下面的文本
#!/jcode/lang/wenyan https://xitu.github.io/jcode-languages/dist/lang-wenyan.json
  • 在外部资源那里引入依赖https://cdn.jsdelivr.net/npm/jcode-tools 和https://cdn.jsdelivr.net/npm/@wenyanlang/core/index.min.js

image.png

  • 在html的部分调用解析自定义语言的方法
<script>
  (async function() {
    const code = await JCode.getCustomCode();
    const jscode = Wenyan.compile(code, {
      logCallback: () => {},
      importPaths: ['https://akira-cn.github.io/wenyan-demos/'],
      allowHttp: true,
    });
    Wenyan.evalCompiled(`(async () => {${jscode}})()`);
  }());
</script>

image.png

码上掘金展示