JavaScript異步編程之Jscex版火拼俄羅斯
俄羅斯方塊(Tetris, 俄文:Тетрис)是一款風(fēng)靡全球的電視游戲機(jī)和掌上游戲機(jī)游戲,它由俄羅斯人阿列克謝·帕基特諾夫發(fā)明,故得此名。俄羅斯方塊的基本規(guī)則是移動、旋轉(zhuǎn)和擺放游戲自動輸出的各種方塊,使之排列成完整的一行或多行并且消除得分。由于上手簡單、老少皆宜,從而家喻戶曉,風(fēng)靡世界。
51CTO推薦專題:JavaScript異步編程
【需求分析】
(完全按照QQ游戲的制作,如下圖:)

【技術(shù)分析與實現(xiàn)】
1.方塊位置定位
解決方案:建立盒子模型







由于長條的存在,所以建立一個4*4的盒子模型,任何一個方塊都會存在該盒子當(dāng)中,方塊的定位就===盒子的定位。
2.顏色狀態(tài)的生成與保存
隨機(jī)生成顏色:
- function randomColor() {
- //16進(jìn)制方式表示顏色0-F
- var arrHex = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"];
- var strHex = "#";
- var index;
- for (var i = 0; i < 6; i++) {
- //取得0-15之間的隨機(jī)整數(shù)
- index = Math.round(Math.random() * 15);
- strHex += arrHex[index];
- }
- return strHex;
- }
顏色保存:(那一個方塊的一種狀態(tài)做示例)
- var diamonds = new Array();
- diamonds[0] = { x: appearPosition.position.x + 1, y: appearPosition.position.y, diamondColor: color };
- diamonds[1] = { x: appearPosition.position.x + 0, y: appearPosition.position.y + 1, diamondColor: color };
- diamonds[2] = { x: appearPosition.position.x + 1, y: appearPosition.position.y + 1, diamondColor: color };
- diamonds[3] = { x: appearPosition.position.x + 2, y: appearPosition.position.y + 1, diamondColor: color };
所有生成的方塊有個diamondColor屬性,用于存顏色。appearPosition.position是盒子模型的位置。
#p#
3.碰撞檢測
碰撞分兩種,一種是元素與左右墻壁和底部的碰撞,另外一種是方塊與底部方塊的接觸碰撞
a.元素與左右墻壁和底部的碰撞
a.1元素與底部的碰撞檢測
- if (diamonds[i].y * height + height >= canvasHeight) {
- appearPosition.position.x = Math.round(appearPosition.position.x);
- appearPosition.position.y = Math.round(appearPosition.position.y);
- createElement();
- breakTag = 1;
- }
a.2元素與左右墻壁的碰撞檢測
- function returnRightOrLeft() {
- var max_X = 11;
- for (i = 0; i < diamonds.length; i++) {
- if (diamonds[i].x > max_X) {
- max_X = diamonds[i].x;
- }
- }
- if (max_X != 11) appearPositionappearPosition.position.x = appearPosition.position.x - (max_X - 11);
- var min_X = 0;
- for (i = 0; i < diamonds.length; i++) {
- if (diamonds[i].x < min_X) {
- min_X = diamonds[i].x;
- }
- }
- if (min_X != 0) appearPositionappearPosition.position.x = appearPosition.position.x - min_X;
- }
b.元素與元素碰撞檢測
- //判斷下面是否有元素
- for (j = 0; j < bottomElement.length; j++) {
- if (bottomElement[j].x == diamonds[i].x) {
- if (Math.round(bottomElement[j].y) == Math.round(diamonds[i].y+1)) {
- appearPosition.position.x = Math.round(appearPosition.position.x);
- appearPosition.position.y = Math.round(appearPosition.position.y);
- createElement();
- breakTag = 1;
- }
- }
- }
- //判斷arrayOne是否在arrayTwo的右邊
- function IsAtRight(arrayOne, arrayTwo) {
- for (i = 0; i < arrayOne.length; i++) {
- for (j = 0; j < arrayTwo.length; j++) {
- if (Math.round(arrayOne[i].y )== Math.round(arrayTwo[j].y)) {
- if (arrayTwo[j].x == arrayOne[i].x + 1) return true;
- }
- }
- }
- return false;
- }
- //判D斷arrayOne是否在arrayTwo的左邊
- function IsAtLeft(arrayOne, arrayTwo) {
- for (i = 0; i < arrayOne.length; i++) {
- for (j = 0; j < arrayTwo.length; j++) {
- if (Math.round(arrayOne[i].y) ==Math.round( arrayTwo[j].y)) {
- if (arrayTwo[j].x == arrayOne[i].x - 1) return true;
- }
- }
- }
- return false;
- }
4.方塊變形
- var direction = 0;
- if (e.keyCode == 87) {
- direction++;
- direction %= 4;
- }
W鍵是變形,0123分別代表四種。
如果是長條或者只有兩種狀態(tài)的直接 if (direction % 2 == 0) {},如果是正方塊直接忽略direction,因為它就一種形狀。
5.鍵盤捕獲(目前WSAD+空格,W是變形,S和空格都是加速,IE9和FF異常,建議在谷歌瀏覽器下運(yùn)行)
- document.onkeydown = function (e) {
- if (e.keyCode == 65) {
- for (i = 0; i < diamonds.length; i++) {
- if (diamonds[i].x == 0) {
- return;
- }
- }
- if (IsAtLeft(diamonds, bottomElement)) {
- return;
- }
- appearPosition.position.x -= 1;
- }
- if (e.keyCode == 87) {
- direction++;
- direction %= 4;
- }
- if (e.keyCode == 68) {
- for (i = 0; i < diamonds.length; i++) {
- if (diamonds[i].x == 11) {
- return;
- }
- }
- if (IsAtRight(diamonds, bottomElement)) {
- return;
- }
- appearPosition.position.x += 1;
- }
- if (e.keyCode == 32) {
- delay = 1;
- }
- if (e.keyCode == 83) {
- delay = 1;
- }
- }
- document.onkeyup = function (e) {
- if (e.keyCode == 32) {
- delay = 20;
- }
- if (e.keyCode == 83) {
- delay = 20;
- }
- }
6.消除加分
- //一行滿了的話,消除并加分
- function clearUp() {
- for (var line = 0; line < 21; line++) {
- var count = 0;
- for (var i = 0; i < bottomElement.length; i++) {
- if (bottomElement[i].y == line) {
- count++;
- }
- }
- if (count == 12) clearByLineNum(line);
- }
- // if(count==12)
- }
- function clearByLineNum(num) {
- //以上的元素下降一行
- score++;
- var count = 0;
- for (i = 0; i < bottomElement.length; i++) {
- if (bottomElement[i].y == num) {
- count++;
- }
- }
- for (var j = 0; j < count; j++) {
- for (var i = 0; i < bottomElement.length; i++) {
- if (bottomElement[i].y == num) {
- bottomElement.splice(i, 1);
- break;
- }
- }
- }
- for (i = 0; i < bottomElement.length; i++) {
- if (bottomElement[i].y < num) {
- bottomElement[i].y += 1;
- }
- }
- }
消除加分有一個潛在的邏輯就是,在該行以上的元素的位置下降一個格子。
7.控制核心Jscex Show Time
- var JropAsync = eval(Jscex.compile("async", function () {
- var breakTag = 0;
- while (true) {
- color = randomColor();
- rectBlockIndex = MR() * 7 | 0;
- direction = MR() * 3 | 0;
- $await(Jscex.Async.sleep(1));
- while (true) {
- for (i = 0; i < diamonds.length; i++) {
- if (diamonds[i].y * height + height >= 525) {
- appearPosition.position.x = Math.round(appearPosition.position.x);
- appearPosition.position.y = Math.round(appearPosition.position.y);
- createElement();
- breakTag = 1;
- }
- //判D斷?下?面?是?否?有D元a素?
- for (j = 0; j < bottomElement.length; j++) {
- if (bottomElement[j].x == diamonds[i].x) {
- if (Math.round(bottomElement[j].y) == Math.round(diamonds[i].y+1)) {
- appearPosition.position.x = Math.round(appearPosition.position.x);
- appearPosition.position.y = Math.round(appearPosition.position.y);
- createElement();
- breakTag = 1;
- }
- }
- }
- }
- if (breakTag == 1) {
- for (i = 0; i < diamonds.length; i++) {
- //alert(diamonds[i].x + "____" + diamonds[i].y)
- bottomElement.push(diamonds[i]);
- }
- clearUp();
- //清?空?下?降μ的?元a素?
- diamonds.splice(0, diamonds.length);
- appearPosition = { position: { x: 4, y: -2 }, direction: 0 };
- breakTag = 0;
- break;
- }
- appearPosition.position.y += step;
- draw();
- $await(Jscex.Async.sleep(delay));
- }
- }
- }));
這是也整個俄羅斯方塊的控制核心,由兩個while循環(huán)構(gòu)成,簡單大方。
原文:http://www.cnblogs.com/iamzhanglei/archive/2011/09/09/2171930.html
【系列文章】