新书推介:《语义网技术体系》
作者:瞿裕忠,胡伟,程龚
   XML论坛     W3CHINA.ORG讨论区     >>计算机科学论坛<<     SOAChina论坛     Blog     开放翻译计划     新浪微博  
 
  • 首页
  • 登录
  • 注册
  • 软件下载
  • 资料下载
  • 核心成员
  • 帮助
  •   Add to Google

    >> 本版讨论SVG, GML, X3D, VRML, VML, XAML, AVALON, Batik等基于XML的图形技术,以及有关GIS的应用。
    [返回] 计算机科学论坛XML.ORG.CN讨论区 - 高级XML应用『 SVG/GML/VRML/X3D/XAML 』 → [转帖]SVG实例展-俄罗斯方块 查看新帖用户列表

      发表一个新主题  发表一个新投票  回复主题  (订阅本版) 您是本帖的第 2774 个阅读者浏览上一篇主题  刷新本主题   树形显示贴子 浏览下一篇主题
     * 贴子主题: [转帖]SVG实例展-俄罗斯方块 举报  打印  推荐  IE收藏夹 
       本主题类别:     
     wanghai00 帅哥哟,离线,有人找我吗?魔羯座2000-12-31
      
      
      威望:4
      等级:大四(总算啃完XML规范了)
      文章:108
      积分:1085
      门派:XML.ORG.CN
      注册:2005/10/1

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给wanghai00发送一个短消息 把wanghai00加入好友 查看wanghai00的个人资料 搜索wanghai00在『 SVG/GML/VRML/X3D/XAML 』的所有贴子 点击这里发送电邮给wanghai00  访问wanghai00的主页 引用回复这个贴子 回复这个贴子 查看wanghai00的博客楼主
    发贴心情 [转帖]SVG实例展-俄罗斯方块

    一个外国佬用SVG编的俄罗斯方块,超强!

    下面为svg源文件:

    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
    <!--
        YAST
        Copyright (c) 2005, Jeff Schiller
        http://www.codedread.com/
    -->
    <svg id="svgsvg" version="1.1"
        width="100%" height="100%"
        viewBox="0 0 800 600"
        xmlns="http://www.w3.org/2000/svg"
        xmlns:xlink="http://www.w3.org/1999/xlink"
        cursor="wait"
        onload="setTimeout('init()', 100);"
        >
    <script xlink:href="yast.js"/>
    <defs>

        <!-- Learned this from Jan Kollhoff's SVG Aqua Button tutorial:
             http://jan.kollhof.net/projects/svg/examples/aqua.svg -->

        <!-- Background Paint -->
        <linearGradient id="bkgnd" x1="0.0" y1="0.0" x2="1.0" y2="1.0">
            <stop offset="0.0" stop-color="#0000aa" stop-opacity="0.8" />
            <stop offset="1.0" stop-color="#000000" stop-opacity="0.8" />
        </linearGradient>

        <!-- Block Definitions -->
        <g id="matteblock">
            <rect x="0" y="0" width="20" height="20"
                fill="inherit" stroke="black" />
        </g>
        <g id="block">
            <rect x="0" y="0" width="20" height="20" rx="3" ry="3"
                fill="inherit" stroke="black" />
            <!-- glare -->
            <path d="M3,12 L3,3 L12,3 L5,5 Z" fill="white" opacity="0.4"/>
            <path d="M17,8 L17,17 L8,17 L15,15 Z" fill="white" opacity="0.4"/>
        </g>

        <!-- Begin Button Definitions -->
        <!-- Button background paints -->
        <linearGradient id="activebuttonbkgnd" x1="0.0" y1="0.0" x2="0.0" y2="1.0">
            <stop offset="0.0" stop-color="#5a0000" stop-opacity="0.8" />
            <stop offset="1.0" stop-color="#ff0000" stop-opacity="0.8" />
        </linearGradient>        
        
        <linearGradient id="pressedbuttonbkgnd" x1="0.0" y1="0.0" x2="0.0" y2="1.0">
            <stop offset="0.0" stop-color="#7a2000" stop-opacity="1.0" />
            <stop offset="1.0" stop-color="#ff7000" stop-opacity="1.0" />
        </linearGradient>
        <linearGradient id="inactivebuttonbkgnd" x1="0.0" y1="0.0" x2="0.0" y2="1.0">
            <stop offset="0.0" stop-color="#000" stop-opacity="0.5" />
            <stop offset="1.0" stop-color="#557" stop-opacity="0.5" />
        </linearGradient>
        <!-- Top Highlight -->
        <linearGradient id="tophigh" x1="0.0" y1="0.0" x2="0.0" y2="1.0">
            <stop offset="0.0" stop-color="#ffffff" stop-opacity="0.7" /> <!-- 0.7 -->
            <stop offset="0.9" stop-color="#ffffff" stop-opacity="0.0" /> <!-- 0.0 -->
        </linearGradient>
        <!-- Bottom Gradient -->
        <linearGradient id="bottomhigh" x1="0.0" y1="0.0" x2="0.0" y2="1.0">
            <stop offset="0.2" stop-color="#ffffff" stop-opacity="0.0"/> <!-- 0.0 -->
            <stop offset="1.0" stop-color="#ffffff" stop-opacity="0.6" /> <!-- 0.6 -->
        </linearGradient>

        <!-- Blurs the bottom highlight -->
        <filter id="gblur">
            <feGaussianBlur stdDeviation="2" />
        </filter>
        <!-- To give that text a slightly "baked-in" feel -->
        <filter id="gblurshadow">
            <feGaussianBlur stdDeviation="0.8" />
        </filter>
        
        <rect id="butt" x="0" y="0" width="87" height="40" rx="25" ry="25"
                fill="inherit" stroke="none" />

        <g id="button">
            <use xlink:href="#butt" fill="inherit" />
            <use transform="scale(0.8,0.45) translate(12,4)" xlink:href="#butt"
                fill="url(#tophigh)" />
            <use transform="scale(0.8,0.45) translate(12,45)" xlink:href="#butt"
                fill="url(#bottomhigh)" filter="url(#gblur)"/>
        </g>

        <g id="vanilla_button">
            <use xlink:href="#butt" fill="inherit" />
        </g>
        
        <polyline id="check" fill="none" stroke="green" stroke-width="5"
            points="0,12 6,20 20,0"/>
        <!-- NOTE:  If I fill this with none, onclick only works on the stroke.  Thus
                    I have to set pointer-events -->
        <rect id="checkbox" pointer-events="fill" fill="none" stroke="yellow" stroke-width="3"
            x="0" y="0" width="15" height="15"/>

        <!-- End Button Definitions -->
    </defs>

    <rect id="canvas" x="0" y="0" width="800" height="600" fill="url(#bkgnd)" />

    <g id="title">
        <a xlink:href="http://www.codedread.com/" target="_none">
        <text id="titletext" x="77" y="50" font-size="48" fill="yellow">YAST!</text>
        </a>
        <text id="leveltext" x="600" y="50" font-size="32" fill="yellow">Level: 1</text>
        <rect x="72" y="65" width="650" height="5" rx="50" ry="50" fill="yellow" stroke="black"/>
    </g>    

    <text id="message" x="150" y="300" font-size="48" fill="yellow"
        >Loading...Please Wait...</text>

    <!-- Buttons Panel -->
    <g id="buttonspanel" display="none">
    <g id="startbut" transform="translate(100,105)">
        <use id="startbut_use" xlink:href="#button" x="0" y="0" width="100" height="50" />
        <text id="startlabel" x="24" y="28" font-size="18" fill="yellow">Start</text>
    </g>

    <g id="pausebut" transform="translate(100,165)">
        <use id="pausebut_use" xlink:href="#button" x="0" y="0" width="100" height="50" />
        <text id="pauselabel" x="19" y="28" font-size="18" fill="yellow">Pause</text>
    </g>

    <g id="helpbut" transform="translate(100,225)">
        <use id="helpbut_use" xlink:href="#button" x="0" y="0" width="100" height="50" />
        <text id="helplabel" x="25" y="28" font-size="18" fill="yellow">Help</text>
    </g>

    <text id="effectslabel" x="38" y="330" font-size="32" fill="yellow">Effects:</text>
    <g id="effectspanel" transform="translate(38,340)">
        <rect x="0" y="0" width="192" height="240" rx="10" ry="10" fill="none"
            stroke="yellow" stroke-width="1"/>

        <g id="effect_gradback">
            <use id="effect_gradback_box" xlink:href="#checkbox" x="10" y="30"/>
            <use id="effect_gradback_check" xlink:href="#check" x="11" y="20" display="inline" />
            <text x="34" y="43" font-size="16" fill="yellow">Gradient Background</text>
        </g>

        <g id="effect_aquabutt">
            <use id="effect_aquabutt_box" xlink:href="#checkbox" x="10" y="55"/>
            <use id="effect_aquabutt_check" xlink:href="#check" x="11" y="45" display="inline" />
            <text x="34" y="68" font-size="16" fill="yellow">Aqua Buttons</text>
        </g>
    </g>

    </g> <!-- End Buttons Panel -->

    <g id="gamescreen" display="none">
        <switch>
            <rect requiredFeatures="http://www.w3.org/TR/SVG11/feature#Filter"
                x="10" y="10" width="322" height="502" opacity="0.6"
                fill="black" stroke="none" filter="url(#gblurshadow)" />
            <rect x="10" y="10" width="322" height="502" opacity="0.6"
                fill="black" stroke="none" />
        </switch>         
            
        <g id="starfield">
            <rect id="space" x="0" y="0" width="322" height="502" fill="#444" stroke="yellow" />
            <!-- Should put some stars here as a nice effect one day -->
        </g>

        <g id="gameborder">
        </g>
        
        <g id="gamegrid">
        </g>

    </g>

    <g id="gameinfo" display="none">
        <g id="thescore">
            <text id="scorelabel" x="600" y="150" font-size="32" fill="yellow">Score:</text>
            <text id="score" x="600" y="190" font-size="32" fill="yellow">0</text>
        </g>
        
        <g id="next">
            <text id="rowsleftlabel" x="600" y="250" font-size="32" fill="yellow">Rows Left:</text>
            <text id="rowsleft" x="600" y="290" font-size="32" fill="yellow">10</text>
        </g>

        <g id="next">
            <text id="nextlabel" x="600" y="350" font-size="32" fill="yellow">Next:</text>
            <g id="nextblok" transform="translate(600,390)">
            </g>
        </g>
    </g>

    <g id="helpscreen" display="none" transform="translate(250,150)">
        <rect x="0" y="0" width="300" height="300" rx="20" ry="20"
            fill="white" stroke="black" />
            
        <text x="67" y="30" font-size="32" fill="black">Instructions</text>
        <text x="20" y="70" font-size="20" fill="black">Left Arrow:</text>
        <text x="140" y="70" font-size="20" fill="black">Move block left</text>
        <text x="20" y="100" font-size="20" fill="black">Right Arrow:</text>
        <text x="140" y="100" font-size="20" fill="black">Move block right</text>
        <text x="20" y="130" font-size="20" fill="black">Up Arrow:</text>
        <text x="140" y="130" font-size="20" fill="black">Rotate block</text>
        <text x="20" y="160" font-size="20" fill="black">Down Arrow:</text>
        <text x="140" y="160" font-size="20" fill="black">Hurry descent</text>
        <text x="20" y="190" font-size="20" fill="black">Space:</text>
        <text x="140" y="190" font-size="20" fill="black">Drop block</text>
        <text x="20" y="220" font-size="20" fill="black">S:</text>
        <text x="140" y="220" font-size="20" fill="black">Start game</text>
        <text x="20" y="250" font-size="20" fill="black">P or Q:</text>
        <text x="140" y="250" font-size="20" fill="black">Pause game</text>
        <text x="30" y="280" font-size="20" fill="black">(Click this window to close)</text>
    </g>

    </svg>


    下面为用到的js:yast.js

    // JavaScript for YAST
    // Copyright (c) 2006, Jeff Schiller
    // http://www.codedread.com/
    // Updated 2005-11-20 to avoid memory leaks in Firefox

    //
    // ===========================================
    // CONSTANTS
    // ===========================================
    var buttons = [ "startbut",
                    "pausebut",
                    "helpbut"
                    ];
    var displayableElements = [
                                "buttonspanel",
                                "gamescreen",
                                "gameinfo"
                                ];
    // I have to give acknowledgments to Alex Fritze at
    // http://www.croczilla.com/svg/samples/svgtetris/svgtetris.svg
    // for this very sensible idea...
    // (I was going to put it all in SVG and then use rotations!)
    var gBlocks = [
                    [ [[0,0],[0,1],[1,0],[1,1]] ],
                    [ [[0,0],[0,1],[0,2],[0,3]], [[0,0],[1,0],[2,0],[3,0]] ],
                    [ [[0,0],[1,0],[0,1],[0,2]], [[0,0],[1,0],[2,0],[2,1]], [[1,0],[1,1],[1,2],[0,2]], [[0,0],[0,1],[1,1],[2,1]] ],
                    [ [[1,1],[1,0],[0,0],[1,2]], [[1,1],[2,1],[2,0],[0,1]], [[0,1],[0,2],[1,2],[0,0]], [[1,0],[0,0],[0,1],[2,0]] ],
                    [ [[1,1],[0,1],[1,0],[2,1]], [[0,1],[0,0],[1,1],[0,2]], [[1,0],[0,0],[1,1],[2,0]], [[1,1],[1,2],[0,1],[1,0]] ],
                    [ [[0,0],[0,1],[1,1],[1,2]], [[1,0],[2,0],[1,1],[0,1]] ],
                    [ [[1,1],[1,0],[0,1],[0,2]], [[1,1],[2,1],[1,0],[0,0]] ]
                    ];
    var gsBlockColors = [ "green", "red", "blueviolet", "olive",
                            "blue", "mediumseagreen", "maroon", "black" ];
    var gSVGNS = "http://www.w3.org/2000/svg";
    var gXLINKNS = "http://www.w3.org/1999/xlink";
    var WIDTH=320;
    var HEIGHT=500
    var BLOCKSIZE=20;
    var NUMCOLS = (WIDTH/BLOCKSIZE)-2;
    var NUMROWS = (HEIGHT/BLOCKSIZE)-1;
    var DROPTIMER = 25;
    var ROWSTOCLEAR = 10;
    var VERSION = "0.1";

    var KEY_LEFT = 37;
    var KEY_RIGHT = 39;
    var KEY_DOWN = 40;
    var KEY_UP = 38;
    var KEY_SPACE = 32;
    var KEY_P = 80;
    var KEY_Q = 81;
    var KEY_S = 83;
    // ===========================================

    // ===========================================
    // Global Variables
    // ===========================================
    var gHelpOn = false;
    var gPaused = true;

    // these should one day be made into an object
    var gCurrentBlockNum = -1;
    var gCurrentBlockOrient = 0;
    var gCurrentBlockTop = 0;
    var gCurrentBlockLeft = 0;
    var gNextBlockNum = -1;
    var gNextBlockOrient = 0;
    var gDropTimer = 0;
    var gsPressedButtonBkgnd = "url(#pressedbuttonbkgnd)";
    var gsActiveButtonBkgnd = "url(#activebuttonbkgnd)";
    var gsInactiveButtonBkgnd = "url(#inactivebuttonbkgnd)";
    var gLevel = 1;
    var gRowsLeft = ROWSTOCLEAR;

    function Cell(parentElement) {
        this.currentColor = -1; // not displayed
        this.parent = parentElement;

        var tempBlock = document.createElementNS(gSVGNS, "use");
        tempBlock.setAttributeNS(gXLINKNS, "href", "#block");
        tempBlock.setAttribute("display", "none");
        
        this.block = this.parent.appendChild(tempBlock);

        this.setColor = function(color) {
            this.block.setAttribute("display", "inline");
            this.block.setAttribute("fill", gsBlockColors[color]);
            this.currentColor = color;
        }
        this.unsetColor = function() {
            this.block.setAttribute("display", "none");
            this.currentColor = -1;
        }
        this.isSet = function() { return (this.currentColor != -1); }
    }


    // this tracks every cell in the grid
    var gGrid = new Array(NUMROWS);
    var gNextBlock = new Array(4);

    // total number of blocks created (set to -1
    // so the first block doesn't count until it is
    // dropped)
    var gTotalBlocks = -1;
    // ===========================================

    function inspect(obj) {
        var str = new Array();
        for(element in obj) { str[str.length] = element; }
        str.sort();
        alert(obj + ":" + str.join(' '));
    }

    // Aqua buttons with animation
    function highlightButton(evt)
    {
        if(evt && evt.currentTarget)
            evt.currentTarget.setAttribute("fill", gsPressedButtonBkgnd);
    }

    function unhighlightButton(evt)
    {
        if(evt && evt.currentTarget)
            evt.currentTarget.setAttribute("fill", gsActiveButtonBkgnd);
    }

    function setButtonActive(button, bActive) {
        if(!button) { return; }
        // class=active_button
        if(bActive) {
            button.setAttribute("enabled", "true");
            button.setAttribute("fill", gsActiveButtonBkgnd);
            button.setAttribute("opacity", "1.0");
            button.setAttribute("cursor", "pointer");
            button.addEventListener("mousedown", highlightButton, false);
            button.addEventListener("mouseup", unhighlightButton, false);
        }
        // class=inactive_button
        else {
            button.setAttribute("enabled", "false");
            button.setAttribute("fill", gsInactiveButtonBkgnd);
            button.setAttribute("opacity", "0.5");
            button.setAttribute("cursor", "default");
            button.removeEventListener("mousedown", highlightButton, false);
            button.removeEventListener("mouseup", unhighlightButton, false);
        }
    }

    function unsetSquare(x,y,grid)
    {
        var cell = grid[y][x];
        if(cell) {
            cell.unsetColor();
        }
    }
    function setSquare(x,y,color,grid)
    {
        var cell = grid[y][x];
        if(cell) {
            cell.setColor(color);
        }
    }

    function doesBlockCollide(arr, left, top)
    {
        for(var pt = 0; pt < 4; ++pt) {
            if( arr[pt][1]+top >= NUMROWS ||                            // if we've reached the bottom
                arr[pt][0]+left < 0 || arr[pt][0]+left >= NUMCOLS ||    // or gone over the sides
                gGrid[ arr[pt][1]+top ][ arr[pt][0]+left ].isSet()) // or collided with another brick
            {
                return true;
            }
        }
        return false;
    }

    function undrawBlock(left, top, blocknum, blockorient, grid)
    {
        if(blocknum==-1) { return; }
        
        for(var pt = 0; pt < 4; ++pt) {
            unsetSquare(left + gBlocks[blocknum][blockorient][pt][0],
                        top + gBlocks[blocknum][blockorient][pt][1],
                        grid);
        }    
    }

    function drawBlock(left, top, blocknum, blockorient, grid)
    {
        if(blocknum==-1) { return; }
        
        for(var pt = 0; pt < 4; ++pt) {
            setSquare(left + gBlocks[blocknum][blockorient][pt][0],
                        top + gBlocks[blocknum][blockorient][pt][1],
                        blocknum,
                        grid);
        }    
    }

    function undrawCurrentBlock()
    {
        undrawBlock(gCurrentBlockLeft, gCurrentBlockTop, gCurrentBlockNum, gCurrentBlockOrient, gGrid);
    }

    function drawCurrentBlock()
    {
        drawBlock(gCurrentBlockLeft, gCurrentBlockTop, gCurrentBlockNum, gCurrentBlockOrient, gGrid);
    }

    function undrawNextBlock()
    {
        undrawBlock(0, 0, gNextBlockNum, gNextBlockOrient, gNextBlock);
    }
    function drawNextBlock()
    {
        drawBlock(0, 0, gNextBlockNum, gNextBlockOrient, gNextBlock);
    }

    function createBlock()
    {
        var blocknum = Math.floor(Math.random()*gBlocks.length);
        
        var maxorientation = gBlocks[blocknum].length;
        var orientation = Math.floor(Math.random()*maxorientation);
        
        undrawNextBlock();
        
        gCurrentBlockNum = gNextBlockNum;
        gCurrentBlockOrient = gNextBlockOrient;
        gCurrentBlockTop = 0;
        gCurrentBlockLeft = NUMCOLS/2 - 2;
        
        gNextBlockNum = blocknum;
        gNextBlockOrient = orientation;
        
        ++gTotalBlocks;
        //if(gTotalBlocks % 10 == 0) { --DROPTIMER; if(DROPTIMER < 0) { DROPTIMER = 0; } }

        var bCollide = doesBlockCollide(gBlocks[gCurrentBlockNum][gCurrentBlockOrient], gCurrentBlockLeft, gCurrentBlockTop);
        
        drawNextBlock();
        drawCurrentBlock();
       
        return !bCollide;
    }

    function restartGame() {
        for(var row = 0; row < NUMROWS; ++row) {
            for(var col = 0; col < NUMCOLS; ++col) {
                unsetSquare(col,row,gGrid);
            }
        }

        for(var row = 0; row < 4; ++row) {
            for(var col = 0; col < 4; ++col) {
                unsetSquare(col,row,gNextBlock);
            }
        }
        
        var textele = document.getElementById("score");
        if(textele) {
            textele.firstChild.nodeValue = 0;
        }
        
        gDropTimer = DROPTIMER;
        gLevel = 1;
        gRowsLeft = ROWSTOCLEAR;
        var rowsleft = document.getElementById("rowsleft");
        if(rowsleft) {
            // update num rows left text ...
            rowsleft.firstChild.nodeValue = "" + gRowsLeft;
        }
        
        gNextBlockNum = Math.floor(Math.random()*gBlocks.length);
        gNextBlockOrient = Math.floor(Math.random()*gBlocks[gNextBlockNum].length);
    }

    function dropBlock()
    {
        undrawCurrentBlock();
        if(doesBlockCollide(gBlocks[gCurrentBlockNum][gCurrentBlockOrient],gCurrentBlockLeft,gCurrentBlockTop+1)) {
            drawCurrentBlock();
            return true;
        }
        else {
            ++gCurrentBlockTop;
            drawCurrentBlock();
        }
        return false;
    }

    function startLevel(levnum) {
        var leveltext = document.getElementById("leveltext");
        if(leveltext) {
            // update level text...
            leveltext.firstChild.nodeValue = "Level: " + levnum;
        }
        
        gRowsLeft = ROWSTOCLEAR;
        var rowsleft = document.getElementById("rowsleft");
        if(rowsleft) {
            // update num rows left text ...
            rowsleft.firstChild.nodeValue = "" + gRowsLeft;
        }    

        for(var row = 0; row < 4; ++row) {
            for(var col = 0; col < 4; ++col) {
                unsetSquare(col,row,gNextBlock);
            }
        }

        for(var row = 0; row < NUMROWS; ++row) {
            for(var col = 0; col < NUMCOLS; ++col) {
                unsetSquare(col,row,gGrid);
            }
        }
        
        // now randomly set a bunch of blocks
        var numblockstolay = (levnum-1)*4;
        while(numblockstolay) {
            var x = Math.floor(Math.random()*NUMCOLS);
            var y = NUMROWS - 1 - Math.floor(Math.random()*levnum);
            setSquare(x,y,gsBlockColors[gsBlockColors.length-1],gGrid);
            
            --numblockstolay;
        }
    }

    function doRowCheck()
    {
        var numRows = 0;
        // start from the bottom up, when we get to a row where no squares
        // had any children, then we are done
        
        for(var y = NUMROWS-1; y >=0; --y) {
            var bAnyOccupied = false;
            var bAnyMissing = false;
            
            for(var x = 0; x < NUMCOLS; ++x) {
                if(gGrid[y][x].isSet()) {
                    bAnyOccupied = true;
                }
                else {
                    bAnyMissing = true;
                }
            } // done one row
            
            if(!bAnyOccupied) { break; }
            
            if(!bAnyMissing) {
                ++numRows;
                
                // row to be deleted and all rows pushed down
                // start y-loop again, pushing all row contents down by one
                for(var newy = y; newy >= 0; --newy) {
                    var bStopPushing = true;
                    
                    for(var x = 0; x < NUMCOLS; ++x) {
                        // if square above is occupied then
                        if(gGrid[newy-1][x].isSet()) {
                            bStopPushing = false;
                            gGrid[newy][x].setColor(gGrid[newy-1][x].currentColor);
                            gGrid[newy-1][x].unsetColor();
                        }
                        else {
                            gGrid[newy][x].unsetColor();
                        }
                    } // for x
                    if(bStopPushing) {
                        break;
                    }
                    
                } // for newy
                ++y; // increment y back so we check the row that was moved down
            } // if none were missing, we had to remove at least one row
        } // for y
        
        // update score and possibly advance level
        if(numRows > 0) {
        
            gRowsLeft -= numRows;
            var rowsleft = document.getElementById("rowsleft");
            if(rowsleft) {
                // update num rows left text ...
                rowsleft.firstChild.nodeValue = "" + gRowsLeft;
            }
            
            var delta = 25;
            while(numRows > 1) { delta <<= 1; --numRows;}
            delta *= gLevel;
            var textele = document.getElementById("score");
            if(textele) {
                // update score...
                var score = parseInt(textele.firstChild.nodeValue) + delta;
                textele.firstChild.nodeValue = score+"";
            }

            if(gRowsLeft <= 0) {
                ++gLevel;
                --DROPTIMER;
                startLevel(gLevel);
            }
        }
        
    }

    function gameTick()
    {
        if(gPaused) { return; }

        if(gCurrentBlockNum == -1) {
            gDropTimer = DROPTIMER;
            
            // check for any complete rows and remove them
            doRowCheck();
            
            if(!createBlock()) {
                pauseClick();
                alert("Game over!");
                restartGame();
            }
        }
        else if(gDropTimer == 0) {
            gDropTimer = DROPTIMER;
            // process drop of block
            if(dropBlock()) {
                gCurrentBlockNum = -1;
            }
        }
        else {
            --gDropTimer;
        }
    }

    function helpoff(evt) {
        gHelpOn = false;
        var helpscreen = document.getElementById("helpscreen");
        if(helpscreen) {
            helpscreen.setAttribute("display", "none");
            helpscreen.removeEventListener("click", helpoff, false);
        }
    }
        
    function helpClick(evt) {
        var butt = evt.currentTarget;
        if(butt && butt.getAttribute("enabled") == "true" && !gHelpOn) {
            // pause game
            pauseClick(evt);
            gHelpOn = true;
            
            var helpscreen = document.getElementById("helpscreen");
            if(helpscreen) {
                helpscreen.setAttribute("display", "inline");
                helpscreen.addEventListener("click", helpoff, false);
            }
        }
    }

    function pauseClick(evt) {
        if(gHelpOn) { return; }
        
        var butt = document.getElementById("pausebut");
        if(butt) { setButtonActive(butt,false); }
        
        butt = document.getElementById("startbut");
        if(butt) { setButtonActive(butt, true); }
            
        gPaused = true;
    }

    function startClick(evt) {
        if(gHelpOn) { return; }

        var butt = document.getElementById("startbut");
        if(butt) { setButtonActive(butt, false); }
        
        butt = document.getElementById("pausebut");
        if(butt) { setButtonActive(butt, true); }
            
        gPaused = false;
    }

    function toggleEffect(evt)
    {
        if(evt && evt.currentTarget) {
            var effectName = evt.currentTarget.getAttribute("id");
            var check = document.getElementById(effectName + "_check");
            if(check) {
                var bEnable = !(check.getAttribute("display") == "inline");
                check.setAttribute("display", (bEnable ? "inline" : "none"));
                switch(effectName) {
                    case "effect_gradback":
                        var canvas = document.getElementById("canvas")
                        if(canvas) {
                            canvas.setAttribute("fill", (bEnable ? "url(#bkgnd)" : "#008"));
                        }
                        break;
                    case "effect_aquabutt":
                        if(bEnable) {
                            gsPressedButtonBkgnd = "url(#pressedbuttonbkgnd)";
                            gsActiveButtonBkgnd = "url(#activebuttonbkgnd)";
                            gsInactiveButtonBkgnd = "url(#inactivebuttonbkgnd)";
                        }
                        else {
                            gsPressedButtonBkgnd = "#a70";
                            gsActiveButtonBkgnd = "#a00";
                            gsInactiveButtonBkgnd = "#aaa";
                        }
                        for(var butt = 0; butt < buttons.length; ++butt) {
                            var buttonuser = document.getElementById(buttons[butt] + "_use");
                            if(buttonuser) {
                                buttonuser.setAttributeNS(gXLINKNS, "href",
                                        (bEnable ? "#button" : "#vanilla_button"));
                                if(buttonuser.parentNode) {
                                    var button = buttonuser.parentNode;
                                    var bActive = button.getAttribute("enabled");
                                    setButtonActive(button, (bActive=="true"));
                                }
                            }
                        }
                        break;
                    default:
                        alert("Unknown effect");
                        break;
                }
            }
        }
    }

    function initializeButtons() {
        var button = null;
        
        // Start button
        if( (button = document.getElementById("startbut")) ) {
            setButtonActive(button, true);
            button.addEventListener("click", startClick, false);
        }

        // Pause button
        if( (button = document.getElementById("pausebut")) ) {
            setButtonActive(button, false);
            button.addEventListener("click", pauseClick, false);
        }
        
        // Help button
        if( (button = document.getElementById("helpbut")) ) {
            setButtonActive(button, true);
            button.addEventListener("click", helpClick, false);
        }

        // Effects
        if( (button = document.getElementById("effect_gradback")) ) {
            button.addEventListener("click", toggleEffect, false);
        }
        if( (button = document.getElementById("effect_aquabutt")) ) {
            button.addEventListener("click", toggleEffect, false);
        }
        
        // hide "Please Wait" message
        var msg = document.getElementById("message");
        if(msg) {
            msg.setAttribute("display", "none");
        }
    }

    function initializeGameboard() {
        var gamescreen = document.getElementById("gamescreen");
        if(!gamescreen) { return; }
        
        gamescreen.setAttribute("transform", "translate(240,80)");
        
        // create border
        var border = document.getElementById("gameborder");
        if(border) {
            var block = null;
            var sBorderColor = "#666";
            for(var row=0; row < NUMROWS+1; ++row) {
                block = document.createElementNS(gSVGNS, "use");
                if(block) {
                    block.setAttributeNS(gXLINKNS, "href", "#matteblock");
                    block.setAttribute("fill", sBorderColor);
                    block.setAttribute("transform", "translate(1," + (1+row*BLOCKSIZE) + ")");
                    border.appendChild(block);
                }
                block = document.createElementNS(gSVGNS, "use");
                if(block) {
                    block.setAttributeNS(gXLINKNS, "href", "#matteblock");
                    block.setAttribute("fill", sBorderColor);
                    block.setAttribute("transform", "translate(" + (WIDTH-BLOCKSIZE) + ","
                                        + (1+row*BLOCKSIZE) + ")");
                    border.appendChild(block);
                }
            }
            for(var col = 0; col < NUMCOLS+2; ++col) {
                block = document.createElementNS(gSVGNS, "use");
                if(block) {
                    block.setAttributeNS(gXLINKNS, "href", "#matteblock");
                    block.setAttribute("fill", sBorderColor);
                    block.setAttribute("transform", "translate(" + (col*BLOCKSIZE+1) + ","
                                        + (HEIGHT-BLOCKSIZE) + ")");
                    border.appendChild(block);
                }
            }
        }
        else {
            alert("Could not find border group");
        }
        
        // create grid
        var gamegrid = document.getElementById("gamegrid");
        if(gamegrid) {
            for(var row = 0; row < NUMROWS; ++row) {
                var rowg = document.createElementNS(gSVGNS, "g");
                rowg.setAttribute("transform", "translate("+BLOCKSIZE+","+(row*BLOCKSIZE)+")");
                
                gGrid[row] = new Array(NUMCOLS);
                for(var col = 0; col < NUMCOLS; ++col) {
                    var squareg = document.createElementNS(gSVGNS, "g");
                    squareg.setAttribute("transform", "translate("+(col*BLOCKSIZE)+")");
                    squareg.setAttribute("width", ""+BLOCKSIZE);
                    squareg.setAttribute("height", ""+BLOCKSIZE);
                    
                    // 2005-11-20:  Fix for JS leaks in Firefox
                    gGrid[row][col] = new Cell(squareg);
                    
                    rowg.appendChild(squareg);
                } // for column      
                
                gamegrid.appendChild(rowg);
            } // for row
        }
        
        // create next block (4x4)
        var nextblok = document.getElementById("nextblok");
        if(nextblok) {
            for(var row = 0; row < 4; ++row) {
                var rowg = document.createElementNS(gSVGNS, "g");
                rowg.setAttribute("transform", "translate("+BLOCKSIZE+","+(row*BLOCKSIZE)+")");
                
                gNextBlock[row] = new Array(4);
                for(var col = 0; col < 4; ++col) {
                    var squareg = document.createElementNS(gSVGNS, "g");
                    squareg.setAttribute("transform", "translate("+(col*BLOCKSIZE)+")");
                    squareg.setAttribute("width", ""+BLOCKSIZE);
                    squareg.setAttribute("height", ""+BLOCKSIZE);
                    
                    // 2005-11-20:  Fix for JS leaks in Firefox
                    gNextBlock[row][col] = new Cell(squareg);
                                    
                    rowg.appendChild(squareg);
                }
                nextblok.appendChild(rowg);
            }
        }
    }

    function displayAll() {
        var ele = null;
        var num = 0;
        
        // display elements
        for(num = 0; num < displayableElements.length; ++num) {
            if( (ele = document.getElementById(displayableElements[num])) ) {
                ele.setAttribute("display", "inline");
            }
        }
    }

    function getKey(evt)
    {
        if(gCurrentBlockNum == -1) { return; }

        evt.preventDefault();

        // if we're paused, only accept the start key
        if(gPaused && (evt.keyCode == KEY_S)) {
            startClick();
        } // if paused
        // else, any key
        else {
            switch(evt.keyCode) {
            case KEY_LEFT:
                undrawCurrentBlock();
                if(!doesBlockCollide(gBlocks[gCurrentBlockNum][gCurrentBlockOrient],gCurrentBlockLeft-1,gCurrentBlockTop)) {
                    --gCurrentBlockLeft;
                }
                drawCurrentBlock();
                break;
            case KEY_RIGHT:
                undrawCurrentBlock();
                if(!doesBlockCollide(gBlocks[gCurrentBlockNum][gCurrentBlockOrient],gCurrentBlockLeft+1,gCurrentBlockTop)) {
                    ++gCurrentBlockLeft;
                }
                drawCurrentBlock();
                break;
            case KEY_UP:
                undrawCurrentBlock();
                rotateCurrentBlock(true);
                if(doesBlockCollide(gBlocks[gCurrentBlockNum][gCurrentBlockOrient],gCurrentBlockLeft,gCurrentBlockTop)) {
                    rotateCurrentBlock(true);
                }
                drawCurrentBlock();
                break;
            case KEY_DOWN:
                gDropTimer = 0;
                break;

            case KEY_SPACE:
                // this drops the current block down as fast as possible
                while(!dropBlock()) {}
                gCurrentBlockNum = -1;
                break;

            case KEY_S:
                startClick();
                break;

            case KEY_P:
            case KEY_Q:
                pauseClick();
                break;
            } // switch
        } // else
    }

    function rotateCurrentBlock(bClockwise) {
        if(gCurrentBlockNum == -1) { return; }
        if(bClockwise) {
            ++gCurrentBlockOrient;
            if(gCurrentBlockOrient >= gBlocks[gCurrentBlockNum].length) {
                gCurrentBlockOrient = 0;
            }
        }
        else {
            --gCurrentBlockOrient;
            if(gCurrentBlockOrient < 0) {
                gCurrentBlockOrient = gBlocks[gCurrentBlockNum].length-1;
            }
        }
    }

    function init() {
        initializeButtons();
        initializeGameboard();
        
        restartGame();

        // now we're all ready, display everything
        // display all in one fell swoop
        displayAll();

        var svg = document.getElementById("svgsvg");
        if(svg) {
            svg.setAttribute("cursor", "default");
            svg.addEventListener("keydown", getKey, false);
        }

        setInterval("gameTick()", 10);
    }

    演示地址:http://www.codedread.com/yastgame.php


       收藏   分享  
    顶(0)
      




    ----------------------------------------------
    交流提高呀!

    svg技术交流: 
    http://greaterthanme.blog.hexun.com/list.aspx?
    tag=svg
    svg技术交流群:24785607
    svg文件共享邮箱:svgcn@126.com  
    password:svg.net.cn

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2006/4/13 15:55:00
     
     GoogleAdSense魔羯座2000-12-31
      
      
      等级:大一新生
      文章:1
      积分:50
      门派:无门无派
      院校:未填写
      注册:2007-01-01
    给Google AdSense发送一个短消息 把Google AdSense加入好友 查看Google AdSense的个人资料 搜索Google AdSense在『 SVG/GML/VRML/X3D/XAML 』的所有贴子 点击这里发送电邮给Google AdSense  访问Google AdSense的主页 引用回复这个贴子 回复这个贴子 查看Google AdSense的博客广告
    2025/7/20 0:35:29

    本主题贴数1,分页: [1]

    管理选项修改tag | 锁定 | 解锁 | 提升 | 删除 | 移动 | 固顶 | 总固顶 | 奖励 | 惩罚 | 发布公告
    W3C Contributing Supporter! W 3 C h i n a ( since 2003 ) 旗 下 站 点
    苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
    218.994ms