• 【Game】2048小游戏


      每个男孩都有一个游戏梦吧,本例简单讲述一款很火的游戏《2048》的制作。

      本例参考地址:https://www.imooc.com/learn/76

     游戏准备

      1、游戏的逻辑(2048大家去玩一玩就知道逻辑了)

      2、制作技术:Html,Css,Javascript,Jquery

      3、美术

    游戏架构

      

    游戏代码

      html代码:

     1 <!DOCTYPE html>
     2 <html>
     3 <head>
     4     <meta charset="utf-8">
     5     <title>2048</title>
     6     <link rel="stylesheet" type="text/css" href="css/index.css">
     7     <script type="text/javascript" src="lib/jquery/jquery.min.js"></script>
     8     <script type="text/javascript" src="js/support.js"></script>
     9     <script type="text/javascript" src="js/animation.js"></script>
    10     <script type="text/javascript" src="js/index.js"></script>
    11 </head>
    12 <body>
    13     <!-- 头部 -->
    14     <header>
    15         <h1>2048</h1>
    16         <a href="javascript:newgame();" id="newgamebutton">New Game</a>
    17         <p>score:<span id="score">0</span></p>
    18     </header>
    19     
    20     <section id="grid-container">
    21         <div class="grid-cell" id="grid-cell-0-0"></div>
    22         <div class="grid-cell" id="grid-cell-0-1"></div>
    23         <div class="grid-cell" id="grid-cell-0-2"></div>
    24         <div class="grid-cell" id="grid-cell-0-3"></div>
    25         <div class="grid-cell" id="grid-cell-1-0"></div>
    26         <div class="grid-cell" id="grid-cell-1-1"></div>
    27         <div class="grid-cell" id="grid-cell-1-2"></div>
    28         <div class="grid-cell" id="grid-cell-1-3"></div>
    29         <div class="grid-cell" id="grid-cell-2-0"></div>
    30         <div class="grid-cell" id="grid-cell-2-1"></div>
    31         <div class="grid-cell" id="grid-cell-2-2"></div>
    32         <div class="grid-cell" id="grid-cell-2-3"></div>
    33         <div class="grid-cell" id="grid-cell-3-0"></div>
    34         <div class="grid-cell" id="grid-cell-3-1"></div>
    35         <div class="grid-cell" id="grid-cell-3-2"></div>
    36         <div class="grid-cell" id="grid-cell-3-3"></div>
    37 
    38     </section>
    39 </body>
    40 </html>

      css代码:

     1 /*头部*/
     2 header {
     3     margin: 0 auto;
     4     width: 500px;
     5     text-align: center;
     6 }
     7 
     8 header h1 {
     9     font-family: Arial;
    10     font-size: 60px;
    11     font-weight: bold;
    12 }
    13 
    14 header #newgamebutton {
    15     display: block;
    16     margin: 20px auto;
    17 
    18     width: 100px;
    19     padding: 10px;
    20     background-color: #8f7a66;
    21 
    22     font-family: Arial;
    23     color: white;
    24     border-radius: 10px;
    25     text-decoration: none;
    26 }
    27 
    28 header #newgamebutton:hover {
    29     background-color: #9f8b77;
    30 }
    31 
    32 header p {
    33     font-family: Arial;
    34     font-size: 25px;
    35     margin: 20px auto;
    36 }
    37 
    38 /*格子*/
    39 #grid-container {
    40     width: 460px;
    41     height: 460px;
    42     padding: 20px;
    43 
    44     margin: 50px auto;
    45     background-color: #bbada0;
    46 
    47     border-radius: 10px;
    48     position: relative;
    49 }
    50 #grid-container .grid-cell {
    51     width: 100px;
    52     height: 100px;
    53     border-radius: 6px;
    54     background-color: #ccc0b3;
    55 
    56     position: absolute;
    57 }
    58 
    59 #grid-container .number-cell {
    60     border-radius: 6px;
    61 
    62     font-family: Arial;
    63     font-weight: bold;
    64     font-size: 60px;
    65     line-height: 100px;
    66     text-align: center;
    67 
    68     position: absolute;
    69 }

      js部分

      底层js:

      1 /* 底层支持js */
      2 
      3 //获取格子距离顶部的距离
      4 function getPosTop(i, j) {
      5     return 20 + i * 120;
      6 }
      7 //获取格子距离左边的距离
      8 function getPosLeft(i, j) {
      9     return 20 + j * 120;
     10 }
     11 
     12 //获取格子背景色
     13 function getNumberBackgroundColor(number) {
     14     switch (number) {
     15         case 2:
     16             return "#eee4da";
     17             break;
     18         case 4:
     19             return "#ede0c8";
     20             break;
     21         case 8:
     22             return "#f2b179";
     23             break;
     24         case 16:
     25             return "#f59563";
     26             break;
     27         case 32:
     28             return "#f67c5f";
     29             break;
     30         case 64:
     31             return "#f65e3b";
     32             break;
     33         case 128:
     34             return "#edcf72";
     35             break;
     36         case 256:
     37             return "#edcc61";
     38             break;
     39         case 512:
     40             return "#9c0";
     41             break;
     42         case 1024:
     43             return "#33b5e5";
     44             break;
     45         case 2048:
     46             return "#09c";
     47             break;
     48         case 4096:
     49             return "#s6c";
     50             break;
     51         case 8192:
     52             return "#93c";
     53             break;
     54     }
     55     return "black";
     56 }
     57 
     58 //获取格子文字色
     59 function getNumberColor(number) {
     60     if (number <= 4) {
     61         return "#776e65";
     62     }
     63     return "white";
     64 }
     65 
     66 // 判断格子是否有无空余
     67 function nospace(board) {
     68     for (var row = 0; row < 4; row++) {
     69         for (var col = 0; col < 4; col++) {
     70             if (board[row][col] == 0) {
     71                 return false;
     72             }
     73         }
     74     }
     75     return true;
     76 }
     77 
     78 
     79 
     80 //判断能否左移
     81 function canMoveLeft(board) {
     82     for (var i = 0; i < 4; i++) {
     83         
     84         for (var j = 1; j < 4; j++) {
     85             if (board[i][j] != 0) {
     86 
     87                 if (board[i][j-1] == 0 || board[i][j-1] == board[i][j]) {
     88                     // 左侧格子空 或 左侧盒子等于自己
     89                     return true;
     90                 }
     91             }
     92         }
     93     }
     94     return false;
     95 }
     96 
     97 function canMoveRight(board) {
     98     for (var i = 0; i < 4; i++) {
     99         for (var j = 2; j >= 0; j--) {
    100             if (board[i][j] != 0) {
    101                 if (board[i][j+1] == 0 || board[i][j+1] == board[i][j]) {
    102                     
    103                     return true;
    104                 }
    105             }
    106         }
    107     }
    108     return false;
    109 }
    110 
    111 //判断能否上移
    112 function canMoveUp(board) {
    113     for (var j = 0; j < 4; j++) {
    114         for (var i = 1; i < 4; i++) {
    115             if (board[i][j] != 0) {
    116                 if (board[i-1][j] == 0 || board[i-1][j] == board[i][j]) {
    117                     
    118                     return true;
    119                 }
    120             }
    121         }
    122     }
    123     return false;
    124 }
    125 
    126 
    127 
    128 
    129 function canMoveDown(board) {
    130     for (var j = 0; j < 4; j++) {
    131         for (var i = 2; i >= 0; i--) {
    132             if (board[i][j] != 0) {
    133                 if (board[i+1][j] == 0 || board[i+1][j] == board[i][j]) {
    134          
    135                     return true;
    136                 }
    137             }
    138         }
    139     }
    140     return false;
    141 }
    142 
    143 
    144 
    145 
    146 // 判断水平方向上是否有障碍物
    147 function noBlockHorizontal(row, col1, col2, board) {
    148     for (var i = col1 + 1; i < col2; i++) {
    149         if(board[row][i] != 0){
    150             return false;
    151         }
    152     }
    153     return true;
    154 }
    155 
    156 // 判断垂直方向是否有障碍物
    157 function noBlockVertical(col, row1, row2, board) {
    158     for (var i = row1 + 1; i < row2; i++) {
    159         if(board[i][col] != 0){
    160             return false;
    161         }
    162     }
    163     return true;
    164 }
    165 
    166 
    167 function nomove(board) {
    168     if(canMoveLeft(board) 
    169         || canMoveRight(board)
    170         || canMoveUp(board)
    171         || canMoveDown(board))
    172         return false;
    173     return true;
    174 }

      动画js:

    // 显示随机数字
    function showNumberWithAnimation(randx, randy, randNumber) {
        var numberCell = $("#number-cell-" + randx + "-" + randy);
        numberCell.css("background-color", getNumberBackgroundColor(randNumber));
        numberCell.css("color", getNumberColor(randNumber));
        numberCell.text(randNumber);
    
        numberCell.animate({
             "100px",
            height: "100px",
            top: getPosTop(randx, randy),
            left: getPosLeft(randx, randy)
        }, 50);
    }
    
    
    // 显示移动动画
    function showMoveAnimation(fromx, fromy, tox, toy){
        var numberCell = $("#number-cell-" + fromx + "-" + fromy);
        numberCell.animate({
            top: getPosTop(tox, toy),
            left: getPosLeft(tox, toy)
        },200);
    }
    
    
    function updateScore(score) {
        $("#score").text(score);
    }

      逻辑js:

      1 var board = new Array();//全局二维数组
      2 var score = 0;//全局分数
      3 var hasConflicted = new Array();//全局碰撞二维数组
      4 
      5 //入口
      6 $(document).ready(function() {
      7     newgame();
      8 });
      9 
     10 
     11 //新游戏 
     12 function newgame() {
     13     // 初始化棋盘格
     14     init();
     15     // 在随机两个各自生成数字
     16     generateOneNumber();
     17     generateOneNumber();
     18 }
     19 
     20 // 初始化棋盘格
     21 function init() {
     22 
     23     // 初始位子
     24     for (var i = 0; i < 4; i++) {
     25         for (var j = 0; j < 4; j++) {
     26             var gridCell = $("#grid-cell-" + i + "-" + j);
     27             gridCell.css("top", getPosTop(i, j));
     28             gridCell.css("left", getPosLeft(i, j));
     29         }
     30     }
     31 
     32     // 初始值
     33     for (var i = 0; i < 4; i++) {
     34         board[i] = new Array();
     35         hasConflicted[i] = new Array();
     36         for (var j = 0; j < 4; j++) {
     37             board[i][j] = 0;
     38             hasConflicted[i][j] = false;
     39         }
     40     }
     41 
     42     // 更新界面显示
     43     updateBoardView();
     44 
     45     score = 0;
     46     updateScore(score);
     47 
     48 }
     49 
     50 // 更新界面显示
     51 function updateBoardView() {
     52     // 移除已有值的元素
     53     $(".number-cell").remove();
     54 
     55     for (var i = 0; i < 4; i++) {
     56         for (var j = 0; j < 4; j++) {
     57             $("#grid-container").append("<div class='number-cell' id='number-cell-" + i + "-" + j + "'></div>");
     58             var theNumberCell = $("#number-cell-" + i + "-" + j);
     59 
     60             if (board[i][j] == 0) {
     61                 theNumberCell.css("width", "0px");
     62                 theNumberCell.css("height", "0px");
     63                 theNumberCell.css("top", getPosTop(i, j) + 50);
     64                 theNumberCell.css("left", getPosLeft(i, j) + 50);
     65             } else {
     66                 theNumberCell.css("width", "100px");
     67                 theNumberCell.css("height", "100px");
     68                 theNumberCell.css("top", getPosTop(i, j));
     69                 theNumberCell.css("left", getPosLeft(i, j));
     70                 theNumberCell.css("background-color", getNumberBackgroundColor(board[i][j]));
     71                 theNumberCell.css("color", getNumberColor(board[i][j]));
     72                 theNumberCell.text(board[i][j]);
     73                 
     74                 
     75             }
     76             hasConflicted[i][j] = false;
     77         }
     78     }
     79 }
     80 
     81 // 随机在格子中生成一个数
     82 function generateOneNumber() {
     83 
     84     // 判断格子空间
     85     if (nospace(board)) {
     86         return false;
     87     }
     88 
     89     // 随机一个位子
     90 
     91     var randx = 0;
     92     var randy = 0;
     93     do {
     94         randx = parseInt(Math.floor(Math.random() * 4));
     95         randy = parseInt(Math.floor(Math.random() * 4));
     96         if (board[randx][randy] == 0) break;
     97     }
     98     while(true);
     99 
    100     // 随机一个数
    101     var randNumber = Math.random() < 0.5 ? 2 : 4 ;
    102 
    103     // 在随机位子显示随机数
    104     board[randx][randy] = randNumber;
    105     showNumberWithAnimation(randx, randy, randNumber);
    106 
    107     return true;
    108 
    109 
    110 }
    111 
    112 
    113 
    114 // 添加操作事件
    115 $(document).keydown(function(event){
    116     switch(event.keyCode) {
    117         case 37: // left
    118             if(moveLeft()) {
    119                 setTimeout("generateOneNumber()", 210);
    120                 setTimeout("isgameover()", 300);
    121             }
    122             console.log(board);
    123             break;
    124         case 38: // up
    125             if(moveUp()) {
    126                 setTimeout("generateOneNumber()", 210);
    127                 setTimeout("isgameover()", 300);
    128             }
    129             break;
    130         case 39: // right
    131             if(moveRight()) {
    132                 setTimeout("generateOneNumber()", 210);
    133                 setTimeout("isgameover()", 300);
    134             }
    135             break;
    136         case 40: // down
    137             if(moveDown()) {
    138                 setTimeout("generateOneNumber()", 210);
    139                 setTimeout("isgameover()", 300);
    140             }
    141             break;
    142         default: break;
    143     }
    144     return false;
    145 });
    146 
    147 function isgameover(){
    148     if(nospace(board) && nomove(board)) {
    149         gameover();
    150     }
    151 }
    152 
    153 function gameover(){
    154     alert("gameover");
    155 }
    156 
    157 // 左移
    158 function moveLeft() {
    159     // 判断能否左移
    160     if(!canMoveLeft(board)) {
    161         return false;
    162     }
    163 
    164     for (var row = 0; row < 4; row++) {
    165         for (var col = 1; col < 4; col++) {
    166             if(board[row][col] != 0) {
    167                 
    168                 for (var k = 0; k < col; k++) {
    169                     // 左侧为0
    170                     if(board[row][k] == 0 && noBlockHorizontal(row, k, col, board)){
    171                         // move
    172                         showMoveAnimation(row, col, row, k);
    173                         board[row][k] = board[row][col];
    174                         board[row][col] = 0;
    175                         continue;
    176                     }
    177                     // 左侧等于自己
    178                     else if (board[row][ k] == board[row][col] && noBlockHorizontal(row, k, col, board) && !hasConflicted[row][k])
    179                     {
    180                         // move
    181                         showMoveAnimation(row, col, row, k);
    182 
    183                         // add
    184                         board[row][k] += board[row][col];
    185                         board[row][col] = 0;
    186 
    187                         score += board[row][k];
    188                         updateScore(score);
    189 
    190                         hasConflicted[row][k] = true;
    191 
    192                         continue;
    193                     }
    194                 }
    195             }
    196         }
    197     }
    198     
    199     setTimeout("updateBoardView()", 200);
    200     return true;
    201 }
    202 
    203 
    204 // 右移
    205 function moveRight() {
    206     // 判断能否右移
    207     if(!canMoveRight(board)) {
    208         return false;
    209     }
    210 
    211     for (var row = 0; row < 4; row++) {
    212         for (var col = 2; col >= 0; col--) {
    213             if(board[row][col] != 0) {
    214                 
    215                 for (var k = 3;  k > col; k--) {
    216                     
    217                     if(board[row][k] == 0 && noBlockHorizontal(row, col, k, board)){
    218                         // move
    219                         showMoveAnimation(row, col, row, k);
    220                         board[row][k] = board[row][col];
    221                         board[row][col] = 0;
    222                         continue;
    223                     }
    224                     
    225                     else if (board[row][k] == board[row][col] && noBlockHorizontal(row, col, k, board) && !hasConflicted[row][k])
    226                     {
    227                         // move
    228                         showMoveAnimation(row, col, row, k);
    229 
    230                         // add
    231                         board[row][k] += board[row][col];
    232                         board[row][col] = 0;
    233 
    234                         score += board[row][k];
    235                         updateScore(score);
    236 
    237                         hasConflicted[row][k] = true;
    238 
    239                         continue;
    240                     }
    241                 }
    242             }
    243         }
    244     }
    245     
    246     setTimeout("updateBoardView()", 200);
    247     return true;
    248 }
    249 
    250 
    251 
    252 // 上移
    253 function moveUp() {
    254     // 判断能否上移
    255     if(!canMoveUp(board)) {
    256         return false;
    257     }
    258 
    259     for (var col = 0; col < 4; col++) {
    260         for (var row = 1; row < 4; row++) {
    261         
    262             if(board[row][col] != 0) {
    263                 
    264                 for (var k = 0; k < row; k++) {
    265                     
    266                     if(board[k][col] == 0 && noBlockVertical(col, k, row, board)){
    267                         // move
    268                         showMoveAnimation(row, col, k, col);
    269                         board[k][col] = board[row][col];
    270                         board[row][col] = 0;
    271                         continue;
    272                     }
    273                     
    274                     else if (board[k][col] == board[row][col] && noBlockVertical(col, k, row, board) && !hasConflicted[k][col])
    275                     {
    276                         // move
    277                         showMoveAnimation(row, col, k, col);
    278 
    279                         // add
    280                         board[k][col] += board[row][col];
    281                         board[row][col] = 0;
    282 
    283                         score += board[k][col];
    284                         updateScore(score);
    285 
    286                         hasConflicted[k][col] = true;
    287 
    288                         continue;
    289                     }
    290                 }
    291             }
    292         }
    293     }
    294     
    295     setTimeout("updateBoardView()", 200);
    296     return true;
    297 }
    298 
    299 
    300 
    301 
    302 // 下移
    303 function moveDown() {
    304     // 判断能否下移
    305     if(!canMoveDown(board)) {
    306         return false;
    307     }
    308 
    309     for (var col = 0; col < 4; col++) {
    310     
    311         for (var row = 2; row >= 0; row--) {
    312             if(board[row][col] != 0) {
    313                 
    314                 for (var k = 3;  k > row; k--) {
    315                     
    316                     if(board[k][col] == 0 && noBlockVertical(col, row, k, board)){
    317                         // move
    318                         showMoveAnimation(row, col, k, col);
    319                         board[k][col] = board[row][col];
    320                         board[row][col] = 0;
    321                         continue;
    322                     }
    323                     
    324                     else if (board[k][col] == board[row][col] && noBlockVertical(col, row, k, board) && !hasConflicted[k][col])
    325                     {
    326                         // move
    327                         showMoveAnimation(row, col, k, col);
    328 
    329                         // add
    330                         board[k][col] += board[row][col];
    331                         board[row][col] = 0;
    332 
    333                         score += board[k][col]
    334                         updateScore(score);
    335 
    336                         hasConflicted[k][col] = true;
    337                         continue;
    338                     }
    339                 }
    340             }
    341         }
    342     }
    343     
    344     setTimeout("updateBoardView()", 200);
    345     return true;
    346 }

    游戏展示

      普通版地址:http://naughty7878.top/game/2048

      优化版地址:http://naughty7878.top/game/2048plus

    游戏优化

      1、随机数的参数,怎么更加准确的找空空位,在随机空位中产生随机数

      2、增加分数时,增加动画。

      3、游戏结束时,动画结束

      4、私人定制游戏,显示时:2-->小白,4-->实习生,8 -->程序猿,16-->项目经理

      5、操作问题,怎么鼠标操作,触摸滑动操作 

      6、设备适配的问题,兼容手机等。

      

  • 相关阅读:
    简单bb两句
    P2894 [USACO08FEB]Hotel G
    文艺平衡树
    CS184.1X 计算机图形学导论作业1
    C++ Primer Plus章节编程练习(第五章)
    C++ Primer Plus章节编程练习(第六章)
    CS184.1X 计算机图形学导论作业0
    C++ Primer Plus章节编程练习(第四章)
    计算机图形学之光栅图形学算法
    Codeforces 980B
  • 原文地址:https://www.cnblogs.com/h--d/p/8168795.html
Copyright © 2020-2023  润新知