从本篇起,我将在此展示制作一些HTML5小游戏的过程和经验。本文描述的是一个经典又简单的小游戏,连连看。
1. 计划
1.1 目标
- 快速建立一个连连看游戏原形。
- 能玩就行。
1.2 游戏特性介绍
- 游戏展示一个m * n大小的表格
- 表格每个格子里面有一个图标/符号
- 每个图标都是成对出现
- 玩家需要找到每对匹配的图标/符号
- 如果玩家选中的两个图标/符号匹配并且其连线转折次数小于等于2次,则可以消除它们
- 连线不能通过未消除的图标/符号
- 连线可以通过已消除图标/符号
- 连线可以通过边框空白区
- 连线不能是斜线
1.3 技术选型
- HTML5 网页
- JavaScript ES5
- CSS
- 为简单起见使用DIV来显示表格,不用游戏引擎,用字母和数字来代表图标
2. 核心算法
2.1 表格初始化算法
2.1.1 需求
- 表格需要填满
- 每个图标都要成对出现
- 图标的位置随机
2.1.2 实现
我们使用随机算法来实现。
* 按总格子数的一半生成随机图标/符号序列
* 把序列复制一份追加到尾部,这样保证每个图标都是成对的
* 随机从序列中取出图标/符号填充到表格中
var symbols = 'ABCDEFGHIGKLMNOPQRSTUVWXYZ123456789';
function reset(){
var all = count = nx*ny;
var halfAll = all/2;
var tmp = [];
for(var i=0;i<halfAll;i++){
var c = symbols.charAt(Math.floor(Math.random()*35));
tmp.push(c);
tmp.push(c);
}
for(var i=all-1;i>=0;i--){
var r = Math.floor(Math.random()*i);
var c = tmp.splice(r,1);
var y = Math.floor(i/nx);
var x = i-y*nx;
fc(x+1,y+1).innerHTML = c;
}
}
2.2 路径查找算法
2.2.1 需求
消去规则:如果玩家先后选择的两个格子中图标相同而且可以在两次转弯内连通,即可消去。
2.2.2 转弯的判断
如下图所示
对于路径上连续的3个位置,如果第一个和第三个位置的x, y坐标都不同,说明在第二个位置转了一个弯。否则同一行,或者列的话,x,y 坐标总有一个相同。
2.2.3 路径的查找
使用深度优先的方式递归地求解,用一个栈来保存路径:
- 转弯次数不能超过2
- 如果当前格子同目标相同则表示找到了路径
- 如果不同就把当前位置入栈,然后递归地尝试其上下左右的邻居
- 邻居不能超过边界
- 邻居不能已经在路径上
function findPath(c/*当前位置*/, target/*目标位置*/, pathStack/*路径栈*/, trunCount/*已经转过的弯*/){
if(!c){
return false;
}
var c_2 = pathStack[pathStack.length-2];
if(c_2&&c_2.x!=c.x&&c_2.y!=c.y){
if(++trunCount>2){
return false;
}
}
if(c == target){
pathStack.push(c);
return true;
}
if(c.innerHTML != empty){
return false;
}
if(pathStack.indexOf(c)>=0){
return false;
}
pathStack.push(c);
var nexts = neibors(c);//neibors函数用于查找当前位置的邻居位置,上下左右
for(var i=0;i<nexts.length;i++){
if(findPath(nexts[i], target, pathStack, trunCount)){
return true;
}
}
pathStack.pop();
return false;
}
3. 游戏渲染
为了简单,这里使用简单的DIV+CSS来显示格子,使用字母数字作为图标/符号。对于nx * ny的游戏,实际上生成了(nx+2) * (ny+2)个格子,因为最外面一圈作为边框(border),边框不填充图标,但可以作为连通的路径的一部分。
.border{
display: inline-block;
width: 40px;
height:40px;
font-weight: 600;
font-size: 36px;
margin:1px;
}
.border.showPath{
background-color:#99FF00;
}
.cell{
display: inline-block;
width: 40px;
height:40px;
border:1px solid #0099FF;
text-align: center;
font-weight: 600;
font-size:36px;
background-color:#FFFFFF;
color: #000000;
}
.cell.selected{
background-color:#3399FF;
color: #FFFFFF;
}
.cell.showPath{
background-color:#99FF00;
}
4. 参数调优
游戏好不好玩,其实参数调整非常重要。对于连连看这个游戏主要需要考虑的参数有:
- nx 与 ny即有多少行多少列。少了太简单,多了太难
- 图标/符号的个数,当nx * ny固定的时候,图标越多越难匹配
5. 可能的改进
5.1 功能上的改进
- 游戏界面可以添加开始按钮
- 游戏可以添加计时或倒计时功能
- 游戏可以提供不同难度
- 游戏可以为玩家在找不到的时候提供提示
- 游戏可以在无法配对时提供图标重排
- 游戏流程可以用状态机来管理,使得游戏可以玩很多局
- 游戏可以提供分享功能来在社交媒体上晒成绩
5.2 界面上的改进
- 使用真正的图标来填充,注意版权问题
- 重新设计布局,使其自动适应桌面和手机等不同屏幕
- 为游戏加上音效,如背景音乐,按钮音效,消除音效等,注意版权问题
- 为消除增加动画
- 为最后赢得游戏增加祝贺的动画
6. 代码及演示
请在这里查看代码及运行结果。