我大抵是废了φ(..) ,横竖都学不进去,上课知识不进脑子,学习光想划水摸鱼,心中仅剩的良知告诉我这样下去是铁定不行的哇,既然学不进去,何不打把游戏,既然要打游戏,为啥不自己写个小游戏嘞٩(๑>◡<๑)۶?手动狗头。

虽然我有着强烈的制作意愿,但是当初学的unity3D的知识早就还给老师了,而且就我一个人的话,做大型游戏先不说我一个人干不干的过来,首要面对的问题就是,没这个能力你知道吧。于是我想起来了小时候第一次去科技馆,玩的华容道,碰巧之前学过一点canvas,做的话应该是可以做的,虽然我上次用canvas还是在上次,那么......

好了,废话不多说,先写html页面吧。

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>小辣鸡毛不会的华容道</title><style>*{margin: 0 ;padding: 0 ;}</style>
</head>
<body><canvas id="canvas" width="240" height="240"></canvas><script  type="text/javascript" src="./index.js"></script>
</body>
</html>

有一说一,这个html页面是真的简单,毕竟只用了一个canvas标签,也就没啥好说的了对吧,那接下来就上js吧。

我在写html的时候有多轻松,在写js的时候就有多难受。我最初以为写一个华容道是一件很简单的事情,毕竟用canvas画几个方块,然后写上左右移动的函数,写上碰撞检测的函数,写上判断通关的函数,这个游戏也就写完了。但是开始写了才发现,貌似实际情况和我幻想的有那么亿丝丝的不一样,其他几个都好写,就是这个碰撞检测有些难顶。怎么判断对应位置是否有方块?怎么判断墙在何处?要是直接用canvas划线来画方块的话,判断起来当是很困难的,虽然没有细细思考这样做的可行性是多少,但是哪怕能做,也一定是比较复杂的,而我之所以要写这个小游戏,不就是为了放松吗,所以此刻摆在我面前的有两条路,一条是放弃,另一条还是放弃。

当然,放弃是不可能放弃的,因为我想到了一个好办法,那就是用一个数组,来存值,存对应位置是否有方块,以及方块的大小形状都是啥。就好比接下来这个数组。

[[['张飞','dir'],['曹操','big'],['曹操','big'],['赵云','dir']],[['张飞','dir'],['曹操','big'],['曹操','big'],['赵云','dir']],[['马超','dir'],['关羽','bro'],['关羽','bro'],['黄忠','dir']],[['马超','dir'],['小兵','squ'],['小兵','squ'],['黄忠','dir']],[['小兵','squ'],[null,null],[null,null],['小兵','squ']],
]

在这个数组里,每一个子数组都代表着一行中的四个方格,这个子数组中的每个子数组,第一个属性是当前方格的棋子名称,以及这个棋子的形状是怎么样的,dir是竖长方形,bro是横长方形,squ是只占当前一个格子的小正方形,big是四个格子之大的大正方形。

既然有了记录当前状态的数组,那么就要开始画棋盘和棋子了,我先定义了棋子的构造函数

    function Rect(x, y, width, height, color) {this.x = xthis.y = ythis.width = widththis.height = heightthis.color = color}Rect.prototype.draw = function () {ctx.beginPath()ctx.fillStyle = this.colorctx.fillRect(this.x, this.y, this.width, this.height)//从x,y处填充矩形,宽度为width,高度为heightctx.strokeRect(this.x, this.y, this.width, this.height)//从x,y处绘制矩形,宽度为width,高度为height}

接下来就是画初始的棋盘了,我设置的每一个格子的宽度高度都是20,想要改变棋子大小的同学们记得将四种构造函数对应的数值一同变动一二。对于四种方块的绘制方法,我的思路是在遍历到第一个值的时候,也就是这个棋子的左上角那个方块的时候,绘制整个棋子,同时将棋子其他位置的值置为0,避免重复绘制。写好了绘制四种方块的方法后,我就用了一个双重for循环遍历数组,绘制整张图。最后则是判断是否闯关成功。

drawCheeks = () =>{ctx.beginPath()ctx.strokeRect(20,20,80,100)ctx.stroke()ctx.closePath()let temp = JSON.parse(JSON.stringify(cheeks));let cheekColor = []cheekColor['张飞'] = 'black';cheekColor['赵云'] = 'brown';cheekColor['马超'] = 'silver';cheekColor['关羽'] = 'red';cheekColor['黄忠'] = 'yellow';cheekColor['曹操'] = 'blue';cheekColor['小兵'] = 'green';function square(i,j,color){var cheek = new Rect(20+20*j,20+20*i,20,20,color);cheek.draw();temp[i][j] = 0;}function Bigsquare(i,j,color){var cheek = new Rect(20+20*j,20+20*i,40,40,color);cheek.draw();temp[i][j] = 0;temp[i+1][j] = 0;temp[i][j+1] = 0;temp[i+1][j+1] = 0;}function dirOblang(i,j,color){var cheek = new Rect(20+20*j,20+20*i,20,40,color);cheek.draw();temp[i][j] = 0;temp[i+1][j] = 0;}function broOblang(i,j,color){var cheek = new Rect(20+20*j,20+20*i,40,20,color);cheek.draw();temp[i][j] = 0;temp[i][j+1] = 0;}function drawSqare(tag,i,j,color){if(tag == 'squ'){return square(i,j,color);}else if(tag == 'big'){return Bigsquare(i,j,color);}else if(tag == 'dir'){return dirOblang(i,j,color);}else if(tag == 'bro'){return broOblang(i,j,color);}}for(let i=0;i<temp.length;i++){for(let j=0;j<temp[0].length;j++){if(temp[i][j] === null){continue;}else{drawSqare(temp[i][j][1],i,j,cheekColor[temp[i][j][0]])}}}if(temp[3][2][0] == "曹操"){const con = confirm(`闯关成功,本次共走了${this.grade}步,要进入下一关吗`)if (con) {custom++;cheeks = customs[custom];drawCheeks();}return}}drawCheeks();

棋盘绘制成功后如图所示,emmm,有点简陋,但是无妨,只是没加皮肤罢了,以后有机会一定会加上的_(:3」∠)_。

那接下来就要写点击的函数了,这块也不难,就是根据点击事件来判断点击的区域是否位于棋盘内,位于棋盘内的话则判断选中哪个棋子,相信大家都能看明白,也就不做过多的解释了。

document.addEventListener("click",function(e){let j = Math.floor((e.pageX-20)/20);let i = Math.floor((e.pageY-20)/20);if(i<5 && j<4){clickIt(i,j)}})clickIt = function(i,j){if(cheeks[i][j]){let cheekVal = cheeks[i][j][0];if(cheeks[i][j][1] == 'dir'){if(i>0 && cheeks[i-1][j][0]==cheekVal){now(i-1,j,cheekVal,cheeks[i][j][1]);}else{now(i,j,cheekVal,cheeks[i][j][1]);}}else if(cheeks[i][j][1] == 'bro'){if(j>0 && cheeks[i][j-1][0]==cheekVal){now(i,j-1,cheekVal,cheeks[i][j][1]);}else{now(i,j,cheekVal,cheeks[i][j][1]);}}else if(cheeks[i][j][1] == 'big'){if(i>0 && cheeks[i-1][j][0]==cheekVal){if(j>0 && cheeks[i][j-1][0]==cheekVal){now(i-1,j-1,cheekVal,cheeks[i][j][1]);}else{now(i-1,j,cheekVal,cheeks[i][j][1]);}}else{if(j>0 && cheeks[i][j-1][0]==cheekVal){now(i,j-1,cheekVal,cheeks[i][j][1]);}else{now(i,j,cheekVal,cheeks[i][j][1]);}}}else{now(i,j,cheekVal,cheeks[i][j][1]);}}}now = function(i,j,cheekVal,tag){x = j;y = i;val = cheekVal;cheekTag = tag;}

接下来就是监听键盘了,准确来说是监听上下左右四个按键,好根据当前选中的方块和按的是哪个按键来做出相应的动作。

    document.onkeydown = function (e) {e = e || window.event// 左37  上38  右39  下40switch (e.keyCode) {case 37:toLeft();breakcase 38:toUp();break case 39:toRight();breakcase 40:toDown();break}}

监听完键盘事件,就要写执行对应动作的函数了,这里四个函数大体上是相同的,我就以向左移动的函数为例说说吧。这块代码我写的其实不好,毕竟使用了过多ifelse,如果以后去工作了的话大概率会被测试同学打,但是谁叫我现在还在上学嘞(灬°ω°灬),本来其实是想要多写几个函数优化一下代码结构的,但是吧,不想写了。。。。

这串代码是根据选中位置,因为前面处理点击的时候已经自动将点击位置转换为点击的棋子的左上角了,因此这里只需要判断当前棋子是否是最左侧那一列的棋子,是的话无法移动,否则判断该棋子若左移的话是否会碰到其他棋子,会的话则无法移动。要是可以移动的话,就对储存棋盘状态的数组进行处理,然后重新执行绘制函数。

    toLeft = () =>{if(x!=0){tag = cheekTag;if(tag == 'bro'){if(cheeks[y][x-1][0] === null){cheeks[y][x+1] = [null,null];cheeks[y][x-1] = [val,tag];}}else if(tag == 'dir'){if(cheeks[y][x-1][0] === null && cheeks[y+1][x-1][0] === null){cheeks[y][x-1] = [val,tag];cheeks[y+1][x-1] = [val,tag];cheeks[y][x] = [null,null];cheeks[y+1][x] = [null,null];}}else if(tag == 'big'){if(cheeks[y][x-1][0] === null && cheeks[y+1][x-1][0] === null){cheeks[y][x-1] = [val,tag];cheeks[y+1][x-1] = [val,tag];cheeks[y][x+1] = [null,null];cheeks[y+1][x+1] = [null,null];}}else if(tag == 'squ'){if(cheeks[y][x-1][0] === null){cheeks[y][x-1] = [val,tag];cheeks[y][x] = [null,null];}}console.log(cheeks)ctx.clearRect(0, 0, canvas.width, canvas.height)grade++;drawCheeks();}}

js的全部代码如下,目前只在关卡的数组里写了三关,即便如此我目前还是一关也没有通过......

let x,y,val,cheekTag,grade=0,custom = 0;
play()
function play() {const canvas = document.getElementById('canvas')const ctx = canvas.getContext('2d')let customs = [[[['张飞','dir'],['曹操','big'],['曹操','big'],['小兵','squ']],[['张飞','dir'],['曹操','big'],['曹操','big'],['小兵','squ']],[['马超','dir'],['赵云','dir'],['黄忠','dir'],['小兵','squ']],[['马超','dir'],['赵云','dir'],['黄忠','dir'],['小兵','squ']],[[null,null],['关羽','bro'],['关羽','bro'],[null,null]],],[[['赵云','dir'],['曹操','big'],['曹操','big'],['小兵','squ']],[['赵云','dir'],['曹操','big'],['曹操','big'],['小兵','squ']],[['关羽','bro'],['关羽','bro'],['小兵','squ'],['小兵','squ']],[['马超','dir'],['张飞','bro'],['张飞','bro'],['黄忠','dir']],[['马超','dir'],[null,null],[null,null],['黄忠','dir']],],[[['张飞','dir'],['曹操','big'],['曹操','big'],['赵云','dir']],[['张飞','dir'],['曹操','big'],['曹操','big'],['赵云','dir']],[['马超','dir'],['关羽','bro'],['关羽','bro'],['黄忠','dir']],[['马超','dir'],['小兵','squ'],['小兵','squ'],['黄忠','dir']],[['小兵','squ'],[null,null],[null,null],['小兵','squ']],]]let cheeks = customs[custom];function Rect(x, y, width, height, color) {this.x = xthis.y = ythis.width = widththis.height = heightthis.color = color}Rect.prototype.draw = function () {ctx.beginPath()ctx.fillStyle = this.colorctx.fillRect(this.x, this.y, this.width, this.height)//从x,y处填充矩形,宽度为width,高度为heightctx.strokeRect(this.x, this.y, this.width, this.height)//从x,y处绘制矩形,宽度为width,高度为height}x=0,y=0,val=1;//默认选中左上角的方块drawCheeks = () =>{ctx.beginPath()ctx.strokeRect(20,20,80,100)ctx.stroke()ctx.closePath()let temp = JSON.parse(JSON.stringify(cheeks));let cheekColor = []cheekColor['张飞'] = 'black';cheekColor['赵云'] = 'brown';cheekColor['马超'] = 'silver';cheekColor['关羽'] = 'red';cheekColor['黄忠'] = 'yellow';cheekColor['曹操'] = 'blue';cheekColor['小兵'] = 'green';function square(i,j,color){var cheek = new Rect(20+20*j,20+20*i,20,20,color);cheek.draw();temp[i][j] = 0;}function Bigsquare(i,j,color){var cheek = new Rect(20+20*j,20+20*i,40,40,color);cheek.draw();temp[i][j] = 0;temp[i+1][j] = 0;temp[i][j+1] = 0;temp[i+1][j+1] = 0;}function dirOblang(i,j,color){var cheek = new Rect(20+20*j,20+20*i,20,40,color);cheek.draw();temp[i][j] = 0;temp[i+1][j] = 0;}function broOblang(i,j,color){var cheek = new Rect(20+20*j,20+20*i,40,20,color);cheek.draw();temp[i][j] = 0;temp[i][j+1] = 0;}function drawSqare(tag,i,j,color){if(tag == 'squ'){return square(i,j,color);}else if(tag == 'big'){return Bigsquare(i,j,color);}else if(tag == 'dir'){return dirOblang(i,j,color);}else if(tag == 'bro'){return broOblang(i,j,color);}}for(let i=0;i<temp.length;i++){for(let j=0;j<temp[0].length;j++){if(temp[i][j] === null){continue;}else{drawSqare(temp[i][j][1],i,j,cheekColor[temp[i][j][0]])}}}if(temp[3][2][0] == "曹操"){const con = confirm(`闯关成功,本次共走了${this.grade}步,要进入下一关吗`)if (con) {custom++;cheeks = customs[custom];drawCheeks();}return}}drawCheeks();document.addEventListener("click",function(e){let j = Math.floor((e.pageX-20)/20);let i = Math.floor((e.pageY-20)/20);if(i<5 && j<4){clickIt(i,j)}})clickIt = function(i,j){if(cheeks[i][j]){let cheekVal = cheeks[i][j][0];if(cheeks[i][j][1] == 'dir'){if(i>0 && cheeks[i-1][j][0]==cheekVal){now(i-1,j,cheekVal,cheeks[i][j][1]);}else{now(i,j,cheekVal,cheeks[i][j][1]);}}else if(cheeks[i][j][1] == 'bro'){if(j>0 && cheeks[i][j-1][0]==cheekVal){now(i,j-1,cheekVal,cheeks[i][j][1]);}else{now(i,j,cheekVal,cheeks[i][j][1]);}}else if(cheeks[i][j][1] == 'big'){if(i>0 && cheeks[i-1][j][0]==cheekVal){if(j>0 && cheeks[i][j-1][0]==cheekVal){now(i-1,j-1,cheekVal,cheeks[i][j][1]);}else{now(i-1,j,cheekVal,cheeks[i][j][1]);}}else{if(j>0 && cheeks[i][j-1][0]==cheekVal){now(i,j-1,cheekVal,cheeks[i][j][1]);}else{now(i,j,cheekVal,cheeks[i][j][1]);}}}else{now(i,j,cheekVal,cheeks[i][j][1]);}}}now = function(i,j,cheekVal,tag){x = j;y = i;val = cheekVal;cheekTag = tag;}document.onkeydown = function (e) {e = e || window.event// 左37  上38  右39  下40switch (e.keyCode) {case 37:toLeft();breakcase 38:toUp();break case 39:toRight();breakcase 40:toDown();break}}toLeft = () =>{if(x!=0){tag = cheekTag;if(tag == 'bro'){if(cheeks[y][x-1][0] === null){cheeks[y][x+1] = [null,null];cheeks[y][x-1] = [val,tag];}}else if(tag == 'dir'){if(cheeks[y][x-1][0] === null && cheeks[y+1][x-1][0] === null){cheeks[y][x-1] = [val,tag];cheeks[y+1][x-1] = [val,tag];cheeks[y][x] = [null,null];cheeks[y+1][x] = [null,null];}}else if(tag == 'big'){if(cheeks[y][x-1][0] === null && cheeks[y+1][x-1][0] === null){cheeks[y][x-1] = [val,tag];cheeks[y+1][x-1] = [val,tag];cheeks[y][x+1] = [null,null];cheeks[y+1][x+1] = [null,null];}}else if(tag == 'squ'){if(cheeks[y][x-1][0] === null){cheeks[y][x-1] = [val,tag];cheeks[y][x] = [null,null];}}console.log(cheeks)ctx.clearRect(0, 0, canvas.width, canvas.height)grade++;drawCheeks();}}toRight = () =>{if(x!=3){tag = cheekTag;if(tag == 'bro' && x <2){if(cheeks[y][x+2][0] === null){cheeks[y][x] = [null,null];cheeks[y][x+2] = [val,tag];}}else if(tag == 'dir'){if(cheeks[y][x+1][0] === null && cheeks[y+1][x+1][0] === null){cheeks[y][x+1] = [val,tag];cheeks[y+1][x+1] = [val,tag];cheeks[y][x] = [null,null];cheeks[y+1][x] = [null,null];}}else if(tag == 'big' && x <2){if(cheeks[y][x+2][0] === null && cheeks[y+1][x+2][0] === null){cheeks[y][x+2] = [val,tag];cheeks[y+1][x+2] = [val,tag];cheeks[y][x] = [null,null];cheeks[y+1][x] = [null,null];}}else{if(cheeks[y][x+1][0] === null){cheeks[y][x+1] = [val,tag];cheeks[y][x] = [null,null];}}ctx.clearRect(0, 0, canvas.width, canvas.height)grade++;drawCheeks();}}toUp = () =>{if(y!=0){tag = cheekTag;if(tag == 'dir'){if(cheeks[y-1][x][0] === null){cheeks[y+1][x] = [null,null];cheeks[y-1][x] = [val,tag];}}else if(tag == 'bro'){if(cheeks[y-1][x][0] === null && cheeks[y-1][x+1][0] === null){cheeks[y-1][x] = [val,tag];cheeks[y-1][x+1] = [val,tag];cheeks[y][x] = [null,null];cheeks[y][x+1] = [null,null];}}else if(tag == 'big'){if(cheeks[y-1][x][0] === null && cheeks[y-1][x+1][0] === null){cheeks[y-1][x] = [val,tag];cheeks[y-1][x+1] = [val,tag];cheeks[y+1][x] = [null,null];cheeks[y+1][x+1] = [null,null];}}else{if(cheeks[y-1][x][0] === null){cheeks[y-1][x] = [val,tag];cheeks[y][x] = [null,null];}}ctx.clearRect(0, 0, canvas.width, canvas.height)grade++;drawCheeks();}}toDown = () =>{if(y!=4){tag = cheekTag;if(tag == 'dir'){if(y<3 && cheeks[y+2][x][0] === null){cheeks[y][x] = [null,null];cheeks[y+2][x] = [val,tag];}}else if(tag == 'bro'){if(cheeks[y+1][x][0] === null && cheeks[y+1][x+1][0] === null){cheeks[y+1][x] = [val,tag];cheeks[y+1][x+1] = [val,tag];cheeks[y][x] = [null,null];cheeks[y][x+1] = [null,null];}}else if(y<3 && tag == 'big'){if(cheeks[y+2][x][0] === null && cheeks[y+2][x+1][0] === null){cheeks[y+2][x] = [val,tag];cheeks[y+2][x+1] = [val,tag];cheeks[y][x] = [null,null];cheeks[y][x+1] = [null,null];}}else{if(cheeks[y+1][x][0] === null){cheeks[y+1][x] = [val,tag];cheeks[y][x] = [null,null];}}ctx.clearRect(0, 0, canvas.width, canvas.height)grade++;drawCheeks();}}
}

做的很简陋,玩的时候每次点击方块,移动方块后都要重新点击,导致游戏体验很差。虽说知道要如何去改进,但是现在又突然间有了学习的动力,改进这事,以后有机会再说吧。

结果视频:

1679730629453

如何用canvas制作一个华容道小游戏(乞丐版)相关推荐

  1. python连连看小游戏_利用Python制作一个连连看小游戏,边学边玩!

    导语 今天我们将制作一个连连看小游戏,让我们愉快地开始吧~ 开发工具 Python版本:3.6.4 相关模块: pygame模块: 以及一些Python自带的模块 环境搭建 安装Python并添加到环 ...

  2. 小福利,用Excel VBA编程制作一个变色小游戏

    小福利,用Excel VBA编程制作一个变色小游戏 设计思想:在正方形的四条边上都是设置循环函数,不断改变颜色和单元格里面的数值. Option ExplicitSub 按钮1_Click() Dim ...

  3. android打地鼠设计报告,android开发中利用handler制作一个打地鼠小游戏

    android开发中利用handler制作一个打地鼠小游戏 发布时间:2020-11-25 15:21:11 来源:亿速云 阅读:136 作者:Leah 这期内容当中小编将会给大家带来有关androi ...

  4. 基于 Vue 制作一个猜拳小游戏

    目录 前言: 项目效果展示: 对应素材: 代码实现思路: 实现代码: 总结: 前言: 在工作学习之余玩一会游戏既能带来快乐,还能缓解生活压力,跟随此文一起制作一个小游戏吧. 描述: 石头剪子布,是一种 ...

  5. python制作阴阳师脚本_利用python制作一个阴阳师小游戏

    利用python制作一个阴阳师小游戏 发布时间:2020-11-27 13:59:49 来源:亿速云 阅读:84 这期内容当中小编将会给大家带来有关利用python制作一个阴阳师小游戏,文章内容丰富且 ...

  6. 教你前端如何用js写一个跑酷小游戏

    在线体验地址:http://summer.pkec.net/ 源码地址:https://gitee.com/ihope_top/juejin-summer 前言 不知不觉夏天又到了,提到夏天你们能想到 ...

  7. 如何用mind+制作一个语音小助手

    要求: 用mind+的实时模式来制作一个语音小助手来进行语音对话,可以实现语音问答,语音学习.前者指的是用户可以与语音智能小助手形成问答的形式,语音学习,后者语音学习的指的是采取机自我学习的形式,即语 ...

  8. 基于java制作一个飞机小游戏(学习心得)

    emmm,第一篇博客 用了这么久的csdn,都是在观摩大佬们发帖,一只小萌新瑟瑟发抖,不敢说话,甚 至连代码也不能完全读懂.假期在b站自学(可以说是复习)了java课程,尚学堂的 2018版.链接如下 ...

  9. 怎样用HTML5 Canvas制作一个简单的游戏

    为了让大家清楚HTML5制作游戏的简单流程,所以先了制作一个非常简单的游戏,来看一看这个过程.   游戏非常简单,无非就是英雄抓住怪物就得分,然后游戏重新开始,怪物出现在地图的随机位置,英雄初始化在地 ...

最新文章

  1. java学习路线导航【教学视频+博客+书籍整理】
  2. element显示true或者false_vue+element-ui实现行数可控的表格输入
  3. 牛式 Prime Cryptarithm
  4. 让ASP.NET5在Jexus上飞呀飞
  5. OSPF动态路由协议(了解ospf,RIP协议,外部网关协议内部网关协议,ospf工作过程,选举过程,ospf邻居关系7个状态)
  6. 诺基亚AirScale支持低频段和高频段5G服务 确保运营商投资收入
  7. MFC中获取App,MainFrame,Doc和View类等指针的方法
  8. windows找不到文件gpedit.msc_u盘插入电脑在windows却找不到u盘的解决办法【详解】...
  9. ATmega328芯片-“变身”-温度计-,附示例教程
  10. MySQL社区版下载地址
  11. Android、Symbian系统手机通讯录和Google Gmai同步
  12. 光标跳转c语言,“乱跑”的光标!C语言小程序:用在舍友电脑上试试!送源码...
  13. 编程灵异事件簿(一)
  14. 基于量化交易回测的金融股票案例基础知识
  15. 【设计模式】简单工厂模式+工厂方法模式+抽象工厂模式
  16. slf4j没有在linux中生成日志,slf4j日志记录问题 - 未生成日志文件
  17. 基于httpx和pyside2的哔哩哔哩(bilibili)-视频下载程序
  18. 一起来做NES开发(1)
  19. 题目4:常微分方程初值问题
  20. 代码规范 详细解释 husky、prettier、eslint、lint-staged 的作用和使用

热门文章

  1. 【二分】Haybale Feast
  2. 微信公众平台测试号管理接口配置信息配置失败
  3. 画论42 茅一相《绘妙》
  4. 微信公众号url认证(服务器认证)
  5. 配置双系统开机选择系统的倒计时
  6. Unity 贝塞尔曲线
  7. 【SpeechX—统一高性能语音部署工具】SpeechX Architecture
  8. JAVA对比崔克,【内含投票】棋逢对手!闪电Tarmac SL6 Comp与崔克Émonda SL6详细测评,你喜欢哪款?...
  9. 相机的内参会改变吗_相机内参外参及成像过程
  10. 1、Nepxion Discovery:Spring Cloud灰度发布神器