65.9K
CodeProject 正在变化。 阅读更多。
Home

图像拼图:一个 HTML 游戏

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.89/5 (89投票s)

2014 年 8 月 28 日

CPOL

6分钟阅读

viewsIcon

250338

downloadIcon

10521

一个 HTML 2D 游戏,用于描述 HTML/CSS 和 JavaScript 中的一些基本游戏开发技巧。

引言

本文档面向希望以简单方式开始 Web 游戏开发的初学者,而无需使用任何重型工具。本文档提供了使用 HTML/CSS 和 JavaScript 开始 2D 游戏开发的简化步骤。在这里,我将展示如何创建一个图片拼图游戏,您可以在其中拖放图片碎片进行交换和重新排列,以形成完整的图片。现在,我们在 GitHub 上也提供了同一游戏的纯 JavaScript 版本。

您可以在线玩游戏,在此处

规则

游戏规则很简单。您只需要拖放打碎的图片碎片进行交换。您需要以正确的方式交换它们,使其形成正确的图像。拖放图片碎片所花费的步数将被计算。因此,您可能希望思考并尝试以最少的可能步数完成。右侧为您提供了正确的图像作为参考。

游戏的屏幕看起来像这样

Image Puzzle

Image Puzzle: Solved

关于代码

为了理解它,我们可以将代码分为三个部分:HTML、CSS 和 JavaScript。HTML 部分包含形成游戏布局的简单标签。CSS 提供了一些响应式设计,JavaScript 部分包含游戏的主要逻辑。游戏的一些重要步骤如下:

打碎图片

为了使图片看起来像被打碎成 nxn 个不同的部分,其中 n 是每边的部分数,nxnli 元素已在 ul 中使用。每个 li 的 display 属性已设置为 inline-block,以便它显示为网格。每个 li 的背景图像仅设置为显示图片的 1/(nxn)th 部分,并且背景图像的位置已相应设置。data-value 属性已分配给每个 li 以识别碎片的索引。

相同的代码看起来像这样

    setImage: function (images, gridSize) {
        console.log(gridSize);
        gridSize = gridSize || 4; // If gridSize is null or not passed, default it as 4.
        console.log(gridSize);
        var percentage = 100 / (gridSize - 1);
        var image = images[Math.floor(Math.random() * images.length)];
        $('#imgTitle').html(image.title);
        $('#actualImage').attr('src', image.src);
        $('#sortable').empty();
        for (var i = 0; i < gridSize * gridSize; i++) {
            var xpos = (percentage * (i % gridSize)) + '%';
            var ypos = (percentage * Math.floor(i / gridSize)) + '%';
            var li = $('<li class="item" data-value="' + (i) + '"></li>').css({
                'background-image': 'url(' + image.src + ')',
                'background-size': (gridSize * 100) + '%',
                'background-position': xpos + ' ' + ypos,
                'width': 400 / gridSize,
                'height': 400 / gridSize
            });
            $('#sortable').append(li);
        }
        $('#sortable').randomize();
    }

在这里,您可以看到打碎的效果是通过简单的 background-imagebackground-position 样式实现的。设置好打碎的图片后,按照正确的顺序,使用 randomize 方法来随机化碎片。在游戏中,用户必须重新排列碎片以形成完整的图片。

gridSize 表示需要将图片每边(水平和垂直)打碎多少部分。硬编码值 400 是框的大小。请注意,您可能希望摆脱这个硬编码值。我将在下一个更新中用一个变量更新它。基于 gridSize,我将拼图级别分为三个部分:简单、中等和困难。简单为 3x3 网格,中等为 4x4,困难为 5x5。您可以通过更改相应单选按钮的值以不同的方式实现。

打碎碎片的随机化

如上一个代码块的最后一行所示,设置好图片的打碎部分后,使用 randomize 方法来随机化打碎的碎片。为此,创建了一个小型通用随机化函数来随机化任何 jquery 元素集合。

randomize 方法的实现如下

$.fn.randomize = function (selector) {
    var $elems = selector ? $(this).find(selector) : $(this).children(),
        $parents = $elems.parent();

    $parents.each(function () {
        $(this).children(selector).sort(function () {
            return Math.round(Math.random()) - 0.5;
        }).remove().appendTo(this);
    });
    return this;
}; 

在这里,我们只是遍历给定选择器的每个子元素,并根据随机数更改其位置。随机数应该在 0 和集合中的元素数量之间。

碎片的拖放

为了使每个打碎的碎片都可以拖动,我们使用了 jquery draggable。请确保您的页面中包含 jquery-ui.js 以实现 draggable/droppable 功能。

enableSwapping: function (elem) {
        $(elem).draggable({
            snap: '#droppable',
            snapMode: 'outer',
            revert: "invalid",
            helper: "clone"
        });
        $(elem).droppable({
            drop: function (event, ui) {
                var $dragElem = $(ui.draggable).clone().replaceAll(this);
                $(this).replaceAll(ui.draggable);

                currentList = $('#sortable > li').map(function (i, el) { 
                    return $(el).attr('data-value'); });
                if (isSorted(currentList))
                    $('#actualImageBox').empty().html($('#gameOver').html());

                imagePuzzle.enableSwapping(this);
                imagePuzzle.enableSwapping($dragElem);
            }
        });
    }   

如上面的代码片段所示,在每次放置后,都会调用 isSorted 来检查碎片是否已排序。每个碎片的排序是根据包含 li 元素的 data-value 属性来检查的。如果碎片已排序,则表示图片已完成。

设置样式

使用了非常少的 CSS 来使其易于理解。使用的 CSS 使页面具有响应性,您也可以在平板电脑或手机上玩游戏。没有使用 CSS 的第三方库,以便您可以轻松理解原生的 CSS 样式。

计算步数

计算任何游戏中的步数或用户操作是最常见的。在这里,它也通过简单的步骤实现。每次放置后,它会检查图片是否形成。如果是,游戏结束;如果不是,则将 stepCount 变量加 1。然后,使用 jquery 在 UI 中更新 stepCount

定时器

计时器也是大多数游戏的重要组成部分。根据读者的反馈,实现了一个基本的计时器来检查完成拼图所需的时间(秒)。计时器在游戏开始时启动,并每秒调用 tick 方法来更新计时器。Tick 方法从 start 方法中调用一次,然后通过 JavaScript SetTimeout 递归地每秒调用自身,并使用 JQuery 在 UI 中更新已用时间。当图片完成时,即游戏结束时,将计算最终耗时并使用 JQuery 在输出中显示。

以下是 timer 方法的实现。
   tick: function () {
        var now = new Date().getTime();
        var elapsedTime = parseInt((now - imagePuzzle.startTime) / 1000, 10);
        $('#timerPanel').text(elapsedTime);
        timerFunction = setTimeout(imagePuzzle.tick, 1000);
    }  

请注意,getTime() 方法给出自 01/01/1970 以来经过的毫秒数。如果您能建议一种在 JavaScript 中计算两个 DateTime 之间时间的更好方法,我将非常欢迎。我不想依赖 setTimeout() 中的 1000 毫秒间隔来增加到 1 秒。

关卡

根据用户的反馈,游戏中添加了 3 种难度级别。

  1. 简单
  2. 媒体
  3. 困难

在我们的示例中,选择简单将拼图设置为 3x3 矩阵,中等设置为 4x4 矩阵,困难设置为 5x5 矩阵。

浏览器兼容性

为了简单起见,我避免使用 HTML 5 或 CSS 3,以便它可以在大多数浏览器中工作。由于使用了最新的 JavaScript 代码,此游戏可能无法在 IE11 及更早的旧浏览器中工作。如果您也希望在旧版本浏览器中使用此游戏,您可以简单地将脚本引用替换为旧版本的 JQuery(1.9 或更早版本)。最新的 JQuery 版本不支持旧浏览器。

附带的示例代码应该可以在大多数最新浏览器中运行。我在 IE 11 和 Google Chrome 中测试过。

未来考量

好了,这是一篇面向初学者的文章,他们希望以简单的方式开始游戏开发。未来,我将实现并演示声音效果和一些动画,使其更具动态性。您也可以考虑实现计时器和完成图片所花费的时间。现在,请享受玩游戏。欢迎提出任何改进游戏的建议。

历史

  • 2014 年 8 月 29 日:发布第一个版本
  • 2015 年 2 月 8 日:更新:根据用户的反馈,添加了基于打碎部分数量的难度级别。
  • 2017 年 3 月 12 日:添加了 GitHub 项目和其他小更新
  • 2019 年 5 月 13 日:添加了纯 JavaScript 版本 GitHub 链接
© . All rights reserved.