当前位置: 首页 > 编程日记 > 正文

HTML5 Canvas编写五彩连珠(3):设计

在看了几篇Canvas相关的文章后,发现前两节的代码实现还是有问题,因为知道的少,所以只能在自己已知的知识上做实现。不过还好,这是一个发现的过程,也是一个纠错和完善的过程。我第一次尝试一边学习一遍写博客,我想这也有助我的学习,可以把知识掌握的牢固些,起码忘的慢一些吧:)。

前两节学习了几个基本绘制的方法,lineTo moveTo和arc,也了解坐标的情况,但写的比较傻,只是单纯的实现。 比如棋盘的起始坐标如果有偏移量,我们还要计算他的具体开始坐标和结束坐标,实际上Canvas有现有的方法提供偏移的功能。 他叫 translate,另外还有缩放scale、旋转rotate,他们都可以用transform代替。所以,在代码方面还会有些调整。不过这个的学习恰巧也让我知道如何实现动画效果。如果多个元素在一个Canvas上,实现动画,必然会需要擦除重绘的情况,如果元素之间有覆盖的情况,擦除就需要多考虑了。当然,简单的办法就是把整个画布根据当然所有元素的位置重新绘制一遍。所以在代码设计方面,需要把不同的元素独立出来,每个元素都有自己的draw方法,并且要依照次序绘制Canvas。

分析一下游戏所需的元素:1、棋盘(地图)2、泡泡 3、等待区域(新的3个即将进入棋盘的泡泡)4、奖励区域(白搭星、超级百搭星、炸弹)5、统计信息 6、按钮
  所以在对象的设计方面起码要有几类 棋盘(map)、新泡泡区(ready)、奖励区(awards)、泡泡(bubble)、星星1(star1) 、星星2(star2) 、炸弹(boom)、统计积分(score),还要包括游戏背后的数据(data)。 OK,先这么规划,挨个的去实现。先把map和bubble重写了。 
  之前把map写成了类,显然是不合适的,因为这个游戏不可能会有多个map,所以直接定义为对象更方便。而泡泡显然需要很多,所以需要写成类比较方便。游戏里面所有对象需要访问的全局变量和常量需要定义在一个game对象里,游戏开始则是调用game.start()的方法。所以先看下game的定义:

var game = {canvas: document.getElementById("canvas"),ctx: this.canvas.getContext("2d"),cellCount: 9,cellWidth: 30,lineCount: 5,mode: 7,colors: ["red", "#039518", "#ff00dc", "#ff6a00", "gray", "#0094ff", "#d2ce00"],over: function () {alert("GAME OVER");},getRandom: function (max) {return parseInt(Math.random() * 1000000 % (max));},
};

cellCount就是格子的总数,cellwidth是每个格子的宽度,因为不光map里需要这个,所以就定义在了这里,mode 是游戏模式 5是简单 7是困难。
 再看下map的代码:

game.map = {startX: 40.5,startY: 60.5,width: 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(i, j, null));}this.bubbles.push(row);}},draw: function () {var ctx = game.ctx;ctx.save();ctx.translate(this.startX, this.startY);ctx.beginPath();for (var i = 0; i <= 9; 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();},addBubble: function (bubble) {var thisBubble = this.bubbles[bubble.x][bubble.y];thisBubble.color = bubble.color;},getBubble: function (x, y) {var thisBubble = this.bubbles[x][y];if (!thisBubble.color) {return null;}else {return thisBubble;}}
};

map的init初始化方法里我先把所有的泡泡部署好了,但是都没有染色,我并没有在ui的背后维护一个数组,因为我觉得泡泡有没有颜色就代表 0,1了,所以就这样也行。
draw方法不再想之前那样把起始坐标计算进去了,而是使用了translate方法,这样就很方便写代码了。
addBubble其实就是染色而已,接收参数是一个泡泡对象,这个对象来自ready区域的泡泡。

Ready区域其实就像俄罗斯方块那样,有三个预备的泡泡即将进入map区域。

game.ready = {startX: 40.5,startY: 20.5,width: 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));}},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();},
};

ready.init 初始化3个泡泡,并且把这3个泡泡“飞入”到map里,ready.draw很简单就是绘制一个小矩形和3个泡泡。

哦,对了,我们的泡泡的绘制代码也稍作了修改,现在的样子不是之前的纯色了,有了水晶效果。。。不妨看看:

        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();};

createRadialGradient方法是画一个放射性的圆,起始在左上角,这样就有个光照效果,还是不错的。 看下效果图吧

转载于:https://www.cnblogs.com/mad/archive/2012/03/17/2392632.html

相关文章:

SQL面试宝典一:

1.什么是sql Injection&#xff08;sql 注入&#xff09;&#xff1f;如何防止&#xff1f; 答&#xff1a;是一种恶意将sql代码添加到输入参数中&#xff0c;传递到sql服务器解析并执行的一种攻击手法。 防止&#xff1a;1.对用户的输入进行校验&#xff0c;可以通过正则表达…

java注解的执行顺序_深入理解Spring的@Order注解和Ordered接口

前言Spring的Order注解或者Ordered接口大家都知道是控制顺序的&#xff0c;那么它们到底是控制什么顺序的&#xff1f;是控制Bean的注入顺序&#xff0c;还是Bean的实例化顺序&#xff0c;还是Bean的执行顺序呢&#xff1f;那么我们先直接给出结论再来验证结论。结论&#xff1…

数据驱动安全需三大核心新技术

要做到数据驱动安全&#xff0c;齐向东认为需要三大核心技术。第一个核心技术是大数据采集器&#xff0c;第二个是大数据引擎&#xff0c;第三个是机器学习挖掘、重要安全问题定位准确。转载于:https://www.cnblogs.com/1992825-Amelia/p/4854220.html

[转]BI 问答

http://blog.bridata.ca/?cat16 前几天Post 了一些BI 的面试问题&#xff0c;感兴趣的人很多&#xff0c;有很多人问我答案以此来评估一下自己的知识水平。坦白地说我没有写在纸上的具体答案&#xff0c;事实上每个问题也没有具体和精确的答案&#xff0c;所谓面试就不是笔试&…

没有学不会的C++:用户自定义的隐式类型转换

C 中的类型转换包含内建类型的转换和用户自定义类型的转换&#xff0c;而这两者都又可分为隐式转换和显示转换&#xff0c;所以一共有如下四象限表格中的 A、B、C、D 四种情况 隐式转换显示转换(casting)内建类型转换 (int, float ...)AB用户自定义类型转换(类 vs 类; 类 vs 内…

python scrapy菜鸟教程_scrapy学习笔记(一)快速入门

安装ScrapyScrapy是一个高级的Python爬虫框架&#xff0c;它不仅包含了爬虫的特性&#xff0c;还可以方便的将爬虫数据保存到csv、json等文件中。首先我们安装Scrapy。pip install scrapy在Windows上安装时可能会出现错误&#xff0c;提示找不到Microsoft Visual C。这时候我们…

执行eclipse,迅速failed to create the java virtual machine。

它们必须在一排&#xff0c;否则会出现The Eclipse executable launcher was unable to locate its companion shared library的错误 打开eclipse文件夹下的eclipse.ini文件。改动–launcher.XXMaxPermSize属性&#xff0c;当中此属性有两处 -startup plugins/org.eclipse.equi…

vue打包后图片找不到情况

打包之前需要修改如下配置文件&#xff1a; 配置文件一&#xff1a;build>>>utils.js (修改publicPath:"../../" , 这样写是处理打包后找不到静态文件&#xff08;图片路径失效&#xff09;的问题) 配置文件二&#xff1a;config>>>index.js(修改a…

UBUNTU安装SSH和xrdp

一、安装SSH&#xff0c;通过PUTTY访问 命令&#xff1a;sudo apt-get install ssh 查看&#xff1a;netstat -l 二、安装xrdp&#xff0c;通过远程桌面访问 命令&#xff1a;sudo apt-get install xrdp 开启远程桌面访问权限 系统-->首选项-->remote desktop 三、去掉远…

python中opencv中inrange用法_python-opencv中的cv2.inRange函数

本次目标是将一副图像从rgb颜色空间转换到hsv颜色空间&#xff0c;颜色去除白色背景部分具体就调用了cv2的两个函数&#xff0c;一个是rgb转hsv的函数具体用法hsv cv2.cvtColor(rgb_image, cv2.COLOR_BGR2HSV)然后利用cv2.inRange函数设阈值&#xff0c;去除背景部分mask cv2…

[转]C++11 随机数学习

相对于C 11之前的随机数生成器来说&#xff0c;C11的随机数生成器是复杂了很多。这是因为相对于之前的只需srand、rand这两函数即可获取随机数来说&#xff0c;C11提供了太多的选择和东西。 随机数生成算法&#xff1a; 随机数生成算法有很多&#xff0c;C11之前的C/C只…

Linux Shell ssh登录脚本

Linux 登陆服务器敲命令太多,某时候确实不便,所以就用shell写了一个 我的blog地址: http://www.cnblogs.com/caoguo 一.说明 支持秘密和密钥两种格式用户名和密码都是写文件的,明文保存二.配置 密码文件配置:序号:IP:端口:用户:密码:说明 1:192.168.88.128:22:root:toor:虚拟机…

C# 温故而知新:Stream篇(二)

C# 温故而知新&#xff1a;Stream篇&#xff08;二&#xff09; TextReader 和StreamReader 目录&#xff1a; 为什么要介绍 TextReader&#xff1f; TextReader的常用属性和方法 TextReader 示例 从StreamReader想到多态 简单介绍下Encoding 编码 StreamReader 的定义及作用 S…

usaco Pollutant Control

第一问是求最小割。第二问求最小割中集合中边最少的集合的大小。 第三问求集合中边最少且字典序最小的边的下标。 第一问直接求最大流就能解&#xff0c;第二问将原来的边的容量都改为1&#xff0c;求出来的最大流就是元素最少的一个最小割的大小。 将容量都改为1之后&#xff…

洛谷P4705 玩游戏(生成函数+多项式运算)

题面 传送门 题解 妈呀这辣鸡题目调了我整整三天……最后发现竟然是因为分治\(NTT\)之后的多项式长度不是\(2\)的幂导致把多项式的值存下来的时候发生了一些玄学错误……玄学到了我\(WA\)的点全都是\(WA\)在\(2\)的幂次行里…… 看到这种题目二话不说先推倒 \[ \begin{aligned}…

blast程序 介绍 简介

每次找都挺麻烦&#xff0c;又记不住&#xff0c;于是抄下来&#xff1a; blastp:将待查询的蛋白质序列及其互补序列一起对蛋白质序列数据库进行查询&#xff1b;blastn:将待查询的核酸序列及其互补序列一起对核酸序列数据库进行查询&#xff1b;blastx:先将待查询的核酸序列按…

java泛型的实现和原理_java 泛型实现原理

泛型思想最早在C语言的模板(Templates)中产生&#xff0c;Java后来也借用了这种思想。虽然思想一致&#xff0c;但是他们存在着本质性的不同。C中的模板是真正意义上的泛型&#xff0c;在编译时就将不同模板类型参数编译成对应不同的目标代码&#xff0c;List和List是两种不同的…

java out of range_关于Parameter index out of range求解决办法

程序&#xff1a;提示参数越界&#xff0c;但我实在不知道我到底哪里越界了。明明该我那样写的嘛。求高手帮我看看&#xff0c;现在我是弄得我有气无力了&#xff01;要死了。在去死亡的路上等着你帮帮我&#xff01;Document : replyokCreated on : 2008-9-29, 6:05:31Autho…

FineReport——权限分配以及自定义首页

权限分配可以有两种方法&#xff0c;第一种方法是根据部门职位分配权限&#xff0c;第二种是根据角色分配权限&#xff1b; FR自带有三个JQ对象&#xff0c;用以保存用户名参数/角色参数/部门参数——$fr_username/$fr_authority/$fr_userposition 根据部门职位&#xff1a; 以…

去掉[]中的英文(正则表达式)C#

这个问题本来是以为信息科技大学的老师问蒋委员长的问题,蒋委员长用正则表达式完成了这个问题 1,问题的情况有哪些? abc[abc]abc,abc[-abc]abc,abc[一abc]abc,abc[一abc一]abc等等. 2,问题的解决目标? 写一个通用的方法来完成提出的问题. 3,解决方案 -->正则表达式方法 其…

Event Loop

事件队列 Javascript是单线程&#xff0c;单线程就意味着所有任务需要排队。然后会将所有任务分成两类&#xff1a;同步任务和异步任务&#xff01;同步任务&#xff1a;在主线程上执行的任务&#xff0c;只有前一个任务执行完成&#xff0c;才会执行后一个&#xff01;异步任务…

java makefile jar包_java makefile学习实践(编译的javac命令写在makefile中,运行命令java写在shell脚本中)...

学习makefile教程&#xff0c;ubuntu中文网1.写一个简单的java项目&#xff0c;不需要外部jar,用的简单的importjava.util.ArrayList;是可以从CLASSPATH环境变量中找到的&#xff0c;在javac阶段不需要特殊添加-cphellocatHellocat.javaimportjava.util.ArrayList;importjava.u…

Python字符编码详解

Python字符编码详解 转自http://www.cnblogs.com/huxi/archive/2010/12/05/1897271.html Python字符编码详解 本文简单介绍了各种常用的字符编码的特点&#xff0c;并介绍了在python2.x中如何与编码问题作战 &#xff1a;&#xff09; 请注意本文关于Python的内容仅适用于2.x&a…

《编写有效用例》读书笔记1

第一章 引言 本章主要介绍用例是什么样子的&#xff0c;并描述为什么不同的项目组需要采用不同 的用例编写风格以及在什么地方使用用例有利于做需求收集工作&#xff0c;也让我们了解 在编写用例之前&#xff0c;需要做哪些准备工作。 用例是代表系统中各个项目相关人员之间就系…

顺序结构,判断结构 if,switch

1&#xff1a;顺序结构&#xff1a;从上往下执行程序代码&#xff0c;为顺序结构 ---------------------------------------------------------------------- 2&#xff1a;判断结构&#xff1a; if 如果 判断是两个选择一个&#xff0c;要么对要么错 if中的条件表达式 返回…

php转换文字Unicode,php实现将中文转为unicode的方法

相关函数说明&#xff1a;iconv命令是用来转换文件的编码方式的&#xff0c;比如它可以将UTF8编码的转换成GB18030的编码&#xff0c;反过来也行。str_split() 函数把字符串分割到数组中。bin2hex() 函数把 ASCII 字符的字符串转换为十六进制值。字符串可通过使用 pack() 函数再…

kail安装和vmtools安装

因位太费劲我直接把我做的Word文档直接上传了&#xff0c;如果想安装可以下载&#xff0c;我就不麻烦在写一遍了&#xff0c;这个教程主要给小白讲的&#xff0c;大佬请绕过 kail安装教程.docx https://pan.wps.cn/l/sm43o7f 密码&#xff1a;f43341转载于:https://www.cnblogs…

Windows计数器做性能监控(window server 2008服务器)

使用Windows计数器 一、创建数据收集器集 二、创建数据收集器 三、使用数据收集器 1、修改数据收集器的属性 2、手动启用、手动停止数据收集器集 3、计划任务 4、在性能监视器中查看 一、性能监视器 Windows 服务器操作系统提供一个名为“性能监视器”的图形工具&#xff0c;可…

使用浏览器wpf应用程序时访问数据库需要报权限错误的解决方法

在这篇wpf教程中&#xff0c;如果选用浏览器wpf应用程序模板我遇到了 访问数据库时权限不够 不能打开连接 将项目属性的安全性中设置为完全信任后即解决 转载于:https://www.cnblogs.com/langu/archive/2012/03/29/2423620.html

gprs 神奇宝典java,2016联通笔试知识点大全

答&#xff1a;呼叫转移是指用户在工作忙或手机无网络等无法用本机接听电话的情况下&#xff0c;即可将来电设置呼叫转移到另一个号码上&#xff0c;实现号码转移。注&#xff1a;呼叫转移业务目前无需月功能费&#xff0c;用户设置呼叫转移后&#xff0c;如正常接听来电则按照…