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的响应事件
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版本)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 + " " 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 + " " 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>
6.总结
我敲代码,可以认认真真地敲到凌晨1点,这个是我之前没预期到的。
开发时,要用版本工具来控制,我使用TortoiseSVN。
最后,如果你有疑问,请在评论区提问,谢谢!