zoukankan      html  css  js  c++  java
  • 火拼《俄罗斯方块》解析

    一.简介

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

    二.需求分析

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

    els

    三.技术分析与实现

    1.方块位置定位

    解决方案:建立盒子模型

    els3els4els5els6els7els8els9

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

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

    随机生成颜色:

     function randomColor() {
            //16进制方式表示颜色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之间的随机整数
                index = Math.round(Math.random() * 15);
                strHex += arrHex[index];
            }
            return strHex;

     } 

        

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

       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是盒子模型的位置。

    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) appearPosition.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) appearPosition.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分别代表四种。

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

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

        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循环构成,简单大方

  • 相关阅读:
    There is an overlap in the region chain修复
    There is an overlap in the region chain
    region xx not deployed on any region server
    python 中的re模块,正则表达式
    TCP粘包问题解析与解决
    yield from
    Git push提交时报错Permission denied(publickey)...Please make sure you have the correct access rights and the repository exists.
    mysql 中Varchar 与char的区别
    Mysql 字符集及排序规则
    请实现一个装饰器,限制该函数被调用的频率,如10秒一次
  • 原文地址:https://www.cnblogs.com/yangmengsheng/p/6026203.html
Copyright © 2011-2022 走看看