<<javascript 高效图形编程>>笔记

某天在学校图书馆里溜达的时候看见的这本书,感觉应该有点干货就借回来了.放了几天,今天干什么都不对劲,就把这本书拿出来看了看,发现一些有意思的东西.

第一个是一个递归绘图,之前见过类似的小动画,感觉很神奇,没想到在这本书里的代码就简简单单的一点.

对我来说最没想到的是这个代码就像平时的递归程序一样简单,我总觉得牵涉到图形的时候一切都悔变得复杂,就不愿意动脑了,这样不好.

<!DOCTYPE html>
<html>
    <head>
        <title>OK</title>
        <script type = "text/javascript" src = "http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
        <script type = "text/javascript">
            var maxAngle = Math.PI / 7;//控制子树于亲树的角度偏转最大值
            var drawTree = function(ctx, startX, startY, length, angle, depth, branchWidth) {//如同深度优先搜索一般简洁明了的程序
                var newLength, endX, endY, newAngle;
                if (depth < 0) {
                    return;
                }
                //枝杈终点
                endX = startX + length * Math.cos(angle);
                endY = startY + length * Math.sin(angle);
                //绘出当前枝杈
                ctx.beginPath();
                ctx.moveTo(startX, startY);
                ctx.lineCap = "round";
                ctx.lineWidth = branchWidth;
                ctx.lineTo(endX, endY);
                if (depth <= 2) {//根据是否靠近边缘决定颜色
                    ctx.strokeStyle = 'rgb(0, ' + (((Math.random() * 64) + 128) >> 0) + ', 0)';//strokestyle接受字符串
                }
                else {
                    ctx.strokeStyle = 'rgb(' + (((Math.random() * 64) + 64) >> 0) + ', 50, 25)';
                }
                ctx.stroke();
                //下级枝杈
                branchWidth *= 0.7;

                newAngle = angle - Math.random() * maxAngle;
                newLength = length * (0.7 + Math.random() * 0.3);
                drawTree(ctx, endX, endY, newLength, newAngle, depth - 1, branchWidth);

                newAngle = angle + Math.random() * maxAngle;
                newLength = length * (0.7 + Math.random() * 0.3);
                drawTree(ctx, endX, endY, newLength, newAngle, depth - 1, branchWidth);
            };
        </script>
    </head>
    <body>
        <script type = "text/javascript">
            $(document).ready(function(){
                var cvs = document.getElementById('myCanvas');
                var ctx = cvs.getContext("2d");
                drawTree(ctx, 400, 600, 60, -Math.PI/2, 14, 12);
            });
        </script>
        <canvas id = "myCanvas" width = "800" height = "600" />
     </body>
</html>
上张效果图


第二个是一个大炮模拟程序,里面使用了向量,游戏对象,还有一些我之前没见过的API,对我启发很大.

要记一下的地方:

1 函数继承 形如 : var vector = function(){var that = {}; return that;};

2 对象字面量,以前一直没用过.

3 向量,还有向量的操作.

4 API

原来可以在元素节点上加事件监听,以前一直不知道.

ctx.save() && ctx.restore() 保存和重绘canvas, 在做有背景的动画时用这个绘制背景,不丢失动画元素渐变信息.

ctx.rotate(), 旋转ctx, 可以画倾斜的矩形了

canvas.getBoundingClientRect(), event里的坐标是相对于整个窗口的,我们要的是相对于画布的坐标,用此获得画布的坐标.

5 gameObjects数组,管理游戏元素

<!DOCTYPE html>
<html>
	<head>
		<title>GO !!!</title>
		<script type = "text/javascript">
			window.onload = function(){
				var gameObjects = [];
				var canvas = document.getElementById("canvas");
				var ctx = canvas.getContext('2d');

				var vector2d = function(x, y){
					var vec = {
						vx : x,
						vy : y,
						//scale() method allows us to scale hte vector, eighter up or down.
						scale : function(scale){
							vec.vx *= scale;
							vec.vy *= scale;
						},
						//add() method adds a vector.
						add : function(vec2){
							vec.vx += vec2.vx;
							vec.vy += vec2.vy;
						},
						//sub() method substracts a vector.
						sub : function(vec2){
							vec.vx -= vec2.vx;
							vec.vy -= vec2.vy;
						},
						//negate() method points the vector in the opposite direction. 
						negate : function(){
							vec.vx = -vec.vx;
							vec.vy = -vec.vy;
						},
						//length() method returns the length of the vector using Pythagoras.
						length : function(){
							return Math.sqrt(vec.vx * vec.vx + vec.vy * vec.vy);
						},
						//A faster length calucalation that returns the length squared.
						//Useful if all you want to know is that one vector is longer than another.
						lengthSquard : function(){
							return vec.vx * vec.vx + vec.vy * vec.vy;
						},
						//normalize() method turns the vector into a unit length vector pointing in the same direction.
						normalize : function(){
							var len = Math.sqrt(vec.vx * vec.vx + vec.vy * vec.vy);
							if(len){
								vec.vx /= len;
								vec.vy /= len;
							}
							return len;//Maybe useful.
						},
						//Rotate the vector by an angle specified in radians.
						rotate : function(angle){
							var vx = vec.vx;
							var	vy = vec.vy;
							var	cosVal = Math.cos(angle);
							var	sinVal = Math.sin(angle);
							vec.vx = vx * cosVal - vy * sinVal;
							vec.vy = vx * sinVal + vy * cosVal;
						},
						//I like it.
						toString : function(){
							return '(' + vec.vx.toFixed(3) + ',' + vec.vy.toFixed(3) + ')';
						}
					};
					return vec;
				};

				var cannonBall = function(x, y, vector)
				{
					var gravity = 0;
					var that = {
						x : x,
						y : y,
						removeMe : false,
						move : function(){
							vector.vy += gravity;
							gravity += 0.1;
							that.x += vector.vx;
							that.y += vector.vy;

							if(that.y > canvas.height - 150){
								that.removeMe = true;
							}
						},

						draw : function(){
							ctx.beginPath();
							ctx.arc(that.x, that.y, 5, 0, Math.PI * 2, true);
							ctx.fill();
							ctx.closePath();
						}
					};
                    return that;
				};

				var cannon = function(x, y){
					var mx = 0, my = 0;
					var angle = 0;
					var that = {
						x : x,
						y : y,
						angle : 0,
						removeMe : false,

						move : function(){
							angle = Math.atan2(my - that.y, mx - that.x);
						},

						draw : function(){
							ctx.save();
							ctx.lineWidth = 2;
							ctx.translate(that.x, that.y);

							ctx.rotate(angle);

							ctx.strokeRect(0, -5, 50, 10);

							ctx.moveTo(0, 0);
							ctx.beginPath();
							ctx.arc(0, 0, 15, 0, Math.PI * 2, true);
							ctx.fill();
							ctx.closePath();
							ctx.restore();
						}
					};
					//原来可以直接给heml元素加事件监听
					canvas.onmousedown = function(event){
						var vec = vector2d(mx - that.x, my - that.y);
						vec.normalize();
						vec.scale(25);
						gameObjects.push(cannonBall(that.x, that.y, vec));
					};

					canvas.onmousemove = function(event){
						var bb = canvas.getBoundingClientRect();
						mx = (event.clientX - bb.left);
						my = (event.clientY - bb.top);
					};

					return that;
				};

				var drawSkyAndGrass = function(){
					ctx.save();
					ctx.globalAlpha = 0.4;
					var linGrad = ctx.createLinearGradient(0, 0, 0, canvas.height);
					linGrad.addColorStop(0, "#00BFFF");

					linGrad.addColorStop(0.5, 'white');
					linGrad.addColorStop(0.5, '#55dd00');
					linGrad.addColorStop(1, 'white');
					ctx.fillStyle = linGrad;
					ctx.fillRect(0, 0, canvas.width, canvas.height);
					ctx.restore();
				};

				gameObjects.push(cannon(50, canvas.height - 150));

				setInterval(function(){
					drawSkyAndGrass();

					var gameObjectsFresh = [];
					for(var i = 0; i < gameObjects.length; i++){
						gameObjects[i].move();
						gameObjects[i].draw();
						if(gameObjects[i].removeMe == false){
							gameObjectsFresh.push(gameObjects[i]);
						}
					}
					gameObjects = gameObjectsFresh;
				}, 30);
			};
        </script>
	</head>
	<body>
		<canvas id = "canvas" width = 640 height = 480 />
	</body>
</html>

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值