canvas入门级小游戏《开关灯》思路讲解
游戏很简单,10行10列布局,每行每列各10盏灯,游戏初始化时随机点亮其中一些灯,点击某盏灯,其上下左右的灯及本身状态反转,如果点击前是灭着的,点击后即点亮,将所有灯全部点亮才算过关。游戏试玩:
下面说说大概思路:
生成画布
创建canvas画布,先是生成10*10阵列的100盏灯,每盏灯之间的间隔为margin = 5px,第一盏灯圆心坐标为它的半径"R, R",第一行第二盏灯坐标为3R+margin,以此类推得出灯坐标计算公式:第一行第i盏灯横坐标(2*i + 1)*R + i*margin,同理第一列第j行纵坐标为(2*j + 1)*R + j*margin
为其中灯开关的状态是随机的,很自然的想到利用随机数Math.random()去和0.5比较大小,随机数大于0.5则灯熄灭,否则点亮。为了便于游戏扩展和维护,游戏中灯的半径、所有灯的坐标、颜色、数量、是否点亮等数据用变量存起来。
<canvas id="canvas" width="445" height="445">
您的浏览器不支持canvas!
</canvas>
<script>
var lightOff = {
gameData : [], // 灯开关状态
r : 20, // 灯半径
margin: 5, // 灯间距
padding: 20, // canvas内边距
onColor: "#0077AA", // 灯亮的颜色
offColor: "#E0E0E0", // 灯灭的颜色
row : 10, // 10行
col : 10, // 10列
canvas : document.getElementById("canvas"),
ctx : this.canvas.getContext("2d"),
reDraw: function(p){
for (var i = 0; i < this.row; i++) {
for (var j = 0; j < this.col; j++) {
this.ctx.beginPath();
this.ctx.fillStyle = this.gameData[i][j] ? this.onColor : this.offColor;
this.ctx.arc( i*this.margin+(2*i+1)*this.r, j*this.margin+(2*j+1)*this.r, this.r, 0, 2*Math.PI );
this.ctx.fill();
}
}
return this;
},
// 随机生成100盏灯的状态
createMap: function(){
for (var i = 0; i < this.row; i++) {
this.gameData[i] = [];
for (var j = 0; j < this.col; j++) {
this.gameData[i].push( Math.random() > 0.5 ? false : true );
}
}
return this;
}
}
</script>
添加点击事件
众所周知,canvas是一个整体,如何给其中某一盏灯添加点击事件?事实上,可以给整个canvas对象添加点击事件,将event对象下的event.layerX, event.layerY传入isPointInPath(x, y)方法判断点击的坐标event.layerX, event.layerY是否在灯上从而触发回调函数。
示例:
需要注意的是:isPointInPath(x, y)方法只能判断坐标x, y是否在最近的上下文所绘制的图形内,如果canvas一次性绘制了100盏灯,isPointInPath(x, y)只能判断x, y是否在第100盏灯内,要想判断x, y是否在所点击的某盏灯内,就应该在每次点击的时候重绘这100盏灯(调用reDraw方法),每绘制一盏灯触发一次isPointInPath(x, y)方法,如果在灯上,将gameData对应灯的数据状态反转。如当前绘制第i行第j盏灯,调用isPointInPath(x, y)返回true,则反转该灯状态game[i][j] = !game[i][j]之后再次调用reDraw方法重绘。每次点击需要重绘两次。
综上所述,代码修改为:
var lightOff = {
gameData : [],
r : ,
margin: ,
padding: ,
onColor: "#0077AA",
offColor: "#E0E0E0",
row : ,
col : ,
canvas : document.getElementById("canvas"),
ctx : this.canvas.getContext("2d"),
init: function(){
var This = this;
// 判断是否点击了该圆点
this.canvas.addEventListener("click", function(ev){
This.reDraw(ev);
This.reDraw();
})
this.createMap().reDraw();
return this;
},
reDraw: function(p){
this.count = ;
this.ctx.clearRect(, , this.canvas.width, this.canvas.height);
for (var i = ; i < this.row; i++) {
for (var j = ; j < this.col; j++) {
this.ctx.beginPath(); this.ctx.fillStyle = this.gameData[i][j] ? this.onColor : this.offColor;
this.ctx.arc( i*this.margin+(*i+)*this.r, j*this.margin+(*j+)*this.r, this.r, , *Math.PI );
this.ctx.fill();
if( p && this.ctx.isPointInPath(p.layerX-this.padding, p.layerY-this.padding) ){
this.gameData[i][j] = !this.gameData[i][j];
i > && (this.gameData[i-][j] = !this.gameData[i-][j]);
i < && (this.gameData[i+][j] = !this.gameData[i+][j]);
j > && (this.gameData[i][j-] = !this.gameData[i][j-]);
j < && (this.gameData[i][j+] = !this.gameData[i][j+]);
}
this.gameData[i][j] && this.count++;
}
} if(this.count === ){
alert("成功了")
} return this;
},
createMap: function(){
for (var i = ; i < this.row; i++) {
this.gameData[i] = [];
for (var j = ; j < this.col; j++) {
this.gameData[i].push( Math.random() > 0.5 ? false : true );
}
}
return this;
}
} lightOff.init();
作者:古德God
出处:http://www.cnblogs.com/wangmeijian
本文版权归作者和博客园所有,欢迎转载,转载请标明出处。
如果您觉得本篇博文对您有所收获,请点击右下角的 [推荐],谢谢!
canvas入门级小游戏《开关灯》思路讲解的更多相关文章
- cocosCreator微信小游戏排行榜思路
cocosCreator制作微信小游戏排行榜实现方案: 游戏认知:项目分为主域和子域,主域就是游戏主程部分,子域为单独处理微信排行榜公共域数据的. 游戏主域里创建一个节点,添加WXSubContext ...
- 用Canvas制作小游戏——贪吃蛇
今天呢,主要和小伙伴们分享一下一个贪吃蛇游戏从构思到实现的过程~因为我不是很喜欢直接PO代码,所以只copy代码的童鞋们请出门左转不谢. 按理说canvas与其应用是老生常谈了,可我在准备阶段却搜索不 ...
- 微信小程序红包开发思路 微信红包小程序开发思路讲解
之前公司开发小程序红包,将自己在开发的过程中遇到的一些坑分享到了博客里.不少人看了以后,还是不明白怎么开发.也加了我微信咨询.所以今天,我就特意再写一篇文章,这次就不谈我开发中遇到的坑了.就主要给大家 ...
- 尝试用canvas写小游戏
还是习惯直接开门见山,这个游戏是有一个老师抓作弊的学生,老师背身,点学生开始加分,老师会不定时回头,如果老师回头还在点学生在,就会被抓住,游戏game over. 1.写游戏首先是loading条,于 ...
- C/C++入门级小游戏——开发备忘录
很多工科的学生在大一都有一门课程,叫C语言程序设计.大概就是装个IDE然后和一个黑乎乎的窗口打交道,期末到了考完试就结束了.然而很多人可能都有一个疑惑:C语言究竟能干什么?除开嵌入式单片机这些高大上的 ...
- java 图形化小工具Abstract Window Toolit :画笔Graphics,画布Canvas(),弹球小游戏
画笔Graphics Java中提供了Graphics类,他是一个抽象的画笔,可以在Canvas组件(画布)上绘制丰富多彩的几何图和位图. Graphics常用的画图方法如下: drawLine(): ...
- 第一个leapmotion的小游戏
自从看过leapmotion的宣传视频,就被吸引住了.觉得这东西迟早要替代鼠标,然后关注了一年多leapmotion的动态,终于在今年8月份入手了一只.//675大洋啊,心疼~ 一直想写份评测,一直想 ...
- 微信小游戏开发之四:使用three.js引擎
一.前言 微信小游戏中最魔性的'跳一跳'就是基于three.js 引擎开发的 源码放到github上了:GitHub地址 请自行下载. 二.下载 three.min.js 打开页面,复制代码到本地 ...
- JS练习实例--编写经典小游戏俄罗斯方块
最近在学习JavaScript,想编一些实例练练手,之前编了个贪吃蛇,但是实现时没有注意使用面向对象的思想,实现起来也比较简单所以就不总结了,今天就总结下俄罗斯方块小游戏的思路和实现吧(需要下载代码也 ...
随机推荐
- 洛谷P2469 星际竞速
上下界费用流比较无脑,提供一种更巧妙的费用流,无需上下界. #include <cstdio> #include <algorithm> #include <queue& ...
- IIS并发连接数和数据库连接池
一.数据库连接池 1.报错: 超时时间已到.超时时间已到,但是尚未从池中获取连接.出现这种情况可能是因为所有池连接均在使用,并且达到了最大池大小. 2.问题分析: 问题的原因是与数据库的连接没有显示关 ...
- Turn your Session into FlushMode.COMMIT/AUTO or remove 'readOnly' marker from transaction 异常一例
参考下面的文章,最终找到我的报错原因: 我是在 service中一个以 get开头的方法中,加入了一行数据库数据删除代码,因为 spring的事务配置中,配置了get开头的方法 是 readonle的 ...
- 使用 yield 减少内存消耗
php 里面想要处理一个文本文件,有一个方法是使用 file() 函数,但是这个函数会读取文件所有内容,可能会导致占用很大内存. // 28.1 M 的文本文件, 200w 行 $file = 'st ...
- Openstack 网络服务 Neutron计算节点部署(十)
Neutron计算节点部署 安装组件,安装的服务器是192.168.137.12 1.安装软件包 yum install -y openstack-neutron-linuxbridge ebtabl ...
- Java基础-JVM调优策略简介
Java基础-JVM调优策略简介 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.JVM结构分析 1>.JVM结构图 2>.JVM运行时数据区功能说明 JVM管理的内 ...
- JXL读取,写入Excel
JXL读取,写入Excel2003 相关阅读:poi 读写excel2003:http://www.cnblogs.com/gavinYang/p/3576739.htmlpoi 读写excel200 ...
- html5 canvas从圆开始
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- [转载]使用SQL Server 2008的事务日志传送功能备份数据库(logshiping)
http://www.cnblogs.com/benbenkoala/archive/2009/03/11/1407793.html 引言:SQL Server的事务日志传送备份是仅次于镜像的高可靠性 ...
- PHP扩展开发--编写一个helloWorld扩展
为什么要用C扩展 C是静态编译的,执行效率比PHP代码高很多.同样的运算代码,使用C来开发,性能会比PHP要提升数百倍. 另外C扩展是在进程启动时加载的,PHP代码只能操作Request生命周期的数据 ...