时间荏苒,唯编程与青春不可辜负,感觉自己一直没有专心去提升编程的技能,甚是惭愧!!!
周五,无意间看到一个开发2048的视频,有点兴趣就动起手来了,虽然不擅长前端开发,在此献丑,分享一下自己使用过程化开发2048的编码思考与过程。
既然要开发2048,大部分人应该都玩过,如果你有更好的建议可以给我留言O(∩_∩)O~
目录结构
- 1.什么是2048?
- 2.玩2048技巧?
- 3.移动端开发注意事项?
- 4.游戏设计图?
- 5.HTML编写?
- 6.CSS编写
- 7.JavaScript游戏模型编写?
- 8.JavaScript游戏逻辑编写?
- 9.JavaScript游戏特效编写?
- 10.打包APP?
什么是2048?
2048有16个格子,初始时会有两个格子上安放了两个数字2,每次可以选择上下左右其中一个方向去滑动,每滑动一次,所有的数字方块都会往滑动的方向靠拢外,系统也会在空白的地方随即出现一个数字方块,相同数字的方块在靠拢、相撞时会相加。
玩2048技巧?
1、最大数尽可能放在角落。
2、数字按顺序紧邻排列。
3、首先满足最大数和次大数在的那一列/行是满的。
4、时刻注意活动较大数(32以上)旁边要有相近的数。
5、以大数所在的一行为主要移动方向
6、不要急于“清理桌面”。
移动端开发注意事项?
屏幕宽度:
开发移动端页面时,必须设置适应移动端显示代码:
1 <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
触屏事件:
基于移动端开发一定要支持触屏touch事件。
因为我开发选用JQ支持,所以引入了JQuery.touch.js
JQuery.min.js下载:http:
//www.netcu.de/templates/netcu/js/jquery-1.4.2.min.js
JQuery.touch.js 下载:http:
//www.netcu.de/templates/netcu/js/jquery.touchwipe.js
JQuery.touch.js 实现大概原理:
1 (function($) { 2 $.fn.touchwipe = function(settings) { 3 var config = { 4 min_move_x: 20, 5 wipeLeft: function() { alert("left"); }, 6 wipeRight: function() { alert("right"); }, 7 preventDefaultEvents: true 8 }; 9 10 if (settings) $.extend(config, settings); 11 12 this.each(function() { 13 var startX; 14 var isMoving = false; 15 16 function cancelTouch() { 17 this.removeEventListener(‘touchmove‘, onTouchMove); 18 startX = null; 19 isMoving = false; 20 } 21 22 function onTouchMove(e) { 23 if(config.preventDefaultEvents) { 24 e.preventDefault(); 25 } 26 if(isMoving) { 27 var x = e.touches[0].pageX; 28 var dx = startX - x; 29 if(Math.abs(dx) >= config.min_move_x) { 30 cancelTouch(); 31 if(dx > 0) { 32 config.wipeLeft(); 33 } 34 else { 35 config.wipeRight(); 36 } 37 } 38 } 39 } 40 41 function onTouchStart(e) 42 { 43 if (e.touches.length == 1) { 44 startX = e.touches[0].pageX; 45 isMoving = true; 46 this.addEventListener(‘touchmove‘, onTouchMove, false); 47 } 48 } 49 50 this.addEventListener(‘touchstart‘, onTouchStart, false); 51 }); 52 53 return this; 54 }; 55 56 })(jQuery);
这样子,我们就可以支持wipeLeft、wipeRight、wipeDown、wipeUp事件了。
注意:在移动端click事件会延迟300ms
游戏设计图?
看看我们2048设计图:
HTML编写?
页面编写过程:
最外层我使用一个div,里面的4*4一共使用16个div。
只要外层的div使用relative相对定位,然后内部的单元格div使用absolute绝对定位。然后使用js代码计算对应单元格的Left与Top值。
HTML代码如下:
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title>2048</title> 5 <link type="text/css" rel="stylesheet" href="./lib/style.css" /> 6 <meta charset="utf-8"> 7 <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width"> 8 9 <script src="./lib/jquery.min.js"></script> 10 <script src="./lib/jquery.touchSwipe.min.js"></script> 11 12 <script src="./lib/data.js"></script> 13 <script src="./lib/function.js"></script> 14 <script src="./lib/animation.js"></script> 15 <script src="./lib/main.js"></script> 16 </head> 17 <body> 18 <div class="main"> 19 <div class="header"> 20 <h4>2048</h4> 21 <div class="score">Score : <span id="score">0</span></div> 22 <div class="new_game" id="new_game">New Game</div> 23 </div> 24 <div class="msg"><span id="msg">GameOver.</span></div> 25 <div class="game-panel"> 26 <div class="wall"> 27 <div class="cell" id="box-cell-0-0"></div> 28 <div class="cell" id="box-cell-0-1"></div> 29 <div class="cell" id="box-cell-0-2"></div> 30 <div class="cell" id="box-cell-0-3"></div> 31 <div class="cell" id="box-cell-1-0"></div> 32 <div class="cell" id="box-cell-1-1"></div> 33 <div class="cell" id="box-cell-1-2"></div> 34 <div class="cell" id="box-cell-1-3"></div> 35 <div class="cell" id="box-cell-2-0"></div> 36 <div class="cell" id="box-cell-2-1"></div> 37 <div class="cell" id="box-cell-2-2"></div> 38 <div class="cell" id="box-cell-2-3"></div> 39 <div class="cell" id="box-cell-3-0"></div> 40 <div class="cell" id="box-cell-3-1"></div> 41 <div class="cell" id="box-cell-3-2"></div> 42 <div class="cell" id="box-cell-3-3"></div> 43 </div> 44 </div> 45 </div> 46 <div class="footer">Hatcher make.2016</div> 47 </body> 48 </html>
header这个div显示标题,然后得分,以及一个开始游戏的button。
wall这个div就是游戏的主体部分。
CSS编写?
对应的CSS如下:
1 *{ 2 margin: 0px 0px; 3 padding: 0px 0px; 4 } 5 .main{ 6 font-family: "微软雅黑"; 7 text-align: center; 8 } 9 .header{ 10 border: 5px solid #fff; 11 height: 120px; 12 border-radius: 2px; 13 position: relative; 14 } 15 .header h4{ 16 width: 100px; 17 height: 100px; 18 color:#fff; 19 font-size: 32px; 20 line-height: 100px; 21 margin: 10px; 22 border-radius: 6px; 23 background-color: #ffad2d; 24 } 25 .header .score{ 26 color: #ffad2d; 27 font-size: 20px; 28 font-weight: bold; 29 position: absolute; 30 top: 20px; 31 left: 150px; 32 } 33 .header .new_game{ 34 color: #ffffff; 35 background-color: #19B8C8; 36 padding: 8px 10px; 37 font-size: 22px; 38 font-weight: bold; 39 position: absolute; 40 border-radius: 2px; 41 42 top: 60px; 43 left: 150px; 44 } 45 .header .new_game:active{ 46 background-color: #e15661; 47 } 48 .msg{ 49 font-size: 22px; 50 font-weight: bold; 51 line-height: 100px; 52 color: #ff3d44; 53 } 54 .game-panel{ 55 height: 300px; 56 width: 250px; 57 margin: 20px auto; 58 } 59 .game-panel .wall{ 60 padding: 10px; 61 width: 230px; 62 height: 230px; 63 background-color: #bbada0; 64 border-radius: 6px; 65 position: relative; 66 } 67 68 .game-panel .wall .cell{ 69 width: 50px; 70 height: 50px; 71 background-color: #ccc0b3; 72 border-radius: 4px; 73 position: absolute; 74 } 75 76 .game-panel .wall .number-cell{ 77 font-size: 25px; 78 font-weight: bold; 79 color: #fff; 80 border-radius: 4px; 81 line-height: 50px; 82 width: 0px; 83 height: 0px; 84 position: absolute; 85 } 86 .footer { 87 font-family: "微软雅黑"; 88 font-weight: bold; 89 font-size: 15px; 90 bottom: 0px; 91 line-height: 30px; 92 text-align: center; 93 position: static; 94 }
嘿嘿,我觉得这个css写得有些牵强了。
好,我们先看看这个时候的效果:
JavaScript编写?
很明显,中间的格子都没有摆放整齐。
没事,我们接下来,就使用js将格子摆放整齐。
从设计图中,我们很容易看出。
单元格(0,0)对应的left与top值应该是:10px , 10px
单元格(0,1)对应的left与top值应该是:10+60px , 10px
单元格(0,2)对应的left与top值应该是:10+60px+60px , 10px
..............依次类推
可以得到两个函数:
1 function getLeftPos(i,j){ 2 return 10+60*j; 3 } 4 5 function getTopPos(i,j){ 6 return 10+60*i; 7 }
那个,初始化内部16个单元的function怎么写呢?
1 function init_grid() { 2 for (var i = 0; i <= 3; i++) { 3 for (var j = 0; j <= 3; j++) { 4 $cell = $("#box-cell-" + i + "-" + j); 5 $cell.css("left", getLeftPos(i, j)); 6 $cell.css("top", getTopPos(i, j)); 7 } 8 } 9 }
ok,真的挺有意思的。
看看效果图
好像还挺简单的。
游戏数据模型?
页面的编写已经差不多了。
接下来,我们该考虑数据模型层了。
1 var lock = false; 2 var cell_grid = [ 3 [0,0,0,0], 4 [0,0,0,0], 5 [0,0,0,0], 6 [0,0,0,0] 7 ]; 8 9 var game_score = 0; 10 11 var color_cell = new Array(); 12 color_cell[2] = "#eee4da"; 13 color_cell[4] = "#ede0c8"; 14 color_cell[8] = "#f2b179"; 15 color_cell[16] = "#f59563"; 16 color_cell[32] = "#f67c5f"; 17 color_cell[64] = "#f65e3b"; 18 color_cell[128] = "#edcf72"; 19 color_cell[256] = "#edcc61"; 20 color_cell[512] = "#9c0"; 21 color_cell[1024] = "#33b5e5"; 22 color_cell[2048] = "#09c"; 23 color_cell[4096] = "#a6c"; 24 color_cell[8192] = "#93c"; 25 26 var font_cell = new Array(); 27 font_cell[2] = "25px"; 28 font_cell[4] = "25px"; 29 font_cell[8] = "23px"; 30 font_cell[16] = "21px"; 31 font_cell[32] = "21px"; 32 font_cell[64] = "21px"; 33 font_cell[128] = "18px"; 34 font_cell[256] = "18px"; 35 font_cell[512] = "18px"; 36 font_cell[1024] = "15px"; 37 font_cell[2048] = "15px"; 38 font_cell[4096] = "15px"; 39 font_cell[8192] = "15px";
声明定义了,4*4单元格对应的数值二维数组,0就代表空。还有对应的数值的颜色和字体大小范围。
注意,我们需要动态生成一个数字放在每个单元格之上,所以,我们需要在每个单元格内使用一个div进行盛放我们的数字,若非零即显示数值。
1 function init_view() { 2 for (var i = 0; i <= 3; i++) { 3 for (var j = 0; j <= 3; j++) { 4 $number_cell = $("<div class=‘number-cell‘ id=‘number-cell-" + i + "-" + j + "‘></div>"); 5 $number_cell.css("left", getLeftPos(i, j) + 25); 6 $number_cell.css("top", getTopPos(i, j) + 25); 7 $(".wall").append($number_cell); 8 } 9 } 10 }
这样,我们每个单元格就有了显示数值的一个容器div。
当对应单元格数值为0,这个div的width,height都为0px。(也就是什么看不到,呵呵)
当对应单元格数值大于0,这个div的width和height等于单元格的宽和高。这样这个数值就覆盖了单元格。
看看要实现的效果图:
对应的数值容器:0,2,0,4
再说一下游戏的规则,每次游戏开始时候,就自动随机生成两个2/4的数值。
所以,我们需要随机在单元格中,寻找为0的位置并设置其数值为2/4。
1 function create_two_number() { 2 3 { 4 var i = Math.floor(Math.random() * 4); 5 var j = Math.floor(Math.random() * 4); 6 var n = Math.floor(Math.random() * 4); 7 var m = Math.floor(Math.random() * 4); 8 9 } 10 while (cell_grid[i][j] != 0 || cell_grid[n][m] != 0); 11 var number1 = Math.random() > 0.5 ? 4 : 2; 12 var number2 = Math.random() > 0.5 ? 4 : 2; 13 14 cell_grid[i][j] = number1; 15 cell_grid[n][m] = number2; 16 }
游戏控制逻辑?
因为整个程序都是JS编写的,所以我们的游戏采用事件驱动编写:
绑定touch滑动事件如下:
1 $(".game-panel").swipe({ 2 swipe: function (event, direction, distance, duration, fingerCount) { 3 var can_handler = false; 4 switch (direction) { 5 case ‘left‘: //left 6 if (can_left()) { 7 handle_left(); 8 } 9 break; 10 case ‘up‘: //up 11 break; 12 case ‘right‘: //right 13 break; 14 case ‘down‘: //down 15 break; 16 default : 17 18 } 19 } 20 });
关键两个游戏逻辑控制函数
can_left 是否可以左移动:
规则,遍历靠右侧的三列单元格,如果存在当前单元格的前一个单元格为空,或者等于当前单元格。
1 function can_left(){ 2 for(var i=0 ; i<=3 ;i++){ 3 for(var j=1 ; j<=3 ;j++){ 4 if(cell_grid[i][j] != 0){ 5 if(cell_grid[i][j-1] == 0 || cell_grid[i][j-1] == cell_grid[i][j]){ 6 return true; 7 } 8 } 9 } 10 } 11 return false; 12 }
handle_left 进行左移动操作:
规则,遍历右侧三列单元格:
然后对每个单元格进行检查,如果存在单元格为0并且,该0单元格到检查中单元格可以走通,则可以进行操作移动。或者存在单元格等于检查中单元格,并也可以走通,则可以进行操作移动。
1 function handle_left(){ 2 for(var i=0 ; i<=3 ;i++){ 3 for(var j=1 ; j<=3 ;j++){ 4 if(cell_grid[i][j] != 0){ 5 for(var k=0 ; k<j ; k++){ 6 if(cell_grid[i][k] == 0 && has_road(i,k,i,j)){ 7 cell_grid[i][k] = cell_grid[i][j]; 8 cell_grid[i][j] = 0; 9 player_run_view(i,j,i,k); 10 break; 11 }else if(cell_grid[i][k] == cell_grid[i][j] && has_road(i,k,i,j)){ 12 game_score += cell_grid[i][j]; 13 $("#score").text(game_score); 14 cell_grid[i][k] += cell_grid[i][j]; 15 cell_grid[i][j] = 0; 16 player_run_view(i,j,i,k); 17 break; 18 } 19 } 20 } 21 } 22 } 23 }
其他right、down、up都是同理。
滑动特效编写?
1 function player_set_number_view(i,j,number){ 2 var cell = $("#number-cell-"+i+"-"+j); 3 cell.text(number); 4 cell.css("background-color",color_cell[number]); 5 cell.css("font-size",font_cell[number]); 6 cell.animate({left:getLeftPos(i,j),top:getTopPos(i,j),width:50,height:50},150); 7 } 8 9 function player_run_view(i,j,i,k){ 10 var cell = $("#number-cell-"+i+"-"+j); 11 cell.animate({left:getLeftPos(i,k),top:getTopPos(i,k)},180); 12 } 13 14 function player_run_vertical_view(i,j,k,j){ 15 var cell = $("#number-cell-"+i+"-"+j); 16 cell.animate({left:getLeftPos(k,j),top:getTopPos(k,j)},180); 17 }
最终效果图:
打包APP?
使用phoneGap进行打包,将代码拷贝到asset目录www下:
完成:
最后形成APK就可以到手机安装了:
最后安装好:
谢谢!!!