课后作业
- 添加重新开始游戏的按钮及逻辑
- 添加记录历史最高分的逻辑
- 响应式布局的样式
在线演示: https://inscode.csdn.net/@willin/girl-3-2048
重新开始游戏按钮
首先确认一下开始函数的逻辑:
function startGame() {
initializeGameBoard();
addRandomTile();
addRandomTile();
generateGameBoard();
document.removeEventListener('keydown', handleKeyDown, false);
document.addEventListener('keydown', handleKeyDown, false);
}
其中 removeEventListener
移除已经有的键盘侦听事件并重新绑定。
为什么要这样做?
如果没有 removeEventListener 操作,每次开始游戏时添加键盘侦听事件,就会导致这样的一个 bug:只按了一次方向键,却重复执行了多次合并。
在 html 中添加开始按钮:
<button onclick="startGame()">重新开始</button>
然后需要修改一下初始化的任务函数,清空棋盘和得分:
function initializeGameBoard() {
// 清空棋盘和得分
gameBoard = [];
score = 0;
// 不动
for (let i = 0; i < 4; i++) {
gameBoard.push(new Array(4).fill(0));
}
}
如果不清空数据,就会在原来的棋盘上直接新增。
添加记录历史最高分的逻辑
首先添加显示的 html 代码:
扫描二维码关注公众号,回复:
16522942 查看本文章
<div class="score">得分: <span class="game-score">0</span></div>
<div class="score">最高分: <span class="game-high-score">0</span></div>
加上最高分的部分。
然后修改渲染逻辑 generateGameBoard
函数:
function generateGameBoard() {
// ... 上面不动
// 判断历史最高分
let max = parseInt(localStorage.getItem('score')) || 0;
if(score > max) {
max = score;
localStorage.setItem('score',`${
score}`);
}
const highScoreContainer = document.querySelector('.game-high-score');
highScoreContainer.textContent = max;
}
这里的逻辑很简单,判断当前得分是否高于历史最高分,如果高于,就向 Localstorage 中存储最新的得分。
响应式布局的样式
考虑到该游戏是通过键盘操作,响应式布局意义不太大。
所以额外再留下一个作业,修改响应式布局,并且支持手势划动(左划、右划、上划、下划)来移动数字方块。
响应式布局提示
- 响应式布局不可以用固定宽高,如:
width: 400px; height: 400px;
这种,需要使用百分比或者vw
、vh
之类(100vw
等于 100% 屏幕设备宽度)的单位。 - 可以使用
min-width
和max-width
来约束最大宽度,高度同理。 - 使用 MediaQuery 来针对不同尺寸屏幕进行个性化的样式定制。
JS Swipe(手势)
有很多第三方库,可以直接引入使用。
比如 Xwiper
如果用原生 JS (Vanilla JS 即原生 JS)实现,就需要了解一下 Touch Event:
- MDN 文档: https://developer.mozilla.org/zh-CN/docs/Web/API/Touch_events
- 参考教程: https://css-tricks.com/simple-swipe-with-vanilla-javascript/
这里,是一个简单的实现 Demo:
let pageWidth = window.innerWidth || document.body.clientWidth;
let treshold = Math.max(1,Math.floor(0.01 * (pageWidth)));
let touchstartX = 0;
let touchstartY = 0;
let touchendX = 0;
let touchendY = 0;
const limit = Math.tan(45 * 1.5 / 180 * Math.PI);
const gestureZone = document.getElementById('modalContent');
gestureZone.addEventListener('touchstart', function(event) {
touchstartX = event.changedTouches[0].screenX;
touchstartY = event.changedTouches[0].screenY;
}, false);
gestureZone.addEventListener('touchend', function(event) {
touchendX = event.changedTouches[0].screenX;
touchendY = event.changedTouches[0].screenY;
handleGesture(event);
}, false);
function handleGesture(e) {
let x = touchendX - touchstartX;
let y = touchendY - touchstartY;
let xy = Math.abs(x / y);
let yx = Math.abs(y / x);
if (Math.abs(x) > treshold || Math.abs(y) > treshold) {
if (yx <= limit) {
if (x < 0) {
console.log("left");
} else {
console.log("right");
}
}
if (xy <= limit) {
if (y < 0) {
console.log("top");
} else {
console.log("bottom");
}
}
} else {
console.log("tap");
}
}