我正在参加「初夏创意投稿大赛」详情请看:初夏创意投稿大赛
序言
夏天到啦!不如来玩合成大冰棍,清爽加倍,快乐加倍!
设计思路
我打算做的是类似于消消乐 + 2048 那种,找到两个相同的元素,点击两个相同的元素就可以合成另一个 level 更高的元素。也就是 1 + 1 = 2... ,最后算到最大的一个数就算游戏成功。
- 整个设计是 5*5 的格子(当然也可以更多)
- 游戏开始之前,每一个格子随机生成一个背景图片(待匹配的元素)
- 如果点击了两个相同的元素,后一个点击的元素会合成成 level 更高的元素,前一个元素会再次随机生成背景图片
- 如果合成的元素是最高等级的(大冰棍),游戏成功
ps:我选择了 16 张图片,1
9 张图片可以随机生成, 1016 张图片只能通过合成
代码实现
创建格子
鱿鱼容器内部全是格子,所以直接使用 grid 布局
<div class="summmer_wrapper">
<div class="eliminate_wrapper"></div>
</div>
.eliminate_wrapper {
display: grid;
grid-template-columns: repeat(5, 120px);
grid-template-rows: repeat(5, 120px);
grid-row-gap: 10px;
grid-column-gap: 10px;
}
一开始无脑冲,直接 html 拉满,但是因为我的格子有 25 个,总不能一个个写到 25 吧这也太拉了
<div class="eliminate_wrapper">
<div id="xxx_1"><div>... ...</div></div>
</div>
然后想到动态创建元素, 但是如果多次使用 appendChild,会造成大量的回流,所以想到了碎片节点
const eliminate = document.getElementsByClassName('eliminate_wrapper')[0];
for (let i = 0; i < 25; i++) {
let elem = document.createElement('div');
elem.id = `eliminate_${i + 1}`;
oFrag.appendChild(elem);
}
eliminate.appendChild(oFrag);
创建完格子之后给每一个格子加上随机背景(待消除的元素)
//生成从minNum到maxNum的随机数
function randomNum(minNum, maxNum) {
return parseInt(Math.random() * (maxNum - minNum + 1) + minNum, 10);
}
for (let i = 0; i < eliminate.children.length; i++) {
// 生成1~9的随机图片
let n = randomNum(1, 9);
eliminate.children[i].style.backgroundImage = `url('${imgs[n - 1]}')`;
eliminate.children[i].style.backgroundRepeat = 'no-repeat';
eliminate.children[i].style.backgroundSize = '100%';
}
然后随便加点绿绿蓝蓝的背景色,显得非常的解暑有没有!
如何选中元素 - 事件代理
一开始想着给每个元素加点击事件,但是如果使用循环绑定,就会非常消耗新能,而且在后面动态添加无法执行,所以使用事件代理
是不是很久没有用原生了!来复习一下事件代理吧!
事件代理:不亲自绑定事件,委托给父级,再通过寻找事件源去处理有(多个元素需要绑定事件的时候,建议使用事件委托)
eliminate.onclick = e => {
let tar = e.target || e.srcElement;
// dosomething
};
核心逻辑
- 创建一个数组来保存选中的元素,点击选中元素,就把元素 push 进数组
- 如果两次点击 id 相同的元素,认为是取消选中
- 如果数组中两个元素 id 不相等且背景相等则匹配成功,否则匹配失败
- 数组中两个元素匹配成功,arr[1]的元素的背景替换成更高 level 的背景,随机生成 arr[0]的元素的背景
- 如果 arr[1]的背景是最高等级的背景,游戏成功,显示成功动画,否则清空数组
let selectedPair = [];
eliminate.onclick = e => {
let tar = e.target || e.srcElement;
if (tar === selectedPair[0] && selectedPair.length === 1) {
selectedPair[0].className = '';
selectedPair = [];
return;
}
if (
tar.id.indexOf('eliminate') !== -1 &&
selectedPair.indexOf(tar) === -1 &&
selectedPair.length < 2
) {
selectedPair.push(tar);
tar.className = 'choose';
}
if (selectedPair.length === 2) {
if (selectedPair[0].style.backgroundImage === selectedPair[1].style.backgroundImage) {
let addImg = parseInt(selectedPair[1].style.backgroundImage.split('ice-cream-img/')[1][0]);
if (addImg <= 15) {
selectedPair[1].style.backgroundImage = `url('../big-ice-cream/ice-cream-img/${
addImg + 1
}.png')`;
selectedPair[0].style.backgroundImage = `url('${imgs[randomNum(1, 9) - 1]}')`;
selectedPair[0].style.backgroundRepeat = selectedPair[1].style.backgroundRepeat =
'no-repeat';
}
if (addImg >= 15) {
selectedPair[1].className += ' success';
restart.style.display = 'block';
} else {
selectedPair[0].className = selectedPair[1].className = '';
selectedPair = [];
}
} else {
selectedPair[1].className = '';
selectedPair.pop();
}
}
};
挑战成功
合成大冰棍之后,弹出成功按钮,并加上一些动画,不然太丑了
再加上游戏说明,完成
马上耍一把看看!