本篇主要讲解,如何利用原生的 JavaScript 来实现一个简单的拼图小游戏。

线上体验地址:拼图

一、游戏的基础逻辑

想用一门语言来开发游戏,必须先了解如何使用这门语言来实现一些基础逻辑,比如图像的绘制、交互的处理、定时器等。

1、图形绘制

图形绘制是一切的基础,这里使用 JavaScriptcanvas 上进行绘制。即先在 html 中创建 canvas 元素,然后在 JavaScript 中,通过 id 拿到这个元素,并且通过 canvas 拿到对应的上下文环境 context,为后续的绘图做好准备。

<canvas id="background" width="450px" height="450px"></canvas>
复制代码
var background = document.getElementById("background");
var context = background.getContext('2d');
复制代码

通过 contextdrawImage 方法可以绘制图片,这里进行了相应的封装:

注: 这里要等图片加载完毕后再进行绘制,即在 onload 中去调用 drawImage 方法,否则会绘制失败。

var drawImageItem = function(index, position) {var img = new Image();img.src = './image/dog_0' + String(index+1) + '.jpg';img.onload = () => {var rect = rectForPosition(position);context.drawImage(img, rect[0], rect[1], rect[2], rect[3]);}
}
复制代码

在绘制图片之后,我们还需要去动态刷新视图,否则 canvas 就只是一张静态的图片。如果是简单的图形刷新,只需在原来的位置重新绘制,进行覆盖即可。但有时候我们只需要将原来已存在的图形清除掉,而不需要绘制新图案。比如在拼图游戏中,将一个方块移动到另一个位置后,需要清空原来的位置。

通过 contextclearRect 方法可以达到清除的目的。以下是清除 canvas 的某个区域的代码:

var originRect = rectForPosition(origin);
context.clearRect(originRect[0], originRect[1], originRect[2], originRect[3]);
复制代码

2、事件处理

有了图形的绘制后,我们还需要处理玩家的输入事件,然后根据输入事件,来决定什么时候刷新视图。输入事件可以分为 3 种:在手机上有触屏事件;在 PC 上,有鼠标和键盘事件。

JavaScript 中对触屏和鼠标点击的监听是一样的,都是通过 canvasonclick 事件进行回调,具体如下:

// 屏幕点击
background.onclick = function(e) {
};
复制代码

我们可以通过 e.offsetXe.offsetY 来获取触控点在 canvas 中的位置。

注: canvas 的坐标原点在左上角,即左上角的坐标是 (0, 0)

键盘的按键点击则是通过 documentonkeyuponkeydown 等事件进行回调。onkeyup 是指按键的抬起事件,onkeydown 是指按键的按下事件。我们可以通过 keyCode 知道当前具体是哪一个按键,然后根据不同的按键去处理不同的逻辑,如下:

if (event.keyCode == '37') {  // 左// do something
} else if (event.keyCode == '38') { // 上// do something
} else if (event.keyCode == '39') { // 右// do something
} else if (event.keyCode == '40') { // 下// do something
}
复制代码

3、定时器

有时候,除了在玩家输入的时候需要去刷新视图,还需要每隔一段时间定时去刷新视图。比如在一个贪吃蛇游戏中,就需要每隔一段时间就去刷新蛇的位置。

这个时候我们就需要一个定时器,让它每隔一段时间去执行一段刷新视图的代码。我们通过 setInterval 方法来实现定时器功能:

setInterval("run()", 100);
复制代码

上面这段代码表示每隔 100 毫秒,去执行一次 run 方法。

二、拼图的基础逻辑

有了游戏的基础逻辑,下面来看一下如何实现拼图的逻辑。

1、生成随机序列

因为不是任意序列都可以通过平移的方式来还原,所以我们不能简单地生成一个随机序列。比如 1、0、2、3、4、5、6、7、8 这个序列,无论怎么平移,都不可能还原。

这里采取的做法是:预先设置了 4 个可还原的序列,先从这 4 个序列中随机选取一个,然后再对序列进行模拟平移若干步骤。以此来尽可能地保证初始序列的多样性,也保证了序列的可还原性。具体代码如下:

var setupRandomPosition = function() {var list1 = [4, 3, 2, 8, 0, 7, 5, 6, 1];var list2 = [2, 0, 5, 6, 8, 7, 3, 1, 4];var list3 = [3, 7, 2, 4, 1, 6, 8, 0, 5];var list4 = [3, 2, 4, 1, 7, 6, 5, 0, 8];var lists = [list1, list2, list3, list4];imageIndexForPosition = lists[parseInt(Math.random() * 4)];// 获取空位位置var emptyPosition = 0;for (var i = imageIndexForPosition.length - 1; i >= 0; i--) {if (imageIndexForPosition[i] == lastIndex()) {emptyPosition = i;break;}}background.emptyPosition = emptyPosition;// 随机移动次数var times = 10;while (times--) {// 获取随机数,决定空位哪个位置进行移动var direction = parseInt(Math.random() * 4);var target = -1;if (direction == 0) {target = topOfPosition(emptyPosition);  // 上} else if (direction == 1) {target = leftOfPosition(emptyPosition);  // 左 } else if (direction == 2) {target = rightOfPosition(emptyPosition);  // 右} else if (direction == 3) {target = bottomOfPosition(emptyPosition);  // 下}if (target < 0 || target > lastIndex()) {  // 位置不合法,继续下一次循环continue;}var result = moveImageIfCanAtPosition(target);if (result >= 0) { // 如果移动成功,更新空位的位置emptyPosition = target;}}
}
复制代码

2、判断是否可以移动方块

在保存顺序的时候,是用 0~8 这 9 个数字来保存,而空白的方块是数字 8 的位置。所以判断可以移动的唯一条件是,目标位置的值是否为 8。代码如下:

var isPositionEmpty = function(position) {if (position < 0 || position > lastIndex()) {return false;} if (imageIndexForPosition[position] == lastIndex()) {return true;} else {return false;}
}
复制代码

上面 lastIndex() 的值为 8。

3、实现方块移动

方块移动的实现很简单,先将旧位置的图形清除,然后在新的位置绘制。

var refreshImagePositions = function(origin, target) {var originRect = rectForPosition(origin);context.clearRect(originRect[0], originRect[1], originRect[2], originRect[3]);drawImageItem(imageIndexForPosition[target], target);
}
复制代码

4、检查是否完成

检查图案是否已经还原,只需要对数组进行一次遍历,看是否有序即可。

var checkIfFinish = function() {for (var index = 0; index < imageIndexForPosition.length; index++) {if (index != imageIndexForPosition[index]) {return false;}}return true;
}
复制代码

5、交互事件屏蔽

当图案还原之后,我们不希望玩家还能通过键盘或鼠标来移动方块,这个时候就需要对交互事件进行屏蔽。

只需要一个标志位就可以达到这个目的:

// 屏幕点击
background.onclick = function(e) {if (isFinish) {return;}// do something
};// 键盘按钮事件
document.onkeyup = function(event) {if (isFinish) {return;}// do something
}
复制代码

当图案还原之后,标志位 isFinish 会被置为 true,然后在屏幕点击和键盘按钮响应事件的开始处添加判断,如果已经结束,则不继续走方块移动的逻辑。

三、源码

请到 GitHub 上查看完整代码。

参考

JavaScript 教程

获取更佳的阅读体验,请访问原文地址 【Lyman's Blog】用 JavaScript 实现简单拼图游戏

用 JavaScript 实现简单拼图游戏相关推荐

  1. H5原生js简单拼图游戏

    H5原生js简单拼图游戏 演示地址 效果展示 源码 index.html puzzle.css puzzle.js 源码下载 演示地址 链接: 演示地址 效果展示 源码 index.html < ...

  2. php拼图游戏开发,原生javascript制作的拼图游戏实现方法详解

    本文实例讲述了原生javascript制作的拼图游戏实现方法.分享给大家供大家参考,具体如下: 实现方法 //1.让所有的li(在ul里)可以拖拽 //2.交换li的位置  计算背景图位置 //1.让 ...

  3. Qt实现简单拼图游戏

    文章目录 前言 演示图 1.ShowWidget.h 2.ShowWidget.cpp 3.MainWindow.h 4.MainWindow.cpp 前言 自己简单实现了下拼图功能.本来开始只是想显 ...

  4. Unity3d制作简单拼图游戏

    本文为原创,如需转载请注明原址:http://blog.csdn.net/cube454517408/article/details/7907247 最近一直在使用Unity,对它有了一些小的使用心得 ...

  5. 用flash制作简单拼图游戏

    简介: 可能有很多玩Flash的朋友都曾和我一样想自己动手制作一个拼图游戏,但是苦于不知道实现的方法或不了解ActionScript(以下简称AS)而心存遗憾.别急,今天盗匪就告诉你如何利用Flash ...

  6. VUE实现的简单拼图游戏

    写在前面 最近玩游戏的时候玩到游戏内置的拼图小游戏,突然唤起我对拼图游戏的热爱了,结果这内置游戏要花钱,在steam上找到的免费拼图游戏也不能自定义图片,想玩其他的图还要花钱.这让我很不爽,就索性自己 ...

  7. HTML 简单拼图游戏

    先不废话,请看演示. 公司要搞这么个微信活动,可现在没有前端开发,没办法,身为打杂总监只好临时顶下这个空缺了.先找了一些 JS 代码,试用了下都不太理想,好一点的写的又太复杂,改起来有难度,干脆撸起袖 ...

  8. JavaScript写一个拼图游戏

    拼图游戏的代码400行, 有点多了, 在线DEMO的地址是:打开: 因为使用canvas,所以某些浏览器是不支持的: you know: 为什么要用canvas(⊙o⊙)?  因为图片是一整张jpg或 ...

  9. Java 简单拼图游戏(实现音乐播放功能)

    此程序为用JAVA编写的拼图小游戏,可通过简单的图片移动实现拼图,并实现音乐播放功能.(此程序只完成简单功能的实现,大佬勿喷) 程序源码下载:点击下载程序源码 软件系统实现 拼图主体为一方形区域,位于 ...

最新文章

  1. SpringMVC传递JSON数据的方法
  2. 算法复习(7)有序二叉树
  3. 女生职场必读:步入30岁后的30句经典感言
  4. Crypto.com APP上线The Graph(GRT)
  5. B. DZY Loves Modification
  6. Discuz!论坛系统模板目录结构注释说明(以default模板为例)
  7. 面试高并发,凉了!!(全程高能,建议收藏)
  8. ofstream错误:error: variable ‘std::ofstream ofs’ has initializer but incomplete type
  9. SyntaxError: invalid character in identifier
  10. matlab小车运动轨迹增量式PID控制
  11. 价值7000万的商业模式,羊毛出在狗身上,猪来买单
  12. dijkstra标号法表格_dijkstra算法模板及其用法
  13. python向上取整_python向上取整
  14. ALK8266WIFI解决方案支持常见普通单片机实现WIFI高速传输和许多实用功能,实测速度超过M字节每秒
  15. 繁体批量转换工具:支持繁体字和简体本地化互转
  16. SQL数据库笛卡尔积、投影、选择、连接运算
  17. 用代码写一个表白biu小心心
  18. 汇编语言——用DOSBox的debug查看CPU和内存 用机器指令和汇编指令编程
  19. Linux下常用软件推荐列表
  20. 参考 | 给C盘 “搬家“

热门文章

  1. 电商平台-系统报表设计与架构
  2. SpaceX载人航天发射,宇航员手动操纵龙飞船进行测试!
  3. 编译原理——短语、简单短语、句柄
  4. linux设置中国时区,Linux更改中国时区
  5. bert论文解析——BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding
  6. Linux的文件类型分类
  7. 自动驾驶系统设计的那些底层软件开发中的重点解读
  8. iphone 重启桌面_如何强制iPhone重新启动/重启/重置?
  9. Linux 阻塞和非阻塞 IO简介
  10. 广告牌定时器怎么设置时间_定时开关怎么调时间?