分享

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

 pengphie 2016-10-23

首先说明qq截图效果太丑了,实际效果要比这个漂亮。本例是实现了100个随机颜色随机大小的圆环以随机速度向随机方向移动并碰壁反弹。

然后推荐以下两个博客,一篇是canvas动画面向对象实现方法的基本思路,一篇是松峰老师翻译的基于canvas开发简单游戏框架的教程

http:///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./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>
复制代码

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约