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

来源:互联网 发布:linux内核源码 编辑:程序博客网 时间:2024/05/16 17:41

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

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

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

<!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;varvy = vec.vy;varcosVal = Math.cos(angle);varsinVal = 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 0
原创粉丝点击