zoukankan      html  css  js  c++  java
  • 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,
    	 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,
    	 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方法是画一个放射性的圆,起始在左上角,这样就有个光照效果,还是不错的。 看下效果图吧

  • 相关阅读:
    UVALive 6909 Kevin's Problem 数学排列组合
    UVALive 6908 Electric Bike dp
    UVALive 6907 Body Building tarjan
    UVALive 6906 Cluster Analysis 并查集
    八月微博
    hdu 5784 How Many Triangles 计算几何,平面有多少个锐角三角形
    hdu 5792 World is Exploding 树状数组
    hdu 5791 Two dp
    hdu 5787 K-wolf Number 数位dp
    hdu 5783 Divide the Sequence 贪心
  • 原文地址:https://www.cnblogs.com/mad/p/2392632.html
Copyright © 2011-2022 走看看