import BackGround from './base/background' import Support from "./base/support" wx.setPreferredFramesPerSecond(12) wx.showShareMenu() let ctx = canvas.getContext('2d') var w = canvas.width var h = canvas.height var csl = 0.18 * w var fsz = 0.07 * w var fontstyle = fsz + "px 楷体" let sp = new Support(w, h) var board = new Array(); var score = 0; var topScore = 0; var hasConflicted = new Array(); var direction = { left: 1, up: 2, down: 3, right: 4 }; let startX //触摸时的坐标 let startY let x //滑动的距离 let y /** * 游戏主函数 */ export default class Main { constructor() { // 维护当前requestAnimationFrame的id this.aniId = 0 this.restart() // 激活重启按钮事件 wx.onTouchStart(this.touchEventHandler.bind(this)) // 开启滑动事件监听 wx.onTouchStart(this.touchStart) wx.onTouchMove(this.touchMove) wx.onTouchEnd(this.touchEnd.bind(this)) } restart() { // console.log(w, h) this.bg = new BackGround(ctx, w, h) // 获取本地存储的最高分数(若有) wx.getStorage({ key: "topScore", success(res) { // console.log(res.data) topScore = res.data } }) // 重置当前分数 score = 0; // 显示新分数 this.updateScore(score) // 初始化棋盘格 this.init(); // 在随机两个格子生成数字 this.generateOneNumber(); this.generateOneNumber(); // 更新游戏面板 this.render(); } init() { for (var i = 0; i < 4; i++) { for (var j = 0; j < 4; j++) { ctx.fillStyle = '#CCC0B3' ctx.fillRect(sp.getPostionLeft(i, j), sp.getPostionTop(i, j), csl, csl) } } //初始化棋盘 for (var i = 0; i < 4; i++) { board[i] = new Array(); hasConflicted[i] = new Array(); for (var j = 0; j < 4; j++) { board[i][j] = 0; hasConflicted[i][j] = false; } } // console.log(board); //更新面板 this.render(); } // 棋盘重绘 render() { // 清空棋盘, 重新刷新 ctx.clearRect(20.04 * w, 50 + 0.3 * w, 0.92 * w, 0.92 * w); ctx.fillStyle = '#BBADA0' ctx.fillRect(0.04 * w, 50 + 0.3 * w, 0.92 * w, 0.92 * w) for (var i = 0; i < 4; i++) { for (var j = 0; j < 4; j++) { if (board[i][j] == 0) { // 绘制无字空图 ctx.fillStyle = '#CCC0B3' ctx.fillRect(sp.getPostionLeft(i, j), sp.getPostionTop(i, j), csl, csl) } else { // 根据数字颜色设置器背景色 ctx.fillStyle = sp.getBackgroundColorByNum(board[i][j]) ctx.fillRect(sp.getPostionLeft(i, j), sp.getPostionTop(i, j), csl, csl) // 设置文字颜色, 大小, 字体, 对其方式 ctx.fillStyle = sp.getPreColorByNum(board[i][j]) // 显示数字(文字) ctx.font = fontstyle ctx.textAlign = "left" ctx.textBaseline = "top" // 获取文字 var st = sp.getShowTextByNum(board[i][j]) // 将4字分两行绘制(有5字的份为前3后2) var st2 = st.slice(-2) var st1 = st.slice(0, st.length - 2) ctx.fillText(st1, sp.getPostionLeft(i, j) + 0.02 * w, sp.getPostionTop(i, j) + 0.01 * w); ctx.fillText(st2, sp.getPostionLeft(i, j) + 0.02 * w, sp.getPostionTop(i, j) + fsz + 0.02 * w); hasConflicted[i][j] = false; } } } } generateOneNumber() { if (sp.isNoSpace(board)) { return false; } //随机一个位置 var randx = parseInt(Math.floor(Math.random() * 4)); var randy = parseInt(Math.floor(Math.random() * 4)); //判断生成的坐标是否合理(无值,位置即可使用) while (true) { if (board[randx][randy] === 0) break; //若果该坐标存在了值,即不合理,继续生成随机一个位置 randx = parseInt(Math.floor(Math.random() * 4)); randy = parseInt(Math.floor(Math.random() * 4)); } //随机一个数字 var randNum = Math.random() < 0.6 ? 2 : 4; board[randx][randy] = randNum; // showNumberWithAnimation(randx, randy, randNum); this.render() return true; } /** * 滑动处理 1, 左滑; 2, 上滑, 3, 右滑; 4, 下滑 */ slideDirection(numm) { switch (numm) { case 1: //left if (this.moveLeft()) { setTimeout(this.generateOneNumber.bind(this), 210); setTimeout(this.isGameOver.bind(this), 300); } break; case 2: //up if (this.moveUp()) { setTimeout(this.generateOneNumber.bind(this), 210); setTimeout(this.isGameOver.bind(this), 300); } break; case 3: //right if (this.moveRight()) { setTimeout(this.generateOneNumber.bind(this), 210); setTimeout(this.isGameOver.bind(this), 300); } break; case 4: //down if (this.moveDown()) { setTimeout(this.generateOneNumber.bind(this), 210); setTimeout(this.isGameOver.bind(this), 300); } break; default: break; } } moveLeft() { if (!sp.canMove(board, direction.left)) return false; //左移 for (var i = 0; i < 4; i++) { for (var j = 1; j < 4; j++) { if (board[i][j] !== 0) { for (var k = 0; k < j; k++) //可以一次移动多个格子 if (board[i][k] == 0 && sp.noBlockHorizontal(i, k, j, board)) { //move // showMoveAnimation(i, j, i, k); board[i][k] = board[i][j]; board[i][j] = 0; continue; } else if (board[i][k] == board[i][j] && sp.noBlockHorizontal(i, k, j, board) && !hasConflicted[i][k]) { //move // showMoveAnimation(i, j, i, k); //add board[i][k] += board[i][j]; board[i][j] = 0; // var element = $("#grid-cell-" + i + k); // anp(element, board[i][k]) score += board[i][k]; this.updateScore(score) continue; } } } } setTimeout(this.render, 200); //等待200在执行更新面板操作,避免动画效果被冲掉 return true } moveRight() { if (!sp.canMove(board, direction.right)) return false; //右移 for (var i = 3; i >= 0; i--) { for (var j = 2; j >= 0; j--) { //该位置不等于0即可进行移动 if (board[i][j] != 0) for (var k = 3; k > j; k--) { //如果可以一次移动多个格子 if (board[i][k] == 0 && sp.noBlockHorizontal(i, j, k, board)) { //move // showMoveAnimation(i, j, i, k); board[i][k] = board[i][j]; board[i][j] = 0; continue; } else if (board[i][k] == board[i][j] && sp.noBlockHorizontal(i, j, k, board) && !hasConflicted[i][k]) { //move // showMoveAnimation(i, j, i, k); //add board[i][k] += board[i][j]; board[i][j] = 0; score += board[i][k]; // var element = $("#grid-cell-" + i + k); // anp(element, board[i][k]) this.updateScore(score) continue; } } } } setTimeout(this.render, 200); //等待200在执行更新面板操作,避免动画效果被冲掉 return true } /** 先判断第一列*/ moveUp() { if (!sp.canMove(board, direction.up)) return false; for (var i = 0; i < 4; i++) { for (var j = 1; j < 4; j++) { //该位置不为0即可进行移动 if (board[j][i] != 0) { for (var k = 0; k < j; k++) { if (board[k][i] == 0 && sp.noBlockVectal(i, k, j, board)) { //move // showMoveAnimation(j, i, k, i); board[k][i] = board[j][i]; board[j][i] = 0; continue; } else if (board[k][i] == board[j][i] && sp.noBlockVectal(i, k, j, board) && !hasConflicted[k][i]) { //move // showMoveAnimation(j, i, k, i); board[k][i] += board[j][i]; board[j][i] = 0; score += board[k][i]; // var element = $("#grid-cell-" + k + i); // anp(element, board[k][i]) this.updateScore(score); continue; } } } } } setTimeout(this.render, 200); //等待200在执行更新面板操作,避免动画效果被冲掉 return true } /** 先判断第一列*/ moveDown() { if (!sp.canMove(board, direction.down)) return false; for (var i = 3; i >= 0; i--) { for (var j = 2; j >= 0; j--) { //该位置不为0即可进行移动 if (board[j][i] != 0) { for (var k = 3; k > j; k--) { if (board[k][i] == 0 && sp.noBlockVectal(i, j, k, board)) { //move // showMoveAnimation(j, i, k, i); board[k][i] = board[j][i]; board[j][i] = 0; continue; } else if (board[k][i] == board[j][i] && sp.noBlockVectal(i, j, k, board) && !hasConflicted[k][i]) { //move // showMoveAnimation(j, i, k, i); board[k][i] += board[j][i]; board[j][i] = 0; score += board[k][i]; // var element = $("#grid-cell-" + k + i); // anp(element, board[k][i]) this.updateScore(score); continue; } } } } } // this.render() setTimeout(this.render, 200) //等待200在执行更新面板操作,避免动画效果被冲掉 return true } isGameOver() { if (sp.isNoSpace(board) && !sp.canMoveAll(board)) { this.gameOver() } } gameOver() { // 本地存储最高分数 wx.setStorage({ key: "topScore", data: topScore }) // 棋盘中出现 游戏结束!C2B6AB ctx.fillStyle = '#F7921E' ctx.fillRect(0.2 * w, 50 + 0.56 * w, 0.6 * w, 0.4 * w) ctx.fillStyle = 'white' ctx.font = "40px 微软雅黑" ctx.textAlign = "center" ctx.textBaseline = "middle" ctx.fillText("游戏结束!", 0.5 * w, 50 + 0.76 * w); console.log("游戏结束!") // alert("游戏结束!") } /** * 滑动处理 touchStart 记录起点; touchMove 记录x,y方向分别移动的距离; touchEnd 判断移动方向 */ touchStart(e) { var touch = e.touches[0] startX = touch.pageX //刚触摸时的坐标 startY = touch.pageY //刚触摸时的坐标 } touchMove(e) { //滑动 var touch = e.touches[0] x = touch.pageX - startX //滑动的距离 y = touch.pageY - startY //滑动的距离 } touchEnd(e) { //手指离开屏幕 // console.log(x) // console.log(y) var xy = Math.abs(x) - Math.abs(y) var d = 0 if (xy > 0) { if (x >= 0) { d = 3 } else { d = 1 } } else { if (y >= 0) { d = 4 } else { d = 2 } } this.slideDirection(d) } /** * * 更新最新分数和最高分数 */ updateScore(score) { // 清除去原分数 ctx.clearRect(0.28 * w, 50 + 0.08 * w, 0.32 * w, 0.08 * w); ctx.fillStyle = '#BAAB9E' ctx.fillRect(0.28 * w, 50 + 0.08 * w, 0.32 * w, 0.08 * w) ctx.clearRect(0.64 * w, 50 + 0.08 * w, 0.32 * w, 0.08 * w); ctx.fillStyle = '#F7921E' ctx.fillRect(0.64 * w, 50 + 0.08 * w, 0.32 * w, 0.08 * w) if (topScore < score) { topScore = score; } // 显示新分数 ctx.fillStyle = 'white' ctx.font = "20px 微软雅黑" ctx.textAlign = "center" ctx.textBaseline = "top" ctx.fillText(score, 0.8 * w, 50 + 0.08 * w); ctx.fillText(topScore, 0.44 * w, 50 + 0.08 * w); return true; } /** * 游戏结束激活处理事件 */ touchEventHandler(e) { var touch = e.touches[0] var cx = touch.clientX var cy = touch.clientY var area = this.bg.btnArea if (cx >= area.startX && cx <= area.endX && cy >= area.startY && cy <= area.endY) { this.restart() } } }