首先说明qq截图效果太丑了,实际效果要比这个漂亮。本例是实现了100个随机颜色随机大小的圆环以随机速度向随机方向移动并碰壁反弹。
然后推荐以下两个博客,一篇是canvas动画面向对象实现方法的基本思路,一篇是松峰老师翻译的基于canvas开发简单游戏框架的教程
http://neekey.net/blog/2011/05/11/canvas-%E7%AE%80%E5%8D%95%E5%8A%A8%E7%94%BB%E5%AE%9E%E7%8E%B0%E6%80%9D%E8%B7%AF/
http://www.cn-cuckoo.com/2011/08/10/game-development-with-javascript-and-the-canvas-element-2554.html
由于之前并没有真正用面向对象的方法编写js,这两篇文章我足足花了两天时间研究才弄懂,并学着写了这个效果出来。
如果你和我一样刚刚接触js的面向对象编程,严重推荐以上两篇文章;如果你是大侠,欢迎指正。
以下是这几天来我对面向对象编程的一些理解:
什么是面向对象的编程?
面 向对象编程是相对于面向过程编程的一种更加有亲和力的编程方法。面向对象编程可以理解为把程序中的关键模块都视为对象,对象拥有一些属性和方法。我们把这 些对象描绘出来并赋予他们属性以后,他们就相当于程序的主要零部件。其实更完美的状态就是,我们把这些零部件的功能编写的足够完善,只要给他们一个开始命 令,他们就开始有条不紊地互相运转了。
举个例子,假如我们要编辑一场车祸,面向过程的编程方法就是一步步编写两车从哪里来,初始速度多少, 怎么撞上的,撞上以后是什么结果。而面向对象的方法就直接构建出两个汽车对象,赋予他们速度,方向等属性,这个过程就自然而然的发生了。两种编辑的结果是 一样的,但思想角度不同。
这就是面向对象和面向过程都能实现相同的功能,但思考方式不一样。
面向对象编程有什么优势?
如 果你写非常简单的效果,趁早打消面向对象编程的念头,它只会让你的程序更加复杂,更加耗费资源。只有你在编写复杂程序时,这种编程方法的优势就会体现出 来。渐渐地你就会发现,这种编程方法更容易理解,也更容易构建,修改。更令人兴奋的是,我们可以随时添加和删除一些非功能性的对象,比如上文的例子,我们 可以轻松地模拟出100辆车相撞的场景,不用去细细地描绘过程,只需要从对象类中继承出100个汽车实例就可以了。这样的话,如果我们要编写一个非常复杂 的动画或者游戏,面向过程的思想就能让我们的代码更加精简易懂,也让我们的思路变得更加清晰。
一直觉得,如果真的把面向对象的思想理解透了,再复杂的环境我们都可以有条不紊地构建出来。
还是说说本例是怎么实现的吧,本程序的两个主要对象是:
圆环;
帧。
圆环比较好理解,这个程序无非就是100个圆环嘛,这个属于实例型的对象,我们能想的通。
那么帧对象是个什么东西呢?这其实是flash中得来的灵感,flash就是靠一帧一帧的渲染来实现动画的。在我们这里,这个帧对象肩负着管理100个圆环并且重复渲染画布的使命,这属于功能性的对象。
其实我这里的程序并不是最好的,还有好多地方值得优化。例如可以从圆环对象中剥离出一个sprite对象来形成一个独立的运动对象,就加更清晰。慢慢改进吧。
废话不多说了,下面是代码,有详尽的注释,大家可以粘下来在支持canvas的浏览器进行测试:
<!doctype html><html><head> <title>智能圆环</title> <meta charset='utf-8' /> <style type="text/css"> body{background-color:black;} #Canvas{height:500px;width:500px;margin:50px auto;display:block;} </style></head><body> <canvas width='500px' height='500px' id='Canvas'>您的浏览器不支持canvas</canvas></body><script type="text/javascript"> /* *用面向对象编程方法实现的一群运动圆环 *by @谢帅shawn */ //初始化画布 var can=document.getElementById('Canvas'); var ctx=can.getContext('2d'); /* *创建一个圆环类Circle,智能圆环的模型 *方法写在prototype里可以减少不必要的创建 */ var Circle=function(x,y,radius,options,speeds){ this.w=can.width; this.h=can.height; this.ctx=ctx; this.x=x; this.y=y; this.radius=radius; this.options=options; this.speed=speeds; } Circle.prototype={ //draw方法,画出圆环 draw:function(){ this.ctx.beginPath(); this.ctx.strokeStyle=this.options.strokeStyle; this.ctx.lineWidth=this.options.lineWidth; this.ctx.arc(this.x,this.y,this.radius,0,2*Math.PI,true); this.ctx.stroke(); }, //move方法,圆环坐标自加速度,并执行draw方法 move:function(){ this.x+=this.speed.speedX; this.y+=this.speed.speedY; this.draw(); } } /* *创建一个Frame帧类,管理所有circles实例,实现画布的渲染 */ var Frame=function(){ this.w=can.width; this.h=can.height; this.ctx=ctx; this.circles=[]; this.sint=null; } Frame.prototype={ //star开始定时器,循环调用渲染方法 star:function () { this.sint=setInterval((function(progra){ return function(){progra.render();} })(this),30); //帧数可以在这里修改 }, //render渲染方法 render:function () { //清除上一帧 this.ctx.clearRect(0,0,can.width,can.height); //调用每个实例circle的运动方法,监听circle坐标实现碰壁反弹效果 for (i in this.circles) { this.circles[i].move(); if(this.circles[i].x>can.width-this.circles[i].radius-this.circles[i].options.lineWidth/2 || this.circles[i].x<0+this.circles[i].radius+this.circles[i].options.lineWidth/2){ this.circles[i].speed.speedX=-this.circles[i].speed.speedX; //delete this.circles[i];可以实现碰壁消失的效果,delete可删除实例 } if(this.circles[i].y>can.height-this.circles[i].radius-this.circles[i].options.lineWidth/2 || this.circles[i].y<0+this.circles[i].radius+this.circles[i].options.lineWidth/2) this.circles[i].speed.speedY=-this.circles[i].speed.speedY; } } } /* *Main */ //创建一个帧实例fra var fra=new Frame(); //创建100个圆环实例circles【i】 for (var i=0; i<100; i++) { //输入speed属性,这里随机产生 var speed={ speedX:Math.random()*10-5, speedY:Math.random()*10-5 } var r=Math.floor(Math.random()*256); var g=Math.floor(Math.random()*256); var b=Math.floor(Math.random()*256); var a=Math.random(); //输入option属性,这里随机产生 var option={ strokeStyle:'rgba('+r+','+g+','+b+','+a+')', lineWidth:Math.random()*20+5 } //创建实例 var circle=new Circle(Math.random()*100+can.width/2,Math.random()*100+can.height/2,Math.random()*50+10,option,speed); fra.circles[i]=circle; } //开始渲染 fra.star();</script></html>
联系客服