持续创作,加速成长!这是我参与「掘金日新计划 · 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
- 在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>