俄罗斯方块的代码

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html>

<style>

    div {display:block;background-color:black;position:absolute;font:17px Tahoma;color:#fff;}

    <!-- 层 -->

    span {float:left;background-color:gray;width:12px;height:12px;border:4px gray outset;margin:0 1 1 0;overflow:hidden;}

    <!-- 游戏区单体方块 -->

    p {float:left;width:8px;height:8px;border:2px gray outset;overflow:hidden;margin:0;padding:0}

    <!-- 预览区单体方块 -->

    #main {width:375px;height:430px;display:block;background-color:gray;position:relative;}

    <!-- 全面版 -->

    #body {width:241px;height:401px;left:15px;top:15px;border:1px solid #999;}

    <!-- 主游戏区 -->

    #score {width:80px;height:24px;left:270px;top:15px;padding:4px;}

    <!-- 计分区 -->

    #level {width:80px;height:24px;left:270px;top:50px;padding:4px;}

    <!-- 等级区 -->

    #next {width:50px;height:50px;left:270px;top:85px;border:19px black solid;}

    <!-- 预览区 -->

    #ctrl {width:80px;height:55px;left:270px;top:360px;padding:4px;text-align:center;background-color:gray}

    <!-- 按钮区 -->

    #ctrl button{width:80px;height:25px;}

    <!-- 按钮 -->

</style>

<script>

    //By: X!ao_f QQ:120000512

    var G = {

        fs:[], // 游戏区点阵

        fn:[], // 预览区点阵

        score:0,

        l:['#9F0','#FF3','#F33','#C0C','#33C','#0F3','#F93'],// 颜色选择器

        v:[0x801,0x801,0x801,0x801,0x801,0x801,0x801,0x801,0x801,0x801,0x801,0x801,0x801,0x801,0x801,0x801,0x801,0x801,0x801,0xFFFF],

        // 游戏区行点阵

        d:[[0xCC00],[0x4444,0xF0],[0x8C40,0x6C00],[0x4C80,0xC600],[0x44C0,0x8E00,0xC880,0xE200],[0x88C0,0xE800,0xC440,0x2E00],[0x4E00,0x8C80,0xE400,0x4C40]],

        // 方块造型点阵

        init:function(){

            var body = document.getElementById('body');

            var next = document.getElementById('next');

            for(var i=0;i<240;i++){ // 以游戏区单体方块填充点阵

                G.fs.push(body.appendChild(document.createElement("span")));

            }

            for(var i=0;i<16;i++){ // 以预览区单体方块填充点阵

                G.fn.push(next.appendChild(document.createElement("p")));

            }

            G.domScore = document.getElementById('score');

            G.domLevel = document.getElementById('level');

            document.onkeydown=function(e){G.event(e||window.event,0)}; // 页面按键事件控制转移到闭包

            G.rand();

            G.next();

        },

        timeTesk:function(){

            if(G.pause)return;// 如果暂停按钮按下,则停止该函数运行

            if(!G.move(G.x, G.y+1, G.t)){ // 是否能继续下移

                var s = 0;

                for(var i=0;i<19;i++){

                    G.v[i]=G.v[i]|G.m[i];

                    if(G.v[i]==0xFFF){// 根据行点阵判断是否已达到可消除行

                        for(var k=i;k>0;k--){

                            G.v[k] = G.v[k-1];// 消除已完全成行(向下移位)

                        }

                        G.score+=++s;// 计分

                    }

                }

                G.next();

                return false;

            }

            G.draw();

            return true;

        },

        move:function(x,y,t){ // 位移函数

            var m = [];

            for(var k=0;k<4;k++){ // 因为方块形状建模是4X4点阵.所以循环4次

                m[y+k] = (G.d[G.n][t]>>(3-k)*4&0xF)<<Math.max(x,0)>>-Math.min(x,0);

                // G.d[G.n]为现在使用的方块点阵模型,[t]为第t种旋转模型点阵

                // G.d[G.n][t]>>(3-k)*4&0xF为获取单行位移后的点阵

                // <<Math.max(x,0)>>-Math.min(x,0)为判断x为左移还是右移

                // m[y+k]对应位移点阵行

                if(m[y+k] & G.v[y+k]){// 判断是否位移后点阵与游戏区现有点阵重叠

                    return false;

                }

            }

            G.x = x;// 保存当前下落点阵模型坐标

            G.y = y;// 保存当前下落点阵模型坐标

            G.t = t;// 保存当前下落点阵模型旋转模型

            G.m = m;// 保存当前下落点阵模型在类游戏区的位置(镜像位置)

            G.draw();

            return true;

        },

        rand:function(){

            G.n = G._n; // 获取上次生成的随机方块点阵模型

            G.t = G._t; // 获取上次生成的随机方块点阵旋转系数

            G.c = G._c; // 获取上次生成的随机颜色

            G._n = parseInt(Math.random()*G.d.length); // 以模型长度生成随机数

            G._t = parseInt(Math.random()*G.d[G._n].length); // 同上

            G._c = parseInt(Math.random()*G.l.length); // 同上

        },

        next:function(){

            G.rand();

            if(parseInt(G.score/20)!=G.level){ // 分数与等级互换的概念...20分一级哦...

                G.level = parseInt(G.score/20);  // 不等于当前等级则升级

                clearInterval(G.handle); // 清楚上一计时器

                G.handle = setInterval("G.timeTesk()",500/(G.level+1));// 按等级设计时器(控制速度的地方哦!)

            }

            G.domScore.innerHTML = 'Score:'+G.score; // 更新分数

            G.domLevel.innerHTML = 'Level:'+G.level; // 更新等级

            var i = 0;

            while(!(G.d[G.n][G.t]>>i*4&0xF))i++; // 将i移动到点阵模型有显示的第一行

            if(!G.move(3, i-3, G.t)){// 如果在点阵模型3行内不能进行向上位移(即点阵到游戏区顶部)

                alert('Game over!'); // 则Game over并提示

                clearInterval(G.handle); // 良好习惯,清除计时器

            }

        },

        draw:function(){

            for(var i=0;i<240;i++){// 遍历游戏区全点阵,每i为全点阵中的1点

                if((G.v[parseInt(i/12)]>>(11-i%12))&0x1){

                // G.v[parseInt(i/12)为该点所在行

                // >>(11-i%12))&0x1为整体操作,&运算前将点移后,让&运算能判断点是否显示

                    G.fs[i].style.visibility = ''; // 判断为真则显示

                }else if((G.m[parseInt(i/12)]>>(11-i%12))&0x1){ // 同上理画下落中的模型镜像点阵

                    G.fs[i].style.visibility = '';

                    G.fs[i].style.borderColor = G.fs[i].style.background = G.l[G.c]; // 上色

                }else{

                    G.fs[i].style.visibility ='hidden'; // 判断为假则隐藏

                }

            }

            for(var i=0;i<16;i++){ // 同理画预览区点阵

                if(G.d[G._n][G._t]>>(15-i)&0x1){

                    G.fn[i].style.visibility = '';

                    G.fn[i].style.borderColor = G.fn[i].style.background = G.l[G._c];

                }else{

                    G.fn[i].style.visibility ='hidden';

                }

            }

        },

        event:function(e,t){

            switch(e.keyCode){

                case 37: // 左键

                    G.move(G.x + 1, G.y, G.t);

                break;

                case 39: // 右键

                    G.move(G.x - 1, G.y, G.t);

                break;

                case 38: // 上键

                    G.move(G.x, G.y, (G.t + 1) % G.d[G.n].length);

                break;

                case 40: // 下键

                    G.timeTesk();

                break;

                case 32: // 空格...看了半天才知道原来按空格直接落底...

                    while(G.timeTesk());   

            }

        }

    }

</script>

<body onload='G.init();'><!-- 网页读取后初始化 -->

    <div id='main'>

        <div id='body'></div>

        <div id='score'></div>

        <div id='level'></div>

        <div id='next'></div>

        <div id='ctrl'>

            <button onclick="javascript:location.href=location.href;">New</button>

            <!-- 重置等于重新读取网页 -->

            <button onclick="javascript:this.innerHTML={'true':'Start','false':'Pause'}[G.pause=!!!G.pause];">Pause</button>

            <!-- 这里运用了一个很好的技巧:!!的用法,可以将为空的数据转成false,避免出现空指针异常 -->

        </div>

    </div>  

</body>

</html>

posted @ 2010-09-30 08:47  Daniel_Lu  阅读(492)  评论(0编辑  收藏  举报