240
世界上有10种人,一种懂二进制,另一种不懂二进制。

JS/Jquery版本的俄罗斯方块(附源码分析)

转载于 http://blog.csdn.net/unionline/article/details/63250597 且后续更新于此

1.前言

写这个jQuery版本的小游戏的缘由在于我想通过从零到有,自己写一个Jquery版本的游戏用来练手,没参考过其他人代码,这样子才不会影响自己的思路。

经历了V1,V2版本,当前版本是V3,版本说明如下:

V1: Use two methods of left and right conflict check, bottom conflict check.
V2: Use U style conflict check for left and right and bottom.
V2.1: add keyDownRaip when press v_down key.
V2.0.2:add Debug Zone for test and theft operation based V2.
V3:UI adjust for lj.w based V2.0.2
V3.1:Add function of Pageviews and Leaderboard.
V4.0:Add function of auto adjust UI

/*****************************************************************/

JS/Jquery版本的俄罗斯方块(Tetris)V4.0
作者: unionline
邮箱:zplufb@163.com
转载请说明来自: http://blog.csdn.net/unionline
 
/*****************************************************************/

2.游戏说明

功能:关卡,分数,暂停,虚拟键,状态栏,自定义宽高大小,还有金手指。
在线试玩地址:play online
游戏界面如下:

 

3.难点及开发时遇到的问题汇总

1.碰撞检测和模型设计
答:在V1版本由于设计模型不合理导致碰撞检测不完美,而且得付出更多代价,后面改成了U模型。
 
2.当cube下降到底部,该给予短时间移动方块(符合游戏玩法)
答:给setTimeout,并延迟刷新二维数据
 
3.方块旋转
答:详情请见KeyHanderUp方法
 
4.触发下一个cube
答:之前用定时器刷新,后来改为当碰到下边界,触发Next();
 
5.下降碰到边界向左或向右移动,此时该cube下面为可降落
答:详情请见KeyHanderDown方法
 
6. to be continued ...

4.源码分析

方法说明:
InitUI(): 初始化界面,绘制出UI
InitData():初始化所有参数
InitVK():初始化并绑定button的响应事件
 
InitAllCubeStatusArr:初始化二维矩阵
printAllCubeStatusArr:打印二维矩阵,在console打印
UpdateAllCubeStatusArr:更新二维矩阵
 
RefreshDrawUI:重绘左侧主区UI
CheckRemoveRowInline:判定是否为可以删除行
RemoveRowInline:删除指定行
UpdateScore:更新分数
UpdateLevel:更新关卡
CheckGameOver:判定是否Game Over
TextSatutsTimeOut:右下角状态栏显示秒数和内容
Int:取整操作
 
CheckNextStatusIsBoundary:判定是否到达边界
CubeInBlock:碰撞检测的核心代码
Types:俄罗斯方块的7中类型
KeyHanderUp/KeyHanderDown/KeyHanderLeft/KeyHanderRight:上下左右操作
UpdatePosNextStatus:更新下一个位置的状态位,为边界判定服务。
 
showCurTypeInMainBoard:显示当前的方块
GetRandType:获取随机数,从而获得下一个候选区的方块
ShowCandidateType:显示候选区方块
 
DrawMainUI:绘制左侧主区UI
DrawCandidateZoneUI:绘制候选区主区UI
DrawOperationZoneUI:绘制操作区UI
Start:获取候选区方块
Next:下一个方块降落
Play:点击play按钮触发,点击后变成pause,可以暂停游戏
 
Pageviews and Leaderboard的源码,请到在线游戏处查看

5.源码(V3版本)

   1 <!DOCTYPE html>
   2 <html>
   3 <head>
   4 <meta chatset="utf-8">
   5 <title>Unionline's JS Tetris V3</title>
   6 <script src="https://cdn.static.runoob.com/libs/jquery/1.10.2/jquery.min.js"></script>
   7 <style>
   8 
   9 table{
  10 border: 1px solid #f77;
  11 }
  12 
  13 td{
  14     border: 1px solid #777;
  15 }
  16 
  17 .float-left{
  18     float: left;
  19 }
  20 
  21 .float-right{
  22     float: right;
  23 }
  24 
  25 #main{
  26     background-color: #94C6DD;
  27     width: 372px;
  28     height: 520px;
  29 }
  30 
  31 #left{
  32 float: left;
  33 
  34 }
  35 
  36 #right{
  37 float: left;
  38 
  39 }
  40 
  41 #candidateZone{
  42 width: 105px;
  43 }
  44 
  45 .description{
  46 border-left: 1px solid #f77;
  47 border-right: 1px solid #f77;
  48 width: 105px;
  49 border-bottom: 5px solid #777;
  50 padding-top: 3px;
  51 }
  52 
  53 .none{
  54     display: none;
  55 }
  56 
  57 button{
  58     margin-top: 2px;
  59     margin-bottom: 3px;
  60 }
  61 </style>
  62 <script>
  63 $(document).ready(function(){
  64 
  65     InitUI();
  66     InitData();
  67     InitVK();
  68     //ShowCandidateType();
  69     //Start();    
  70 
  71 });
  72 
  73 function InitData(){
  74 
  75  curTypeArr = null;
  76  nextTypeArr = null;
  77  pos = {x:0,y:Int(width/2)};
  78  curTypeObjIndex = 0;
  79  curTypeArrPos = [];
  80  flagIsBoundary = false;
  81  curTypeArrPosNextStatus = [];
  82  curTypeArrPosForCubeStatus = [];
  83  AllCubeStatusArr =[];
  84  speed = 1;
  85  score = 0;
  86  clearRowsNum = 0;
  87  nextTypeObjIndex = 0;
  88  stopFlag = false;
  89  firstStart = true;
  90 
  91  $("#level").html("0"+ speed);
  92  $("#score").html(score);
  93  //$("#textStatus").html("No Start");
  94  TextSatutsTimeOut(3,"No Start");
  95     
  96 clearInterval(timeInterval);
  97 InitAllCubeStatusArr();
  98 Types();
  99     //ShowCandidateType();
 100 }
 101 
 102 function InitUI(){
 103     DrawMainUI();
 104     DrawCandidateZoneUI();
 105     DrawOperationZoneUI();
 106 }
 107 
 108 var typeObj = new Object();
 109 var curTypeArr = null;
 110 var nextTypeArr = null;
 111 var width = 10;
 112 var height = 20;
 113 var model_width = width + 2;
 114 var model_height = height + 1;
 115 var pos = {x:0,y:Int(width/2)};
 116 var curTypeObjIndex = 0;
 117 var typeObjAttrList = [["aa","ab"],["ba"],["ca","cb"],["da","db"],["ea","eb","ec","ed"],["fa","fb","fc","fd"],["ga","gb","gc","gd"]];
 118 
 119 var curTypeArrPos = [];
 120 var flagIsBoundary = false;
 121 var curTypeArrPosNextStatus = [];
 122 var curTypeArrPosForCubeStatus = [];
 123 var AllCubeStatusArr =[];
 124 
 125 var speed = 1;
 126 var score = 0;
 127 var clearRowsNum =0;
 128 var nextTypeObjIndex = 0;
 129 var timeInterval = null;
 130 var stopFlag = false;
 131 var PauseFlag = false;
 132 var firstStart = true;
 133 var mainbgcolor = "#94C6DD";
 134 
 135 
 136 function InitAllCubeStatusArr(){
 137     //U type, Arr is (width +2 )*(height+1)
 138     
 139     //reset AllCubeStatusArr
 140     AllCubeStatusArr = [];
 141     for (var j = height  ; j >= 0; j--) {
 142         AllCubeStatusArr[j] = new Array([0]);
 143     for (var i = width + 1 ; i >= 0; i--) {
 144         AllCubeStatusArr[j][i] = 0;
 145         }
 146         
 147     }
 148     
 149     for (var j = height ; j >= 0; j--) {
 150         AllCubeStatusArr[j][0] = 1;
 151         AllCubeStatusArr[j][width +1] = 1;
 152     }
 153     for (var i = width ; i >= 0; i--) {
 154         AllCubeStatusArr[height][i] = 1;
 155     }
 156 
 157     //RefreshDrawUI();
 158 }
 159 
 160 function printAllCubeStatusArr(){
 161     
 162     var content = "";
 163     var row = AllCubeStatusArr.length;
 164     var col = AllCubeStatusArr[0].length;
 165     for (var j =0 ; j < row; j++) {
 166         for (var i = 0 ; i < col; i++) {
 167          content +=(" "+AllCubeStatusArr[j][i]);
 168         }
 169         console.log("row="+j+":"+content+"\n");
 170         content = "";
 171     }
 172     
 173 }
 174 
 175 function UpdateAllCubeStatusArr(){
 176     //last type done will execute the function
 177     
 178     for (var i = curTypeArrPosForCubeStatus.length - 1; i >= 0; i--) {
 179         var row = Int(curTypeArrPosForCubeStatus[i] / model_width);
 180         var col = Int(curTypeArrPosForCubeStatus[i] % model_width);
 181         //if(row < height){
 182             AllCubeStatusArr[row][col] = 1;
 183             $("#mtd_"+ curTypeArrPosForCubeStatus[i]).attr("flag","1");
 184             console.log("i="+i+" 1 = AllCubeStatusArr["+row+"]["+col+"]");
 185         //}
 186         
 187     }
 188     console.log("UpdateAllCubeStatusArr() Complete");
 189     
 190 }
 191 
 192 function RefreshDrawUI(){
 193 
 194 
 195     for(var i = 0; i < model_height -1; i++){
 196         for(var j = 1; j < model_width -1; j++){
 197         
 198             var curId = $("#mtd_"+ (i*model_width+j));
 199             if(AllCubeStatusArr[i][j] == 1){
 200                 curId.css("background-color","#f00");
 201                 //console.log("showCurTypeInMainBoard->red,curId= "+(i*model_width+j ));
 202             }else{
 203                 curId.css("background-color", mainbgcolor);
 204                 //console.log("showCurTypeInMainBoard->white,curId= "+(i*model_width+j ));
 205             }    
 206         }
 207     }
 208     console.log("RefreshDrawUI() Complete");
 209 
 210 }
 211 
 212 
 213 function CheckRemoveRowInline(){
 214     var count = 0;
 215     var clearRow = 0;
 216     for(var i = 0; i < model_height - 1; i++){
 217         for(var j = 1; j < model_width - 1; j++){
 218             if(AllCubeStatusArr[i][j] ==1){
 219                 count ++;
 220             }        
 221         }
 222         if (count == width) {
 223             clearRow = i;
 224             clearRowsNum ++;
 225             RemoveRowInline(clearRow);
 226             RefreshDrawUI();            
 227         }
 228 
 229         count = 0;
 230 
 231     }
 232     UpdateScore();
 233     
 234 }
 235 
 236 function RemoveRowInline(row){
 237     
 238     for(var i = row ; i > 0; i--){
 239         for(var j = 1; j < model_width - 1; j++){    
 240             
 241             AllCubeStatusArr[i][j] = AllCubeStatusArr[i-1][j];
 242         
 243         }
 244 
 245     }
 246     $("#textStatus").html("<div style='color:red'>remove "+clearRowsNum+" row!");
 247     TextSatutsTimeOut();
 248     console.log("RemoveRowInline row="+row);
 249 }
 250 
 251 
 252 function UpdateScore(){
 253     var lastScore =    score;
 254     if(clearRowsNum == 1){
 255         score += 1;
 256     }else if(clearRowsNum == 2){
 257         score += 3;
 258     }else if(clearRowsNum == 3){
 259         score += 6;
 260     }else if(clearRowsNum == 4){
 261         score += 10;
 262     }else{// when clearRowsNum = 0, it will not happen
 263         //score += 0;
 264     }
 265 
 266     //reset
 267     clearRowsNum = 0;
 268 
 269     if(score >= 20 && lastScore < 20){
 270         UpdateLevel();    
 271     }else if(score >= 40 && lastScore < 40){
 272         UpdateLevel();    
 273     }else if(score >= 60 && lastScore < 60){
 274         UpdateLevel();
 275     }else if(score >= 80 && lastScore < 80){
 276         UpdateLevel();    
 277     }else if(score >= 100 && lastScore < 100){
 278         UpdateLevel();
 279     }else if(score >= 120 && lastScore < 120){
 280         UpdateLevel();
 281     }else if(score >= 140 && lastScore < 140){
 282         UpdateLevel();
 283     }else if(score >= 147){
 284         score = 147;
 285         $("#textStatus").html("<div style='color:green'><b>Win</b>");
 286         //TextSatutsTimeOut(10);
 287         firstStart = true;
 288         
 289         var t =setInterval(function(){
 290             
 291             for(var i = height -1 ; i > 0; i--){
 292             for(var j = 1; j < model_width - 1; j++){                    
 293                 AllCubeStatusArr[i][j] = AllCubeStatusArr[i-1][j];        
 294                 }
 295             }
 296 
 297             RefreshDrawUI();    
 298             },500);
 299 
 300         setTimeout(function(){
 301             clearInterval(t);
 302             $("#reset").trigger("click");
 303             },500*height);    
 304     }
 305 
 306     $("#score").html(score);
 307 }
 308 
 309 function UpdateLevel(){
 310     // speed value from  1 to 6, Max is 6
 311     speed = Int(score / 20);
 312     $("#level").html("0"+ speed);
 313     if ( score >= 20 ) {
 314         $("#textStatus").html("<div style='color:green'>Congratulation! You have arrived "+speed+" Level");
 315         TextSatutsTimeOut(5);
 316     }
 317 
 318 }
 319 
 320 function CheckGameOver(){
 321     for(var i=0; i<curTypeArrPos.length;i++)
 322     
 323         if(CheckNextStatusIsBoundary()){
 324             if (Int(curTypeArrPos[i] / model_width) == 0) {
 325 
 326             console.log("Game Over! Your Score is="+$("#score").text());
 327             $("#textStatus").html("<div style='color:red'><b>Game over</b>");
 328             $('#score').html('<b style="color:green">'+$('#score').text()+'</b>');
 329             
 330             clearInterval(timeInterval);
 331 
 332             setTimeout(function(){
 333                 $('#reset').trigger('click');
 334             },3000);
 335 
 336             break;
 337 
 338         }
 339     }
 340 
 341 }
 342 
 343 function TextSatutsTimeOut(seconds,msg){
 344     if (typeof seconds == 'undefined') {
 345         seconds = 3;
 346     }
 347     if (typeof msg == 'undefined') {
 348         msg="playing";
 349     }
 350     setTimeout(function(){
 351         $("#textStatus").html(msg);            
 352         },seconds*1000);
 353 
 354 }
 355 
 356 function Int(number){
 357 
 358     return Math.floor(number);
 359 
 360 }
 361 
 362 function CheckNextStatusIsBoundary(reCheck){
 363     
 364     for (var i = curTypeArrPos.length - 1; i >= 0; i--) {
 365 
 366             if(curTypeArrPosNextStatus[i] >= model_width * (model_height-1)){
 367                     return true;
 368                 }
 369 
 370             if (reCheck == true ) {
 371                 UpdatePosNextStatus(KEY_DOWN);
 372                 if(CubeInBlock(curTypeArrPosNextStatus[i])){
 373                     return true;
 374                 }
 375                 console.log("reCheck i="+i);
 376             }
 377             else if(CubeInBlock(curTypeArrPosNextStatus[i])){
 378                 console.log("CheckNextStatusIsBoundary_i_val_ret="+i+" "+curTypeArrPosNextStatus[i]+" true");
 379                 return true;
 380             }
 381         }
 382         console.log("CheckNextStatusIsBoundary_i_val_ret="+i+" "+false);
 383     return false;
 384 }
 385 
 386 /*function CheckCurTypeStatusIsBottomBoundary(){
 387 
 388 for (var i = curTypeArrPosNextStatus.length - 1; i >= 0; i--) {
 389         //bottom check boundary when first start 
 390         if(curTypeArrPosNextStatus[i] >= model_width * (model_height-1)){
 391             console.log("CheckCurTypeStatusIsBottomBoundary0="+curTypeArrPosNextStatus[i]);
 392             return true;
 393         }
 394 
 395         //If NextStatus is Boundary, then NextNextStatus will be in CubeInBlock
 396         if(CubeInBlock(curTypeArrPosNextStatus[i] + model_width)){
 397             console.log("CheckCurTypeStatusIsBottomBoundary1="+curTypeArrPosNextStatus[i]);
 398             return true;
 399         }
 400     }
 401     return false;
 402 
 403 }
 404 */
 405 
 406 function CubeInBlock(number){
 407 
 408     var row = Int(number / model_width);
 409     var col = Int(number % model_width);
 410     console.log("CubeInBlock_num_row_col="+ number+" "+row+" "+col);
 411     if (AllCubeStatusArr[row][col] == 1){
 412         console.log("CubeInBlock_num is in block="+ number);
 413         return true;
 414     }
 415     
 416     return false;
 417 }
 418 
 419 
 420 
 421 function Types(){
 422 //five type
 423 typeObj.aa = [[1,1,1,1],[0,0,0,0],[0,0,0,0],[0,0,0,0]];//----
 424 typeObj.ab = [[1,0,0,0],[1,0,0,0],[1,0,0,0],[1,0,0,0]];//clockwise rotate 90 degree
 425 
 426 typeObj.ba = [[1,1,0,0],[1,1,0,0],[0,0,0,0],[0,0,0,0]];//
 427 
 428 typeObj.ca = [[1,1,0,0],[0,1,1,0],[0,0,0,0],[0,0,0,0]];//z
 429 typeObj.cb = [[0,1,0,0],[1,1,0,0],[1,0,0,0],[0,0,0,0]];//clockwise rotate 90 degree
 430 
 431 typeObj.da = [[0,1,1,0],[1,1,0,0],[0,0,0,0],[0,0,0,0]];//mirror z
 432 typeObj.db = [[1,0,0,0],[1,1,0,0],[0,1,0,0],[0,0,0,0]];//clockwise rotate 90 degree
 433 
 434 typeObj.ea = [[0,1,0,0],[0,1,0,0],[1,1,0,0],[0,0,0,0]];//mirror L
 435 typeObj.eb = [[1,0,0,0],[1,1,1,0],[0,0,0,0],[0,0,0,0]];//clockwise rotate 90 degree
 436 typeObj.ec = [[1,1,0,0],[1,0,0,0],[1,0,0,0],[0,0,0,0]];//clockwise rotate 180 degree
 437 typeObj.ed = [[1,1,1,0],[0,0,1,0],[0,0,0,0],[0,0,0,0]];//anticlockwise rotate 90 degree
 438 
 439 typeObj.fa = [[1,0,0,0],[1,0,0,0],[1,1,0,0],[0,0,0,0]];//L
 440 typeObj.fb = [[1,1,1,0],[1,0,0,0],[0,0,0,0],[0,0,0,0]];//clockwise rotate 90 degree
 441 typeObj.fc = [[1,1,0,0],[0,1,0,0],[0,1,0,0],[0,0,0,0]];//
 442 typeObj.fd = [[0,0,1,0],[1,1,1,0],[0,0,0,0],[0,0,0,0]];//
 443 
 444 typeObj.ga = [[0,1,0,0],[1,1,1,0],[0,0,0,0],[0,0,0,0]];//I---
 445 typeObj.gb = [[1,0,0,0],[1,1,0,0],[1,0,0,0],[0,0,0,0]];
 446 typeObj.gc = [[1,1,1,0],[0,1,0,0],[0,0,0,0],[0,0,0,0]];
 447 typeObj.gd = [[0,1,0,0],[1,1,0,0],[0,1,0,0],[0,0,0,0]];
 448 
 449 }
 450 
 451 
 452 $(window).keypress(function(event){
 453     
 454     var currKey = event.keyCode || event.which || event.charCode;
 455     var keyName = String.fromCharCode(currKey); 
 456     console.log("keyCode: " + currKey + " charCode: " + keyName); 
 457   
 458   switch(currKey) {
 459     case 119:
 460     case 87:
 461         KeyHanderUp();
 462         break;
 463     case 115:
 464     case 83:
 465         KeyHanderDown();
 466         break;
 467     case 97:
 468     case 65:
 469         KeyHanderLeft();
 470         break;
 471     case 100:
 472     case 68:
 473         KeyHanderRight();
 474         break;
 475     }
 476     console.log("pos(x,y)=["+pos.x+","+pos.y+"]");
 477 });
 478 
 479 function KeyHanderUp(){
 480 
 481 if (!flagIsBoundary && !PauseFlag && !firstStart) {
 482     eraseCurTypeUI();
 483     //default rotate dir is right
 484     var curTypeArrRotate = null;
 485     var nextAttr = null;
 486     console.log("curIndex ="+(curTypeObjIndex));
 487 
 488     if(curTypeObjIndex == 0){
 489         nextAttr = typeObjAttrList[0][1];
 490         curTypeObjIndex = 1;
 491     }else if(curTypeObjIndex == 1 ){
 492         nextAttr = typeObjAttrList[0][0];
 493         curTypeObjIndex = 0;
 494     }else if(curTypeObjIndex == 2){
 495         nextAttr = typeObjAttrList[1][0];
 496         curTypeObjIndex = 2;
 497     }else if(curTypeObjIndex == 3){
 498         nextAttr = typeObjAttrList[2][1];
 499         curTypeObjIndex = 4;
 500     }else if(curTypeObjIndex == 4 ){
 501         nextAttr = typeObjAttrList[2][0];
 502         curTypeObjIndex = 3;
 503     }else if(curTypeObjIndex == 5){
 504         nextAttr = typeObjAttrList[3][1];
 505         curTypeObjIndex = 6;
 506     }else if(curTypeObjIndex == 6 ){
 507         nextAttr = typeObjAttrList[3][0];
 508         curTypeObjIndex = 5;
 509     }else if(curTypeObjIndex >= 7){
 510         //first four rows number is 2+1+2+2 = 7, add 9 is 4 * 4 = 16
 511         var index = curTypeObjIndex + 9;
 512         var row =Math.floor(index / 4);
 513         var col =Math.floor(index % 4);
 514         //var curAttr = typeObjAttrList[row][col];
 515         
 516         if (col < 3) {
 517             nextAttr = typeObjAttrList[row][col+1];
 518             curTypeObjIndex ++;
 519         }else{
 520             col = 0;
 521             nextAttr = typeObjAttrList[row][col];
 522             
 523             if ((curTypeObjIndex+9) % 4 == 3) {
 524                 curTypeObjIndex -= 3;
 525             };
 526         }
 527                 
 528     }
 529 
 530     curTypeArrRotate = typeObj[nextAttr];
 531 
 532     curTypeArrPosNextStatus = [];
 533     for(var i = 0; i < 4; i++){
 534     for(var j = 0; j < 4-i; j++){
 535         if (curTypeArrRotate[i][j] == 1) {
 536             var id = (i+pos.x)*model_width+j+(pos.y)
 537             curTypeArrPosNextStatus.push(id);
 538             }
 539         }
 540             
 541     }
 542 
 543     if(! CheckNextStatusIsBoundary()){
 544         curTypeArr = typeObj[nextAttr];
 545     }else{
 546         curTypeObjIndex --;
 547         //Fix Type aa -> ab
 548         if (curTypeObjIndex < 0) {
 549             curTypeObjIndex = 1;
 550         };
 551     }
 552     
 553     showCurTypeInMainBoard();
 554     }
 555 }
 556 
 557 
 558 function KeyHanderDown(){
 559     
 560     if (!flagIsBoundary && !PauseFlag && !firstStart) {
 561         eraseCurTypeUI();
 562         pos.x ++;
 563         //Remember last status before conflict check 
 564 
 565         UpdatePosNextStatus(KEY_DOWN);
 566         if(CheckNextStatusIsBoundary()){
 567             pos.x --;
 568 
 569             flagIsBoundary =true;
 570         
 571         setTimeout(function(){
 572             
 573             //Remember last status before conflict check 
 574             for (var i = curTypeArrPosNextStatus.length - 1; i >= 0; i--) {
 575                 curTypeArrPosForCubeStatus[i] = curTypeArrPosNextStatus[i];
 576             }
 577 
 578             if(!CheckNextStatusIsBoundary(true)){
 579                 flagIsBoundary = false;
 580             }else{
 581 
 582             PauseFlag = true;
 583             UpdateAllCubeStatusArr();
 584             RefreshDrawUI();
 585             CheckRemoveRowInline();
 586             if(!CheckGameOver()){
 587                 PauseFlag = false;
 588                 Next();
 589             }
 590         }
 591             
 592         },300);
 593     }
 594     
 595     showCurTypeInMainBoard();
 596     }
 597 
 598 
 599 }
 600 
 601 //var KEY_UP = 0;
 602 var KEY_DOWN = 1;
 603 var KEY_LEFT = 2;
 604 var KEY_RIGHT = 3;
 605 
 606 function UpdatePosNextStatus(keyStatus){
 607     var offset =0;
 608     if (keyStatus == KEY_LEFT){
 609         offset = -1;
 610     }else if (keyStatus == KEY_RIGHT) {
 611         offset = 1;
 612     }else if (keyStatus == KEY_DOWN){ //KEY_DOWN 
 613         offset = model_width;
 614     }else{//KEY_UP
 615         offset = -model_width;
 616     }
 617 
 618     for (var i = curTypeArrPosNextStatus.length - 1; i >= 0; i--) {
 619         curTypeArrPosNextStatus[i] += offset;
 620     }
 621 }
 622 
 623 function KeyHanderLeft(){
 624     
 625     if(!PauseFlag && !firstStart){
 626     eraseCurTypeUI();
 627     pos.y --;
 628         
 629     UpdatePosNextStatus(KEY_LEFT);
 630 
 631     if (CheckNextStatusIsBoundary()) {
 632         
 633         //curTypeArrPosForCubeStatus = curTypeArrPosNextStatus;
 634         pos.y ++;
 635         
 636         }
 637     showCurTypeInMainBoard();
 638     }
 639 
 640 }
 641 
 642 function KeyHanderRight(){
 643     
 644     if(!PauseFlag && !firstStart){
 645     eraseCurTypeUI();
 646     pos.y ++;
 647         
 648     UpdatePosNextStatus(KEY_RIGHT);
 649     if (CheckNextStatusIsBoundary()) {
 650         //curTypeArrPosForCubeStatus = curTypeArrPosNextStatus;
 651         pos.y --;
 652     }
 653 
 654     showCurTypeInMainBoard();
 655     }
 656 }
 657 
 658 
 659 function showCurTypeInMainBoard(){
 660     // reset curTypeArrPos data
 661     curTypeArrPos = [];
 662     curTypeArrPosNextStatus = [];
 663     for(var i = 0; i < 4; i++){
 664     for(var j = 0; j < 4-i; j++){
 665         if (curTypeArr[i][j] == 1) {
 666             var id = (i+pos.x)*model_width+j+(pos.y);
 667             $("#mtd_"+ id).css("background-color","#f00");
 668             //console.log("showCurTypeInMainBoard->red,id="+curTypeArr[i][j] +" "+id );
 669             curTypeArrPos.push(id);
 670             curTypeArrPosNextStatus.push(id);
 671             }
 672         }
 673             
 674     }
 675     
 676 }
 677 
 678 function GetRandType(){
 679     var type = null;
 680     var i =0;
 681     var randNum =Math.floor(Math.random()*19);
 682     for (x in typeObj) {
 683         type = typeObj[x];
 684 
 685         if (randNum == i) {
 686             break;
 687         };
 688         i++;
 689     };
 690     nextTypeObjIndex = randNum;
 691     console.log("GetRandType_curTypeObjIndex=" + curTypeObjIndex);
 692     
 693     return type;
 694 }
 695 
 696 
 697 function ShowCandidateType(){
 698 
 699     nextTypeArr = GetRandType();
 700     //nextTypeObjIndex =  curTypeObjIndex;
 701     //reset color to white
 702     for(var i = 0; i < 4; i++){
 703         for(var j = 0; j < 4-i; j++){    
 704         $("#ctd_"+(i*4+j)).css("background-color", mainbgcolor);            
 705         }
 706             
 707     }
 708 
 709     for(var i = 0; i < 4; i++){
 710         for(var j = 0; j < 4-i; j++){
 711         if (nextTypeArr[i][j] == 1) {
 712                 $("#ctd_"+(i*4+j)).css("background-color","#f00");
 713             }
 714         }
 715             
 716     }
 717 }
 718 
 719 function DrawMainUI(){
 720 
 721     //reset div
 722     $("#left").html("");
 723     var table = $("<table>").appendTo($("#left"));
 724     for(var i = 0; i < model_height - 1; i++){
 725         var row = $("<tr>").appendTo(table);
 726     for(var j = 1; j < model_width - 1 ; j++){
 727      //row.append("<td>null</td>");
 728         $("<td id=mtd_"+(i*model_width+j)+" style='width:20px;height:20px'></td>").appendTo(row); 
 729     
 730         }
 731             
 732     }
 733 }
 734 
 735 function DrawCandidateZoneUI(){
 736     //reset div
 737     $("#candidateZone").html("");
 738     var table = $("<table>").appendTo($("#candidateZone"));
 739     for(var i = 0; i < 4; i++){
 740     var row = $("<tr>").appendTo(table);
 741     for(var j = 0; j < 4; j++){
 742      //row.append("<td>null</td>");
 743     $("<td id=ctd_"+(i*4+j)+" style='width:20px;height:20px'></td>").appendTo(row); 
 744     
 745         }
 746             
 747     }
 748 }
 749 
 750 function DrawOperationZoneUI(){
 751 
 752 
 753     var content ="";
 754 
 755     var div_custom = $("<div>").appendTo($("#custom"));
 756         content = "<div><b>Custom</b></div><div>width :<input id='width' style='width:40px' placeholder='5-20'/></div>"
 757                 + "<div>height:<input id='height' style='width:40px' placeholder='5-20'/></div>"
 758                 + "<button id='customOk'>OK</button>"
 759                 + "&nbsp;"
 760                 + "<button id='customClear'>Clear</button>";
 761     div_custom.html(content);
 762 
 763     var div_debug = $("<div>").appendTo($("#debugZone"));
 764         content = "<button id='refresh'>RefreshUI</button>"    
 765                 + "<button id='printAllCubeStatusArr'>printStatusArr</button>"
 766                 + "<div>SetLevel :<input id='setLevel' style='width:20px' placeholder='1-7'/></div>"
 767                 + "<div>SetScore :<input id='setScore' style='width:20px' placeholder='147'/></div>"
 768                 + "<button id='debugOk'>OK</button>"
 769                 + "&nbsp;"
 770                 + "<button id='debugClear'>Clear</button>"
 771                 + "<button id='debugHide' style='width:100%'>Hide</button>";
 772     div_debug.html(content);
 773 
 774     var div_manual = $("<div>").appendTo($("#manual"));
 775         content = "<div>Manual:Press WSAD is for UP DOWN LEFT RIGHT or Using below virtual nav key</div>";
 776     div_manual.html(content);
 777 
 778     var div_score = $("<div style='background-color:#77ff77; width:372px; font-size:larger'>").appendTo($("#scoreZone"));
 779          content = "<b>Level:</b><span id='level'>01</span>"
 780                 + "<b style='padding-left:95px'>Score:</b><span id='score'>0</span>";
 781     div_score.html(content);
 782 
 783     var div_play = $("<div>").appendTo($("#playZone"));
 784          content = "<button id='play' >Play</button>"
 785                 + "<button id='reset' class='float-right'>Reset</button>";
 786     div_play.html(content);
 787 
 788     var div_text = $("<div>").appendTo($("#textStatusZone"));
 789          content = "<div>Status: </div>"
 790                  + "<div id='textStatus'>No Start</div>";
 791     div_text.html(content);
 792 
 793     var div_nav = $("<div>").appendTo($("#virtualNav"));
 794          content = "<button id='v_up' style='width:100%'>Up</button>"
 795                 + "<button id='v_left' class='float-left'>Left</button>"
 796                 + "<button id='v_right' class='float-right'>Right</button>"
 797                 + "<button id='v_down' style='width:100%'>Down</button>";
 798     div_nav.html(content);
 799 }
 800 
 801 function InitVK(){
 802 
 803     //custom
 804     $("#customOk").click(function(){
 805         var cwidth = parseInt($("#width").val());
 806         var cheight =parseInt($("#height").val());
 807         if (cwidth >= 5 && cheight >=5 && cwidth <= 20 &&cheight <=20) {
 808             width = cwidth;
 809             height =cheight;
 810             model_width = width + 2;
 811             model_height = height + 1;
 812             $("#textStatus").html("custom setting done");
 813             $("#reset").trigger('click');
 814             $("#main").css('width',width/10*260+112+'px');
 815             $("#scoreZone > div").css('width',width/10*260+112+'px');
 816 
 817 
 818         }else{
 819             $("#textStatus").html("width or height size both is among <b>5-20</b>");
 820             
 821         }
 822         TextSatutsTimeOut(3,"No Start");
 823 
 824         //open debugZone
 825         if (cwidth == "520" || cheight =="520") {
 826             $("#debugZone").removeClass("none");
 827             $("#debugZone").css("border","1px solid #0f0");
 828         }
 829     });
 830 
 831     $("#customClear").click(function(){
 832             
 833         if($("#width").val() == "" && $("#height").val() == ""){
 834             $("#textStatus").html("Don't Press Clear button when no value");
 835              
 836              setTimeout(function(){
 837                 $("#textStatus").html("No Start");            
 838              },2000);
 839         
 840         }else{
 841              $("#width").val("");
 842              $("#height").val("");
 843              $("#textStatus").html("Clear Custom width and height");
 844             
 845              setTimeout(function(){
 846                 $("#textStatus").html("No Start");            
 847              },2000);
 848          }
 849          
 850     });
 851     
 852     //debugZone
 853     $("#printAllCubeStatusArr").click(function(){
 854         printAllCubeStatusArr();
 855     });
 856 
 857     $("#refresh").click(function(){
 858         RefreshDrawUI();
 859     });
 860     
 861     $("#debugOk").click(function(){
 862         var dlevel = parseInt($("#setLevel").val());
 863         var dScore =parseInt($("#setScore").val());
 864         if (dlevel <= 7 && dlevel >=1) {
 865             speed = dlevel -1;    
 866             $("#level").html("0"+dlevel);
 867             
 868         }else{
 869             $("#textStatus").html("level is among <b>1-7</b>");    
 870         }
 871 
 872         if (dScore <= 147 && dScore >= 0) {
 873             score = dScore;
 874             $("#score").html(dScore);
 875             //$("#textStatus").html("setScore done");
 876         }else{
 877             $("#textStatus").html("level is among <b>1-7</b> and Score is among <b>0-147</b>");    
 878         }    
 879 
 880         setTimeout(function(){
 881             $("#textStatus").html("No Start");            
 882         },5000);
 883 
 884 
 885     });
 886 
 887     $("#debugClear").click(function(){
 888             
 889         if($("#width").val() == "" && $("#height").val() == ""){
 890             $("#textStatus").html("Don't Press Clear button when no value");
 891              
 892              setTimeout(function(){
 893                 $("#textStatus").html("No Start");            
 894              },2000);
 895         
 896         }else{
 897              $("#setLevel").val("");
 898              $("#setScore").val("");
 899              $("#textStatus").html("Clear Level and Score");
 900             
 901              setTimeout(function(){
 902                 $("#textStatus").html("No Start");            
 903              },2000);
 904          }
 905          
 906     });
 907 
 908     $("#debugHide").click(function(){
 909 
 910         $("#debugZone").addClass("none");
 911             $("#textStatus").html("Debug Zone has hided");         
 912              setTimeout(function(){
 913                 $("#textStatus").html("No Start");            
 914              },2000);     
 915     });
 916     
 917     //playZone
 918     $("#play").click(function(){
 919     
 920         if($("#play").text() == "Pause"){
 921             clearInterval(timeInterval);
 922             $("#play").html("<b>Play<b>");
 923             PauseFlag = true;
 924             $("#textStatus").html("game is paused");
 925         }else{//$("#play").text() == "Play"
 926             Play();
 927             if(firstStart){
 928                 //init nextTypeArr show CandidateType
 929                 ShowCandidateType();
 930                 Start();
 931                 firstStart = false;
 932             }
 933 
 934             $("#play").text("Pause");
 935             PauseFlag = false;
 936             $("#textStatus").html("playing");
 937         }        
 938 
 939     });
 940 
 941     $("#reset").click(function(){
 942         DrawMainUI();
 943         DrawCandidateZoneUI();
 944         InitData();
 945         //firstStart = true;
 946         clearInterval(timeInterval);
 947         $("#play").text("Play");
 948 
 949         
 950     });
 951 
 952     //nav
 953     $("#v_up").click(function(){
 954         KeyHanderUp();
 955     });
 956 
 957     $("#v_down").click(function(){
 958         KeyHanderDown();
 959     });
 960 
 961     $("#v_left").click(function(){
 962         KeyHanderLeft();
 963     });
 964 
 965     $("#v_right").click(function(){
 966         KeyHanderRight();
 967     });
 968 
 969 }
 970 
 971 
 972 function Start(){
 973     //ShowCandidateType();
 974     curTypeArr = nextTypeArr;
 975     var lastTypeObjIndex = nextTypeObjIndex;
 976     ShowCandidateType();
 977     curTypeObjIndex = lastTypeObjIndex;
 978     showCurTypeInMainBoard();
 979 }
 980 
 981 
 982 
 983 function Next(){
 984     
 985     if(flagIsBoundary){
 986         flagIsBoundary = false;
 987         pos = {x:0,y:Int(width/2)};
 988         Start();
 989     }
 990     console.log("Next() Complete");
 991 
 992 }
 993 function Play(){
 994     timeInterval = setInterval(function(){
 995         KeyHanderDown();
 996     },(8-speed)*70);
 997 }
 998 
 999 function eraseCurTypeUI(){
1000     for(var i = 0; i < 4; i++){
1001         $("#mtd_"+curTypeArrPos[i]).css("background-color", mainbgcolor);
1002     }
1003 
1004 }
1005 
1006 </script>
1007 
1008 
1009 </head>
1010 <body>
1011 <h3>Welcome to my game exercise - Tetris</h3>
1012 <div id ="manual">
1013 </div>
1014         <div id ="scoreZone">
1015         </div>
1016 <div id="main">
1017     <div id="left">
1018     </div>
1019     <div id="right">
1020         <div id="candidateZone">
1021         </div>
1022         <div id ="custom" class="description">
1023         </div>
1024         <div id ="debugZone" class="description none">
1025         </div>
1026 
1027         <div id ="playZone" class="description">
1028         </div>
1029         <div id ="virtualNav" class="description">
1030         </div>
1031         <div id ="textStatusZone" class="description">
1032         </div>
1033     </div>
1034 </body>
1035 </html>
View Code

6.总结

我敲代码,可以认认真真地敲到凌晨1点,这个是我之前没预期到的。
开发时,要用版本工具来控制,我使用TortoiseSVN。
最后,如果你有疑问,请在评论区提问,谢谢!

 

posted @ 2017-03-18 14:00  unionline  阅读(944)  评论(0编辑  收藏  举报