利用原生的JavaScript实现简单拼图游戏


Posted in Javascript onNovember 18, 2018

前言

本篇主要讲解,如何利用原生的 JavaScript

来实现一个简单的拼图小游戏。

利用原生的JavaScript实现简单拼图游戏

一、游戏的基础逻辑

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

1、图形绘制

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

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

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

注:这里要等图片加载完毕后再进行绘制,即在 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 就只是一张静态的图片。如果是简单的图形刷新,只需在原来的位置重新绘制,进行覆盖即可。但有时候我们只需要将原来已存在的图形清除掉,而不需要绘制新图案。比如在拼图游戏中,将一个方块移动到另一个位置后,需要清空原来的位置。

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

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

2、事件处理

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

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

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

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

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

键盘的按键点击则是通过 document 的 onkeyup 、 onkeydown 等事件进行回调。 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 ,然后在屏幕点击和键盘按钮响应事件的开始处添加判断,如果已经结束,则不继续走方块移动的逻辑。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
你可能不再需要JQUERY
Mar 09 Javascript
麻雀虽小五脏俱全 Dojo自定义控件应用
Sep 04 Javascript
JavaScript游戏之优化篇
Nov 08 Javascript
浅谈setTimeout 与 setInterval
Jun 23 Javascript
jQuery插件简单实现方法
Jul 18 Javascript
神奇!js+CSS+DIV实现文字颜色渐变效果
Mar 16 Javascript
使用jQuery中的wrap()函数操作HTML元素的教程
May 24 Javascript
js date 格式化
Feb 15 Javascript
微信小程序 生命周期函数详解
May 24 Javascript
Vue项目从webpack3.x升级webpack4不完全指南
Apr 28 Javascript
解决layui的使用以及针对select、radio等表单组件不显示的问题
Sep 05 Javascript
JavaScript键盘事件响应顺序详解
Sep 30 Javascript
Javascript实现动态时钟效果
Nov 17 #Javascript
使用Javascript简单计算器
Nov 17 #Javascript
JS实现图片切换效果
Nov 17 #Javascript
js实现导航跟随效果
Nov 17 #Javascript
JavaScript实现新年倒计时效果
Nov 17 #Javascript
JS实现倒计时图文效果
Nov 17 #Javascript
javaScript实现游戏倒计时功能
Nov 17 #Javascript
You might like
火车头discuz6.1 完美采集的php接口文件
2009/09/13 PHP
php获取CSS文件中图片地址并下载到本地的方法
2014/12/02 PHP
php微信公众号开发之欢迎老朋友
2018/10/20 PHP
解决laravel 表单提交-POST 异常的问题
2019/10/15 PHP
2020最新版 PhpStudy V8.1版本下载安装使用详解
2020/10/30 PHP
ExtJS的FieldSet的column列布局
2009/11/20 Javascript
Jquery拖拽并简单保存的实现代码
2010/11/28 Javascript
javascript 二进制运算技巧解析
2012/11/27 Javascript
将两个div左右并列显示并实现点击标题切换内容
2013/10/22 Javascript
javascript间隔定时器(延时定时器)学习 间隔调用和延时调用
2014/01/13 Javascript
jQuery多媒体插件jQuery Media Plugin使用详解
2014/12/19 Javascript
BootStrap selectpicker
2016/06/20 Javascript
html+js+highcharts绘制圆饼图表的简单实例
2016/08/04 Javascript
Vue数据驱动模拟实现2
2017/01/11 Javascript
JS实现中国公民身份证号码有效性验证
2017/02/20 Javascript
node.js平台下利用cookie实现记住密码登陆(Express+Ejs+Mysql)
2017/04/26 Javascript
jQuery实现radio第一次点击选中第二次点击取消功能
2017/05/15 jQuery
JS中去掉array中重复元素的方法
2017/05/26 Javascript
微信小程序 swiper组件构建轮播图的实例
2017/09/20 Javascript
python实现图片批量剪切示例
2014/03/25 Python
python自动化测试之连接几组测试包实例
2014/09/28 Python
python操作CouchDB的方法
2014/10/08 Python
Python实现Linux的find命令实例分享
2017/06/04 Python
python进行文件对比的方法
2018/12/24 Python
python 图像平移和旋转的实例
2019/01/10 Python
用Python+OpenCV对比图像质量的几种方法
2019/07/15 Python
通过代码实例解析Pytest运行流程
2020/08/20 Python
HTML5 预加载让页面得以快速呈现
2013/08/13 HTML / CSS
微信端html5页面调用分享接口示例
2018/03/14 HTML / CSS
自主实习接收函
2014/01/13 职场文书
党员公开承诺书范文
2014/03/25 职场文书
2014年度培训工作总结
2014/11/27 职场文书
焦裕禄观后感
2015/06/03 职场文书
新闻简讯格式及范文
2015/07/22 职场文书
详解Js模块化的作用原理和方案
2021/04/29 Javascript
Win11如何启用启动修复 ? Win11执行启动修复的三种方法
2022/04/08 数码科技