JavaScript异步编程之Jscex版火拼俄罗斯

开发 前端
俄罗斯方块是一款风靡全球的电视游戏机和掌上游戏机游戏,它由俄罗斯人阿列克谢·帕基特诺夫发明,故得此名。俄罗斯方块的基本规则是移动、旋转和摆放游戏自动输出的各种方块,使之排列成完整的一行或多行并且消除得分。

俄罗斯方块(Tetris, 俄文:Тетрис)是一款风靡全球的电视游戏机和掌上游戏机游戏,它由俄罗斯人阿列克谢·帕基特诺夫发明,故得此名。俄罗斯方块的基本规则是移动、旋转和摆放游戏自动输出的各种方块,使之排列成完整的一行或多行并且消除得分。由于上手简单、老少皆宜,从而家喻户晓,风靡世界。

51CTO推荐专题:JavaScript异步编程

 

 

【需求分析】

(完全按照QQ游戏的制作,如下图:)

 

els

 

【技术分析与实现】

1.方块位置定位

解决方案:建立盒子模型

 

els3
els4
els5
els6
els7
els8
els9

 

由于长条的存在,所以建立一个4*4的盒子模型,任何一个方块都会存在该盒子当中,方块的定位就===盒子的定位。

2.颜色状态的生成与保存

随机生成颜色:

  1. function randomColor() {  
  2.          //16进制方式表示颜色0-F      
  3.          var arrHex = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"];   
  4.       var strHex = "#";  
  5.          var index;  
  6.          for (var i = 0; i < 6; i++) {  
  7.              //取得0-15之间的随机整数   
  8.              index = Math.round(Math.random() * 15);  
  9.              strHex += arrHex[index];  
  10.          }  
  11.          return strHex;  
  12.      } 

颜色保存:(那一个方块的一种状态做示例)

  1. var diamonds = new Array();  
  2.    diamonds[0] = { x: appearPosition.position.x + 1, y: appearPosition.position.y, diamondColor: color };  
  3.    diamonds[1] = { x: appearPosition.position.x + 0, y: appearPosition.position.y + 1, diamondColor: color };  
  4.    diamonds[2] = { x: appearPosition.position.x + 1, y: appearPosition.position.y + 1, diamondColor: color };  
  5.    diamonds[3] = { x: appearPosition.position.x + 2, y: appearPosition.position.y + 1, diamondColor: color };  

所有生成的方块有个diamondColor属性,用于存颜色。appearPosition.position是盒子模型的位置。

#p#

3.碰撞检测

碰撞分两种,一种是元素与左右墙壁和底部的碰撞,另外一种是方块与底部方块的接触碰撞

a.元素与左右墙壁和底部的碰撞

a.1元素与底部的碰撞检测

  1. if (diamonds[i].y * height + height >= canvasHeight) {  
  2.                             appearPosition.position.x = Math.round(appearPosition.position.x);  
  3.                             appearPosition.position.y = Math.round(appearPosition.position.y);  
  4.                             createElement();  
  5.                             breakTag = 1;  
  6.                         } 

a.2元素与左右墙壁的碰撞检测

  1. function returnRightOrLeft() {  
  2.             var max_X = 11;  
  3.             for (i = 0; i < diamonds.length; i++) {  
  4.                 if (diamonds[i].x > max_X) {  
  5.                     max_X = diamonds[i].x;  
  6.                 }  
  7.             }  
  8.  
  9.             if (max_X != 11) appearPositionappearPosition.position.x = appearPosition.position.x - (max_X - 11);  
  10.             var min_X = 0;  
  11.             for (i = 0; i < diamonds.length; i++) {  
  12.                 if (diamonds[i].x < min_X) {  
  13.                     min_X = diamonds[i].x;  
  14.                 }  
  15.             }  
  16.  
  17.             if (min_X != 0) appearPositionappearPosition.position.x = appearPosition.position.x - min_X;  
  18.         } 

b.元素与元素碰撞检测

  1. //判断下面是否有元素  
  2.                        for (j = 0; j < bottomElement.length; j++) {  
  3.                            if (bottomElement[j].x == diamonds[i].x) {  
  4.                                if (Math.round(bottomElement[j].y) == Math.round(diamonds[i].y+1)) {  
  5.                                    appearPosition.position.x = Math.round(appearPosition.position.x);  
  6.                                    appearPosition.position.y = Math.round(appearPosition.position.y);  
  7.                                    createElement();  
  8.                                    breakTag = 1;  
  9.                                }  
  10.                            }  
  11.                        }  
  12. //判断arrayOne是否在arrayTwo的右边  
  13.        function IsAtRight(arrayOne, arrayTwo) {  
  14.            for (i = 0; i < arrayOne.length; i++) {  
  15.                for (j = 0; j < arrayTwo.length; j++) {  
  16.                    if (Math.round(arrayOne[i].y )== Math.round(arrayTwo[j].y)) {  
  17.                        if (arrayTwo[j].x == arrayOne[i].x + 1) return true;  
  18.                    }  
  19.                }  
  20.            }  
  21.            return false;  
  22.        }  
  23.        //判D断arrayOne是否在arrayTwo的左边  
  24.        function IsAtLeft(arrayOne, arrayTwo) {  
  25.            for (i = 0; i < arrayOne.length; i++) {  
  26.                for (j = 0; j < arrayTwo.length; j++) {  
  27.                    if (Math.round(arrayOne[i].y) ==Math.round( arrayTwo[j].y)) {  
  28.                        if (arrayTwo[j].x == arrayOne[i].x - 1) return true;  
  29.                    }  
  30.                }  
  31.            }  
  32.            return false;  
  33.        } 

4.方块变形

  1. var direction = 0;  
  2.        if (e.keyCode == 87) {  
  3.            direction++;  
  4.            direction %= 4;  
  5.        } 

W键是变形,0123分别代表四种。

如果是长条或者只有两种状态的直接 if (direction % 2 == 0) {},如果是正方块直接忽略direction,因为它就一种形状。

 

5.键盘捕获(目前WSAD+空格,W是变形,S和空格都是加速,IE9和FF异常,建议在谷歌浏览器下运行)

  1. document.onkeydown = function (e) {  
  2.     if (e.keyCode == 65) {  
  3.         for (i = 0; i < diamonds.length; i++) {  
  4.             if (diamonds[i].x == 0) {  
  5.                 return;  
  6.             }  
  7.         }  
  8.         if (IsAtLeft(diamonds, bottomElement)) {  
  9.             return;  
  10.         }  
  11.         appearPosition.position.x -1;  
  12.     }  
  13.     if (e.keyCode == 87) {  
  14.         direction++;  
  15.         direction %= 4;  
  16.     }  
  17.     if (e.keyCode == 68) {  
  18.         for (i = 0; i < diamonds.length; i++) {  
  19.             if (diamonds[i].x == 11) {  
  20.                 return;  
  21.             }  
  22.         }  
  23.         if (IsAtRight(diamonds, bottomElement)) {  
  24.             return;  
  25.         }  
  26.         appearPosition.position.x += 1;  
  27.     }  
  28.     if (e.keyCode == 32) {  
  29.         delay = 1;  
  30.     }  
  31.     if (e.keyCode == 83) {  
  32.         delay = 1;  
  33.     }  
  34. }  
  35.  
  36. document.onkeyup = function (e) {  
  37.     if (e.keyCode == 32) {  
  38.         delay = 20;               
  39.     }  
  40.     if (e.keyCode == 83) {  
  41.         delay = 20;               
  42.     }  

6.消除加分

  1. //一行满了的话,消除并加分  
  2. function clearUp() {  
  3.     for (var line = 0; line < 21; line++) {  
  4.         var count = 0;  
  5.         for (var i = 0; i < bottomElement.length; i++) {  
  6.             if (bottomElement[i].y == line) {  
  7.                 count++;  
  8.             }  
  9.         }  
  10.         if (count == 12) clearByLineNum(line);  
  11.     }  
  12.     // if(count==12)  
  13. }  
  14. function clearByLineNum(num) {  
  15.     //以上的元素下降一行  
  16.     score++;  
  17.     var count = 0;  
  18.     for (i = 0; i < bottomElement.length; i++) {  
  19.         if (bottomElement[i].y == num) {  
  20.             count++;  
  21.         }  
  22.     }  
  23.     for (var j = 0; j < count; j++) {  
  24.         for (var i = 0; i < bottomElement.length; i++) {  
  25.             if (bottomElement[i].y == num) {  
  26.                 bottomElement.splice(i, 1);  
  27.                 break;  
  28.             }  
  29.         }  
  30.     }  
  31.     for (i = 0; i < bottomElement.length; i++) {  
  32.         if (bottomElement[i].y < num) {  
  33.             bottomElement[i].y += 1;  
  34.         }  
  35.     }  

消除加分有一个潜在的逻辑就是,在该行以上的元素的位置下降一个格子。

7.控制核心Jscex Show Time

  1. var JropAsync = eval(Jscex.compile("async", function () {  
  2.     var breakTag = 0;  
  3.     while (true) {  
  4.          color = randomColor();  
  5.         rectBlockIndex = MR() * 7 | 0;  
  6.         direction = MR() * 3 | 0;  
  7.         $await(Jscex.Async.sleep(1));  
  8.         while (true) {  
  9.             for (i = 0; i < diamonds.length; i++) {  
  10.                 if (diamonds[i].y * height + height >= 525) {  
  11.                     appearPosition.position.x = Math.round(appearPosition.position.x);  
  12.                     appearPosition.position.y = Math.round(appearPosition.position.y);  
  13.                     createElement();  
  14.                     breakTag = 1;  
  15.                 }  
  16.                 //判D断?下?面?是?否?有D元a素?  
  17.                 for (j = 0; j < bottomElement.length; j++) {  
  18.                     if (bottomElement[j].x == diamonds[i].x) {  
  19.                         if (Math.round(bottomElement[j].y) == Math.round(diamonds[i].y+1)) {  
  20.                             appearPosition.position.x = Math.round(appearPosition.position.x);  
  21.                             appearPosition.position.y = Math.round(appearPosition.position.y);  
  22.                             createElement();  
  23.                             breakTag = 1;  
  24.                         }  
  25.                     }  
  26.                 }  
  27.             }  
  28.  
  29.             if (breakTag == 1) {  
  30.                 for (i = 0; i < diamonds.length; i++) {  
  31.                     //alert(diamonds[i].x + "____" + diamonds[i].y)  
  32.                     bottomElement.push(diamonds[i]);  
  33.                 }  
  34.                 clearUp();  
  35.                 //清?空?下?降μ的?元a素?  
  36.                 diamonds.splice(0, diamonds.length);  
  37.                 appearPosition = { position: { x: 4, y: -2 }, direction: 0 };  
  38.                 breakTag = 0;   
  39.                 break;  
  40.             }  
  41.             appearPosition.position.y += step;                   
  42.             draw();  
  43.             $await(Jscex.Async.sleep(delay));  
  44.         }  
  45.     }  
  46. })); 

这是也整个俄罗斯方块的控制核心,由两个while循环构成,简单大方。

原文:http://www.cnblogs.com/iamzhanglei/archive/2011/09/09/2171930.html

【系列文章】

  1. JavaScript异步编程之Jscex制作愤怒的小鸟
  2. 什么是JavaScript异步编程
  3. Jscex+jQuery UI打造游戏力度条
  4. JavaScript异步编程之Jscex无创痕切入jQueryUI
  5. Jscex模拟重力场与google苹果logo的比较
责任编辑:陈贻新 来源: 张磊的博客
相关推荐

2011-11-10 10:23:56

Jscex

2011-11-16 13:22:38

Jscex

2011-11-11 13:38:39

Jscex

2011-07-27 14:10:43

javascript

2012-06-14 13:40:04

JavaScript

2012-06-14 14:03:19

JavaScript

2016-10-21 11:04:07

JavaScript异步编程原理解析

2012-06-14 14:42:42

JavaScript

2014-10-08 10:04:14

代码解释俄罗斯方块

2012-06-14 14:09:58

JavaScript

2020-10-15 13:29:57

javascript

2011-11-11 14:05:13

Jscex

2017-07-13 12:12:19

前端JavaScript异步编程

2016-09-07 20:43:36

Javascript异步编程

2014-12-24 13:32:21

2015-04-22 10:50:18

JavascriptJavascript异

2014-05-23 10:12:20

Javascript异步编程

2012-10-29 13:25:54

JavaScriptJSjQuery

2012-06-13 13:16:16

2015-01-22 15:36:46

游戏源码
点赞
收藏

51CTO技术栈公众号