Javascript 拼圖游戲,可以自定義圖片拼圖,可以設置無限關卡,拼圖成功后含動畫效果


基本就是拖拽功能的應用,其它鼠標事件綁定,距離的計算,動畫等,也有很多細節問題,

需要親自做了才知道, 支持IE系列,FIREFOX,chrome瀏覽器, IE6下可能有點卡。

過關卡的時候需要下載下一張圖片,如果網速慢則會暫時停止一下,稍等一會就可以接着下一關。

玩到最后一關就可以自定義圖片拼圖了,只需要輸入圖片的地址就可以了!

如果需要直接自定義圖片,則用谷歌瀏覽器或者FIREBUG把隱藏的Id  imgDiy 的層顯示出來

就可以了. 

DEMO演示:點擊試玩 

源代碼下載:點擊下載

IFREAME演示:

 就不解釋了,我源代碼里面的注釋寫得很清楚,有興趣的可以看一下源代碼,如下:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>JS</title>
    <meta name="keywords" content="拼圖游戲"/>
    <meta name="description" content="拼圖游戲"/>
    <style type="text/css">
        #vvg p {
            text-align: center;
            font-size: 14px;
            font-weight: bold;
        }

        #vvg ul {
            overflow: hidden;
            text-align: center;
        }

        #thumb li {
            list-style: none;
            float: left;
            display: inline;
            margin-left: 5px;
        }

        #gameCanvas {
            position: relative;
            padding: 0;
            margin: 0 auto;
        }

        #gameCanvas li {
            position: absolute;
            list-style: none;
            cursor: move;
        }

        #vvgBox {
            margin: 0 auto;
            overflow: hidden;
            position: relative;
        }

        #mask {
            position: absolute;
            z-index: 999;
            background: #fff;
            left: 0;
            top: 0;
        }

        #button {
            width: 133px;
            height: 133px;
            background-image: url('images/play.png');
            position: absolute;
            z-index: 1000;
            margin-left: -66px;
            left: 50%;
            margin-top: -66px;
            top: 50%;
        }

        #button:hover {
            background-position: -133px 0;
        }

        #textTip {
            font-size: 25px;
            font-weight: bold;
            color: #000;
            text-align: center;
            position: relative;
            top: -75%;
            z-index: 1000;
        }

        #step {
            margin-left: 5px;
            margin-right: 5px;
            color: red;
            font-size: 20px;
        }

        #imgDiy {
            text-align: center;
            display: none;
        }
    </style>
</head>
<body>
<div id="vvg">
    <p id="desTip">通過四個關卡后可以自定義圖片&nbsp;&nbsp;&nbsp;&nbsp;現在是第<span id="step">1</span>關</p>
    <p id="imgDiy">填入圖片地址:<input type="text" id="imgUrl"><input id="startDiy" type="button" value="開始"></p>
    <div id="vvgBox">
        <ul id="gameCanvas"></ul>
    </div>
</div>
<script type="text/javascript">
/*  by VVG 2012年6月1日
    E-MAIL:mysheller@163.com
    博客地址:http://www.cnblogs.com/NNUF/
*/
/*快捷函數*/
function getId(id) {
    return typeof id === "string" ? document.getElementById(id) : id
}

function setOpacity(node, level) {
    if (document.all) {
        node.style.filter = 'alpha(opacity=' + level + ')';
    } else {
        node.style.opacity = level / 100;
    }
}

//設置第幾關
var vvg = {};
vvg.step = 1;
/* 游戲 內容代碼 */
function makeGame(url) {
    var imgArray = [], imgArray_bak = [],
            dragging = null, draggingL, draggingT, dear, dearL, dearT, top, left, effectEnd,
            posArray = [], posArray_bak = [], canvas = getId('gameCanvas'), vvgBox = getId('vvgBox'), successTimer;
    // posx,posy 為鼠標相對於拖動對象的左上角距離, sLeft sTop 為拖動對象的初始位置
    var posx, posy, zindex = 0, isMouseMove;
    var imgWidth, imgHeight;
    var img = new Image();
    img.src = url;
    // 圖片加載完畢
    img.onload = function () {
        //獲取圖片的尺寸
        imgWidth = img.width;
        imgHeight = img.height;
        var myw = Math.floor(imgWidth / 4),
                myh = Math.floor(imgHeight / 4);
        vvgBox.style.width = imgWidth + 'px';
        vvgBox.style.height = imgHeight + 'px';
        canvas.style.width = imgWidth + 'px';
        canvas.style.height = imgHeight + 'px';
        //清空gameCanvas
        while (canvas.firstChild) {
            canvas.removeChild(canvas.firstChild);
        }
        // 文檔碎片
        var oFragment = document.createDocumentFragment();
        //循環生成方塊狀態的小圖,以背景的形式展現,生成16格,並添加到數組
        for (var i = 0; i < 16; i++) {
            var li = document.createElement('li');
            li.style.width = myw + 'px';
            li.style.height = myh + 'px';
            li.style.backgroundImage = 'url(' + url + ')';
            // 計算坐標
            if (i < 4) {//0,1,2,3 第一排
                top = 0;
                left = i * myw;
            } else if (i >= 4 && i < 8) {// 4,5,6,7 第二排
                top = myh;
                left = (i - 4) * myw;
            } else if (i >= 8 && i < 12) {// 8,9,10,11 第三排
                top = 2 * myh;
                left = (i - 8) * myw;
            } else if (i >= 12) { // 12,13,14,15 第四排
                top = 3 * myh;
                left = (i - 12) * myw;
            }
            // 記錄還未打亂次序的初始ID對應的每個id的正確位置,用於比較拼圖是否完成
            posArray.push([i, left, top]);
            // 賦值背景backgroundPosition 與 位置
            li.style.backgroundPosition = -left + 'px' + ' ' + (-top) + 'px';
            // 賦值ID為i, 用於檢查拼圖的位置
            li.id = i;
            // 對象是否在移動
            li.isMove = false;
            // 存儲到數組imgArray中
            imgArray.push(li);
            li.style.left = left + 'px';
            li.style.top = top + 'px';
            // 事件綁定
            li.onmousedown = function (event) {
                event = event || window.event;
                var target = event.target || event.srcElement;
                isMouseMove = false;
                dragging = target;
                //記錄拖動對象的初始位置
                draggingL = parseInt(dragging.style.left);
                draggingT = parseInt(dragging.style.top);
                posx = event.clientX - canvas.offsetLeft - dragging.offsetLeft;
                posy = event.clientY - canvas.offsetTop - dragging.offsetTop;
                zindex++;
                // 在移動的圖片就不綁定事件
                if (!dragging.isMove) {
                    document.onmousemove = function (event) {
                        event = event || window.event;
                        var myleft = event.clientX - canvas.offsetLeft - posx;
                        var mytop = event.clientY - canvas.offsetTop - posy;
                        if (myleft < 0)myleft = 0;
                        if (mytop < 0)mytop = 0;
                        if (myleft > canvas.offsetWidth - dragging.offsetWidth)myleft = canvas.offsetWidth - dragging.offsetWidth;
                        if (mytop > canvas.offsetHeight - dragging.offsetHeight)mytop = canvas.offsetHeight - dragging.offsetHeight;
                        dragging.style.left = myleft + 'px';
                        dragging.style.top = mytop + 'px';
                        dragging.style.zIndex = zindex;
                        // 設置拖動的元素的不透明度
                        setOpacity(dragging, 80);
                        // 獲取離拖動元素最近的元素
                        dear = checkMeet(dragging);
                        // 循環設置透明度為100....就是為了改變最近距離的透明度
                        for (var i = 0, n = imgArray_bak.length; i < n; i++) {
                            setOpacity(imgArray_bak[i], 100);
                        }
                        setOpacity(dear, 50);
                        dearL = parseInt(dear.style.left);
                        dearT = parseInt(dear.style.top);
                        isMouseMove = true;
                        return false;
                    };
                    document.onmouseup = function () {
                        document.onmousemove = null;
                        document.onmouseup = null;
                        // 只發生單擊事件鼠標沒有移動時不會設置透明度移動動畫操作
                        if (isMouseMove === true) {
                            dear.style.zIndex = zindex;
                            setOpacity(dragging, 100);
                            setOpacity(dear, 100);
                            startMove(dear, draggingL, draggingT, 10);
                            startMove(dragging, dearL, dearT, 10);
                        }
                        isMouseMove = false;
                        dragging = null;
                        return false;
                    };
                }
                return false;
            };
            oFragment.appendChild(li);
        }
        canvas.appendChild(oFragment);
        // 復制一份密碼到posArray_bak,用於檢查拼圖是否完成(id對應正確的位置時,則拼圖完成)
        imgArray_bak = imgArray.concat(); //只包含對象
        // posArray.push([i, left, top]);
        posArray_bak = posArray.concat(); //包含對象id以及未打亂對象的位置屬性
        play();
        // 打亂數組imgArray

    };
    // 隨機排列
    function rank() {
        while (imgArray.length > 0) {
            // 在數組的長度中獲取隨機值下標
            // 隨機獲取ID
            var ranLi = imgArray.splice(random(0, imgArray.length), 1);
            // 隨機獲取位置,並從原數組移除,返回移除項組成的數組
            var ranCss = posArray.splice(random(0, posArray.length), 1);
            // 賦值隨機位置
            startMove(ranLi[0], ranCss[0][1], ranCss[0][2], 10);
        }
    }

    // 返回隨機數函數
    function random(from, to) {
        return Math.floor(Math.random() * (to - from) + from);
    }

    // 檢測與誰相交,判斷對象的中心點的距離最近即相交
    function checkMeet(obj) {
        // 存儲與每個對象的最小距離的數組
        var disArray = [];
        //循環圖片對象列表,求距離並計入數組
        for (var i = 0, n = imgArray_bak.length; i < n; i++) {
            // 排除自身和正在移動的對象
            if (imgArray_bak[i] != obj && !imgArray_bak[i].isMove) {
                var item = getDistance(obj, imgArray_bak[i]);
                //數組只傳入一個值,后面的值與第一個值比較,如果比它小這替換這個值,剩下的就是最小的距離
                if (disArray.length == 0) {
                    disArray.push([imgArray_bak[i], item]);
                }
                if (item - 0 < disArray[0][1] - 0) {
                    disArray.splice(0, 1, [imgArray_bak[i], item]);
                }
            }
        }
        // 返回距離最小的對象
        return disArray[0][0];
    }

    // 求兩對象中心兩點之間的距離,傳入對象,利用勾股定理求值
    function getDistance(obj1, obj2) {
        var a = (obj1.offsetLeft + obj1.offsetWidth / 2) - (obj2.offsetLeft + obj2.offsetWidth / 2);
        var b = (obj1.offsetTop + obj1.offsetHeight / 2) - (obj2.offsetTop + obj2.offsetHeight / 2);
        return Math.ceil(Math.sqrt(a * a + b * b));
    }

    // 檢查拼圖是否完成
    function check() {
        for (var j = 0, n = posArray_bak.length; j < n; j++) {
            // posArray.push([i, left, top]);
            var loopLi = getId(posArray_bak[j][0] + ''); //加空轉換成字符串
            var loopLiLeft = parseInt(loopLi.style.left);
            var loopLiTop = parseInt(loopLi.style.top);
            if (loopLiLeft != posArray_bak[j][1]) return false;
            if (loopLiTop != posArray_bak[j][2]) return false;
        }
        return true;
    }

    // 設置移動
    function startMove(obj, x2, y2, time) {
        clearInterval(obj.timer);
        if (!obj.timer) {
            obj.timer = setInterval(function () {
                move(obj, x2, y2);
            }, time);
        }
    }

    // 移動效果
    function move(obj, x2, y2) {
        //判斷對象是否移動
        obj.isMove = true;
        var x1 = parseInt(obj.style.left), y1 = parseInt(obj.style.top),
                movex = (x2 > x1 ? Math.ceil : Math.floor)((x2 - x1) / 10),
                movey = (y2 > y1 ? Math.ceil : Math.floor)((y2 - y1) / 10);
        obj.style.left = (x1 + movex) + 'px';
        obj.style.top = (y1 + movey) + 'px';
        if (parseInt(obj.style.left) == x2 && parseInt(obj.style.top) == y2) {
            clearInterval(obj.timer);
            obj.isMove = false;
            obj.timer = null;
            // 通過拼圖檢查,並已經執行了拼圖成功后的效果,避免成功動畫也執行拼圖成功,產生循環
            if (!!check() && !effectEnd) {
                successTimer && clearTimeout(successTimer);
                successTimer = setTimeout(sucessEffect, 800);
            }
        }
    }

    // 拼圖成功后效果
    function sucessEffect() {
        var num = 0, cTimer;
        effect();
        function effect() {
            var copy2 = imgArray_bak.concat();
            var copy1 = posArray_bak.concat();
            // 打亂數組imgArray
            while (copy2.length > 0) {
                // 隨機獲取ID
                var ranLi = copy2.splice(random(0, copy2.length), 1);
                // 隨機獲取位置,並從原數組移除,返回移除項組成的數組
                var ranCss = copy1.splice(random(0, copy1.length), 1);
                startMove(ranLi[0], ranCss[0][1], ranCss[0][2], 10);
            }
            num++;
            if (num < 4) {
                setTimeout(effect, 800);
            } else {
                setTimeout(back, 800);
            }
        }

        function back() {
            var copy1 = posArray_bak.concat();
            while (copy1.length > 0) {
                var ranCss = copy1.splice(random(0, copy1.length), 1);
                startMove(getId(ranCss[0][0] + ''), ranCss[0][1], ranCss[0][2], 30);
                // 特效過后彈出蒙板
                cTimer && clearTimeout(cTimer);
                cTimer = setTimeout(tipNextStep, 1000);
            }
            effectEnd = true;
        }
    }

    function play() {
        var mask = document.createElement('div');
        mask.id = 'mask';
        mask.style.width = imgWidth + 'px';
        mask.style.height = imgHeight + 'px';
        setOpacity(mask, 80);
        var playBtn = document.createElement('div');
        playBtn.id = 'button';
        playBtn.onclick = function () {
            canvas.removeChild(mask);
            vvgBox.removeChild(playBtn);
            // 打亂排序
            rank();
        };
        canvas.appendChild(mask);
        vvgBox.appendChild(playBtn);
    }

    // 下一張圖按鈕
    function tipNextStep() {
        vvg.step += 1;
        var mask = document.createElement('div');
        mask.id = 'mask';
        mask.style.width = imgWidth + 'px';
        mask.style.height = imgHeight + 'px';
        setOpacity(mask, 80);
        var playBtn = document.createElement('div');
        playBtn.id = 'button';
        if (vvg.step < 5) {
            playBtn.onclick = function () {
                canvas.removeChild(mask);
                vvgBox.removeChild(playBtn);
                vvgBox.removeChild(textTip);
                var step = getId('step');
                step.innerHTML = vvg.step;
                makeGame('images/0' + vvg.step + '.jpg');
            }
        } else {
            playBtn.onclick = function () {
                while (canvas.firstChild) {
                    canvas.removeChild(canvas.firstChild);
                }
                var btn = getId('button');
                btn.parentNode.removeChild(btn);
                var tip = getId('textTip');
                tip.innerHTML = '';
                var desTip = getId('desTip');
                desTip.innerHTML = '現在你可以自定義圖片了,請在下面的文本框中輸入圖片的地址:';
                var imgDiy = getId('imgDiy');
                var startDiy = getId('startDiy');
                var imgUrl = getId('imgUrl');
                imgDiy.style.display = 'block';
                startDiy.onclick = function () {
                    if (imgUrl.value == '') {
                        alert('請填入圖片地址');
                    } else {
                        makeGame(imgUrl.value);
                    }
                }
            }
        }


        var textTip = document.createElement('div');
        textTip.id = 'textTip';
        textTip.innerHTML = "點擊開始第" + vvg.step + "關";
        canvas.appendChild(mask);
        vvgBox.appendChild(playBtn);
        vvgBox.appendChild(textTip);
    }
}

// 默認播放第一關
makeGame('images/01.jpg');


</script>
</body>
</html>

 轉載請注明博客地址:http://www.cnblogs.com/NNUF/archive/2012/06/01/2531436.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM