过程化开发2048智力游戏WebApp

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了过程化开发2048智力游戏WebApp相关的知识,希望对你有一定的参考价值。

时间荏苒,唯编程与青春不可辜负,感觉自己一直没有专心去提升编程的技能,甚是惭愧!!!

周五,无意间看到一个开发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&nbsp;:&nbsp;<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就可以到手机安装了:

最后安装好:

技术分享

技术分享

 

谢谢!!!

 

以上是关于过程化开发2048智力游戏WebApp的主要内容,如果未能解决你的问题,请参考以下文章

一文梳理2048小游戏从开发到上云全流程

Unity3D游戏开发实战Unity3D实现休闲类游戏《2048》——算法源代码

Unity3D游戏开发实战Unity3D实现休闲类游戏《2048》——算法源代码

一百行写一个2048

一百行写一个2048

一百行写一个2048