面向对象编程方法实现一群圆环的随机运动

面向对象编程方法实现一群圆环的随机运动

首先说明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>

你可能感兴趣的:(面向对象)