• 基于HTML5实现五彩连珠小游戏


    今天给大家分享一款基于HTML5实现五彩连珠小游戏。这款游戏的规则:点击彩球移动到期望的位置,每移动一次,画面将随机出现3个新的彩球;当同一颜色的彩球连成5个一行或一列或一斜线时,这5个彩球同时消失,游戏得分10分。当画面上每个方格都被彩球占满时,游戏结束。

    在线预览   源码下载

    实现的代码。

    html代码:

     <canvas id="canvas" height="400" width="600" style="background: #333;">
        </canvas>
        <br />
        <p style=" 1000px; font-size: 14px; line-height: 24px; margin: 0 auto; text-align: left">
            游戏规则:<br>
            点击彩球移动到期望的位置,每移动一次,画面将随机出现3个新的彩球;当同一颜色的彩球连成5个一行或一列或一斜线时,这5个彩球同时消失,游戏得分10分。当画面上每个方格都被彩球占满时,游戏结束。</p>
        <br />
        <a href="index.html" style="font-size: 16px;">再玩一次</a>

    js代码:

    var game = {
                canvas: document.getElementById("canvas"),
                ctx: document.getElementById("canvas").getContext("2d"),
                cellCount: 9,  //九宫格
                cellWidth: 30,  //方格大小
                lineCount: 5,
                mode: 7,
                actions: {},
                play: function (name, action, interval) {
                    var me = this;
                    this.actions[name] = setInterval(function () {
                        action();
                        me.draw();
                    }, interval || 50);
                },
                stop: function (name) {
                    clearInterval(this.actions[name]);
                    this.draw();
                },
                colors: ["red", "#039518", "#ff00dc", "#ff6a00", "gray", "#0094ff", "#d2ce00"],
                start: function () {
                    this.map.init();
                    this.ready.init();
                    this.draw();
                    this.canvas.onclick = this.onclick;
                },
                over: function () {
                    alert("GAME OVER");
                    this.onclick = function () {
                        return false;
                    };
                },
                draw: function () {
                    this.ctx.clearRect(0, 0, 400, 600);
                    this.ctx.save();
                    this.map.draw();
                    this.ready.draw();
                    this.score.draw();
                    this.ctx.restore();
                },
                clicked: null,
                isMoving: function () {
                    return this.ready.isMoving || this.map.isMoving;
                },
                onclick: function (e) {
                    if (game.isMoving()) {
                        return;
                    }
                    var px = (e.offsetX || (e.clientX - game.canvas.offsetLeft)) - game.map.startX;
                    var py = (e.offsetY || (e.clientY - game.canvas.offsetTop)) - game.map.startY;
                    if (px < 0 || py < 0 || px > game.map.width || py > game.map.height) {
                        return;
                    }
                    var x = parseInt(px / game.cellWidth);
                    var y = parseInt(py / game.cellWidth);
                    var clicked = game.clicked;
                    var bubble = game.map.getBubble(x, y);
                    if (bubble.color) {
                        if (clicked) {
                            //同一个泡不做反映
                            if (clicked.x == x && clicked.y == y) {
                                return;
                            }
                            clicked.stop();
                        }
                        clicked = game.clicked = bubble;
                        bubble.play();
                    }
                    else {
                        if (clicked) {
                            clicked.stop();
                            //移动clicked
                            game.map.move(clicked, bubble);
                        }
                    }
                    //console.log("x:" + x + " y:" + y);
                },
                getRandom: function (max) {
                    return parseInt(Math.random() * 1000000 % (max));
                },
            };
            game.score = {
                basic: 0,
                operate: 0,
                star1: 0,
                star2: 0,
                boom: 0,
                draw: function () {
                    var startX = game.cellWidth * 10 + game.map.startX;
                    var startY = game.map.startY;
                    var ctx = game.ctx;
                    ctx.save();
                    ctx.translate(startX, startY);
                    ctx.clearRect(0, 0, 150, 400);
                    ctx.strokeStyle = "#456";
                    //ctx.strokeRect(0, 0, 150, 200);
                    ctx.font = "24px 微软雅黑";
                    ctx.fillStyle = "#fefefe";
                    ctx.fillText("得分:" + (this.basic * 5 + this.star1 * 8 + this.star2 * 10 + this.boom * 20), 0, 30);
                    ctx.stroke();
                    ctx.restore();
                },
                addScore: function (length) {
                    switch (length) {
                        case 5:
                            this.basic++;
                            break;
                        case 6:
                            this.star1++;
                            break;
                        case 7:
                            this.star2++;
                            break;
                        default:
                            this.boom++;
                            break;
                    }
                    this.draw();
                },
            };
            game.ready = {
                startX: 41.5,
                startY: 21.5,
                 game.cellWidth * 3,
                height: game.cellWidth,
                bubbles: [],
                init: function () {
                    this.genrate();
                    var me = this;
                    me.flyin();
                },
                genrate: function () {
                    for (var i = 0; i < 3; i++) {
                        var color = game.colors[game.getRandom(game.mode)];
                        this.bubbles.push(new Bubble(i, 0, color));
                    }
                    //console.log(this.bubbles);
                },
                draw: function () {
                    var ctx = game.ctx;
                    ctx.save();
                    ctx.translate(this.startX, this.startY);
                    ctx.beginPath();
                    ctx.strokeStyle = "#555";
                    ctx.strokeRect(0, 0, this.width, this.height);
                    ctx.stroke();
                    //绘制准备的泡
                    this.bubbles.forEach(function (bubble) {
                        bubble.draw();
                    });
    
                    ctx.restore();
                },
                isMoving: false,
                flyin: function () {
                    var emptys = game.map.getEmptyBubbles();
                    if (emptys.length < 3) {
                        //GAME OVER
                        game.over();
                        return;
                    }
                    var me = this;
                    var status = [0, 0, 0];
                    var times = 1;
                    game.play("flyin", function () {
                        if (status[0] && status[1] && status[2]) {
                            game.stop("flyin");
                            me.isMoving = false;
                            status = [0, 0, 0];
                            me.bubbles = [];
                            me.genrate();
                            return;
                        }
                        me.isMoving = true;
                        for (var i = 0; i < me.bubbles.length; i++) {
                            if (status[i]) {
                                continue;
                            }
                            var target = emptys[i];
                            var x2 = target.px + game.map.startX - me.startX;
                            var y2 = target.py + game.map.startY - me.startY;
                            var current = me.bubbles[i];
                            var step = Math.abs(x2 - current.px)/10 || Math.abs(y2 - current.y)/10;
                            if (current.px < x2) {
                                current.py = ((y2 - current.py) / (x2 - current.px)) * step + current.py;
                                current.px += step;
                                if (current.px > x2) {
                                    current.px = x2;
                                }
                            }
                            else if (current.px > x2) {
                                current.py = ((y2 - current.py) / (current.px - x2)) * step + current.py;
                                current.px -= step;
                                if (current.px < x2) {
                                    current.px = x2;
                                }
                            }
                            else {
                                current.py += step;
                            }
                            if (current.py > y2) {
                                current.py = y2;
                            }
                            if (parseInt(current.px+0.1) == x2 && parseInt(current.py+0.1) == y2) {
                                status[i] = 1;
                                current.x = target.x;
                                current.y = target.y;
                                game.map.addBubble(current);
                                game.map.clearLine(current.x, current.y, current.color, false);
                            }
                        }
                    }, 10);
    
                }
            };
            game.map = {
                startX: 40.5,  //棋盘X坐标
                startY: 60.5,  //棋盘Y坐标
                 game.cellCount * game.cellWidth,
                height: game.cellCount * game.cellWidth,
                bubbles: [],
                init: function () {
                    for (var i = 0; i < game.cellCount; i++) {
                        var row = [];
                        for (var j = 0; j < game.cellCount; j++) {
                            row.push(new Bubble(j, i, null));
                        }
                        this.bubbles.push(row);
                    }
                },
                clearLine: function (x1, y1, color, isClick) {
                    if (this.isEmpty(x1, y1)) {
                        if (isClick) game.ready.flyin();
                        return;
                    };
                    //给定一个坐标,看是否有满足的line可以被消除
                    //4根线 一  | / 
                    //横线
                    var current = this.getBubble(x1, y1);
                    if (!current.color) {
                        console.log(current);
                    }
                    var arr1, arr2, arr3, arr4;
                    arr1 = this.bubbles[y1];
                    arr2 = [];
                    for (var y = 0; y < game.cellCount; y++)
                        arr2.push(this.getBubble(x1, y));
                    arr3 = [current];
                    arr4 = [current];
                    for (var i = 1; i < game.cellCount ; i++) {
                        if (x1 - i >= 0 && y1 - i >= 0)
                            arr3.unshift(this.getBubble(x1 - i, y1 - i));
                        if (x1 + i < game.cellCount && y1 + i < game.cellCount)
                            arr3.push(this.getBubble(x1 + i, y1 + i));
    
                        if (x1 - i >= 0 && y1 + i < game.cellCount)
                            arr4.push(this.getBubble(x1 - i, y1 + i));
                        if (x1 + i < game.cellCount && y1 - i >= 0)
                            arr4.unshift(this.getBubble(x1 + i, y1 - i));
                    }
                    var line1 = getLine(arr1);
                    var line2 = getLine(arr2);
                    var line3 = getLine(arr3);
                    var line4 = getLine(arr4);
                    var line = line1.concat(line2).concat(line3).concat(line4);
                    if (line.length < 5) {
                        if (isClick) game.ready.flyin();
                        return;
                    }
                    else {
                        var me = this;
                        var i = 0;
                        game.play("clearline", function () {
                            if (i == line.length) {
                                game.score.addScore(line.length);
                                game.stop("clearline");
                                me.isMoving = false;
                                //game.ready.flyin();
                                return;
                            }
                            me.isMoving = true;
                            var p = line[i];
                            me.setBubble(p.x, p.y, null);
                            i++;
                        }, 100);
                    }
                    function getLine(bubbles) {
    
                        var line = [];
                        for (var i = 0; i < bubbles.length; i++) {
                            var b = bubbles[i];
                            if (b.color == color) {
                                line.push({ "x": b.x, "y": b.y });
                            }
                            else {
                                if (line.length < 5)
                                    line = [];
                                else
                                    return line;
                            }
                        }
                        if (line.length < 5)
                            return [];
                        return line;
                    }
                },
                draw: function () {
                    var ctx = game.ctx;
                    ctx.save();
                    ctx.translate(this.startX, this.startY);
                    ctx.beginPath();
                    for (var i = 0; i <= game.cellCount; i++) {
                        var p1 = i * game.cellWidth;;
                        ctx.moveTo(p1, 0);
                        ctx.lineTo(p1, this.height);
    
                        var p2 = i * game.cellWidth;
                        ctx.moveTo(0, p2);
                        ctx.lineTo(this.width, p2);
                    }
                    ctx.strokeStyle = "#555";
                    ctx.stroke();
                    //绘制子元素(所有在棋盘上的泡)
                    this.bubbles.forEach(function (row) {
                        row.forEach(function (bubble) {
                            bubble.draw();
                        });
                    });
                    ctx.restore();
                },
                isMoving: false,
                move: function (bubble, target) {
                    var path = this.search(bubble.x, bubble.y, target.x, target.y);
                    if (!path) {
                        //显示不能移动s
                        //alert("过不去");
                        return;
                    }
                    //map开始播放当前泡的移动效果
                    //两种实现方式,1、map按路径染色,最后达到目的地 2、map生成一个临时的bubble负责展示,到目的地后移除
                    //console.log(path);
                    var me = this;
                    var name = "move_" + bubble.x + "_" + bubble.y;
                    var i = path.length - 1;
                    var color = bubble.color;
                    game.play(name, function () {
                        if (i < 0) {
                            game.stop(name);
                            game.clicked = null;
                            me.isMoving = false;
                            me.clearLine(target.x, target.y, color, true);
                            return;
                        }
                        me.isMoving = true;
                        path.forEach(function (cell) {
                            me.setBubble(cell.x, cell.y, null);
                        });
                        var currentCell = path[i];
                        me.setBubble(currentCell.x, currentCell.y, color);
                        i--;
                    }, 50);
                },
                search: function (x1, y1, x2, y2) {
                    var history = [];
                    var goalCell = null;
                    var me = this;
                    getCell(x1, y1, null);
                    if (goalCell) {
                        var path = [];
    
                        var cell = goalCell;
                        while (cell) {
                            path.push({ "x": cell.x, "y": cell.y });
                            cell = cell.parent;
                        }
                        return path;
                    }
                    return null;
                    function getCell(x, y, parent) {
                        if (x >= me.bubbles.length || y >= me.bubbles.length)
                            return;
                        if (x != x1 && y != y2 && !me.isEmpty(x, y))
                            return;
    
                        for (var i = 0; i < history.length; i++) {
                            if (history[i].x == x && history[i].y == y)
                                return;
                        }
                        var cell = { "x": x, "y": y, child: [], "parent": parent };
                        history.push(cell);
    
                        if (cell.x == x2 && cell.y == y2) {
                            goalCell = cell;
                            return cell;
                        }
                        var child = [];
                        var left, top, right, buttom;
                        //最短路径的粗略判断就是首选目标位置的大致方向
                        if (x - 1 >= 0 && me.isEmpty(x - 1, y))
                            child.push({ "x": x - 1, "y": y });
                        if (x + 1 < me.bubbles.length && me.isEmpty(x + 1, y))
                            child.push({ "x": x + 1, "y": y });
                        if (y + 1 < me.bubbles.length && me.isEmpty(x, y + 1))
                            child.push({ "x": x, "y": y + 1 });
                        if (y - 1 >= 0 && me.isEmpty(x, y - 1))
                            child.push({ "x": x, "y": y - 1 });
                        var distance = [];
                        for(var i=0;i<child.length;i++){
                            var c = child[i];
                            if(c){
                                distance.push({"i":i,"d":Math.abs(x2 - c.x) + Math.abs(y2 - c.y)});
                            }else{
                                distance.push({"i":i,"d":-1});
                            }
                        };
                        distance.sort(function (a, b) { return a.d - b.d });
                        for (var i = 0; i < child.length; i++) {
                            var d = distance[i];
                            var c = child[d.i];
                            if (c) cell.child.push(getCell(c.x, c.y, cell));
                        }
                        return cell;
                    }
                },
                getEmptyBubbles: function () {
                    var empties = [];
                    this.bubbles.forEach(function (row) {
                        row.forEach(function (bubble) {
                            if (!bubble.color) {
                                empties.push(new Bubble(bubble.x, bubble.y));
                            }
                        });
                    });
                    if (empties.length <= 3) {
                        return [];
                    }
                    var result = [];
                    var useds = [];
                    for (var i = 0; i < empties.length; i++) {
                        if (result.length == 3) {
                            break;
                        }
                        var isUsed = false;
                        var ra = game.getRandom(empties.length);
                        for (var m = 0; m < useds.length; m++) {
                            isUsed = ra === useds[m];
                            if (isUsed) break;
                        }
                        if (!isUsed) {
                            result.push(empties[ra]);
                            useds.push(ra);
                        }
                    }
                    //console.log(useds);
                    return result;
                },
                addBubble: function (bubble) {
                    var thisBubble = this.getBubble(bubble.x, bubble.y);
                    thisBubble.color = bubble.color;
                },
                setBubble: function (x, y, color) {
                    this.getBubble(x, y).color = color;
                },
                getBubble: function (x, y) {
                    if (x < 0 || y < 0 || x > game.cellCount || y > game.cellCount) return null;
                    return this.bubbles[y][x];
                },
                isEmpty: function (x, y) {
                    var bubble = this.getBubble(x, y);
                    return !bubble.color;
                },
            };
            var Cell = function (x, y) {
                this.x = x;
                this.y = y;
            }
            var Bubble = function (x, y, color) {
                this.x = x;
                this.y = y;
                this.px = game.cellWidth * (this.x + 1) - game.cellWidth / 2;
                this.py = game.cellWidth * (this.y + 1) - game.cellWidth / 2;
                this.color = color;
                this.light = 10;
            };
            Bubble.prototype.draw = function () {
                if (!this.color) {
                    return;
                }
                var ctx = game.ctx;
                ctx.beginPath();
                //console.log("x:" + px + "y:" + py);
                var gradient = ctx.createRadialGradient(this.px - 5, this.py - 5, 0, this.px, this.py, this.light);
                gradient.addColorStop(0, "white");
                gradient.addColorStop(1, this.color);
                ctx.arc(this.px, this.py, 11, 0, Math.PI * 2);
                ctx.strokeStyle = this.color;
                ctx.fillStyle = gradient;
                ctx.fill();
                ctx.stroke();
            };
            Bubble.prototype.play = function () {
                var me = this;
                var isUp = true;
                game.play("light_" + this.x + "_" + this.y, function () {
                    if (isUp) {
                        me.light += 3;
                    }
    
                    if (!isUp) {
                        me.light -= 3;
                    }
                    if (me.light >= 30) {
                        isUp = false;
                    }
                    if (me.light <= 10) {
                        isUp = true;
                    }
                }, 50);
            };
            Bubble.prototype.stop = function () {
                //this.light = 10;
                var me = this;
                game.stop("light_" + this.x + "_" + this.y);
                game.play("restore_" + this.x + "_" + this.y, function () {
                    if (me.light > 10) {
                        me.light--;
                    }
                    else {
                        me.light = 10;
                        game.stop("restore_" + me.x + "_" + me.y);
                    }
                }, 50);
            };
            game.start();

    via:http://www.w2bc.com/Article/17647

  • 相关阅读:
    桥接,NAT,Host Only的区别
    PHP并发IO编程之路
    Git SSH Key 生成步骤
    composer安装学习
    db file sequential read等待事件的一点研究
    多个hints 怎么写?
    再次遭遇笛卡尔积
    pl/sql 在一个程序块里打印日志输出到表格
    pl/sql 程序块里打印问题
    利用ordered hints优化SQL
  • 原文地址:https://www.cnblogs.com/liaohuolin/p/4235216.html
Copyright © 2020-2023  润新知