zoukankan      html  css  js  c++  java
  • canvas学习作业,模仿做一个祖玛的小游戏

    这个游戏的原理我分为11个步骤,依次如下:

    1、布局,

    2、画曲线(曲线由两个半径不同的圆构成)

    3、画曲线起点起始圆和曲线终点终止圆

    4、起始的圆动起来,

    5、起始的圆沿曲线走起来

    6、起始的圆沿曲线走起来,并在曲线初始位置处产生新圆

    7、添加图片,这个图片是为了发射子弹

    8、让图片跟随鼠标动起来

    9、让动起来的图片跟随鼠标的位置发送子弹,并让子弹的颜色变红

    10、图片发射的子弹和轨迹上的小圆碰撞检测

    11、碰撞检测后让发射的子弹和轨迹上的小圆消失

    这就是该程序步骤的的分解。

    第一点:布局

    <div id="div1">
        <canvas id="canvas1" width="800px" height="800px"></canvas>
    </div>
     *{margin:0;padding:0;}
        #canvas1{background-color: #ccc;}
        #div1{
            width: 800px; margin: 20px auto;}

    布局很简单。

    第二点:画曲线

    //外大圆
                    oCG.beginPath();
                    oCG.arc(400,400,250,-90*Math.PI/180,180*Math.PI/180,false);
                    oCG.stroke();
                    //内小圆
                    oCG.beginPath();
                    oCG.arc(350,400,200,180*Math.PI/180,0,false);
                    oCG.stroke();
                    //末尾圆
                    oCG.beginPath();
                    oCG.arc(550,400,30,0,360*Math.PI/180,false);
                    oCG.stroke();

    外面的大圆圆心坐标为400,400,半径为250,从-90度到180度,顺时针。,内小圆的圆心坐标为350,400,半径为200,从180度到0度,瞬时针。曲线终点有一个小圆,圆心坐标为550,400,半径为30。三个圆都为空心圆。

    第三点:画曲线起点起始圆和曲线终点末尾圆

    曲线终点的末尾圆,在上面已经绘制了,下来就是曲线的起始点的圆如何绘制

                        oCG.beginPath();
                        oCG.moveTo(400,150);
                        oCG.arc(400,150,30,0,360*Math.PI/180,false);
                        oCG.fill();        

    第四点:起始的圆动起来

    起始点的坐标为400,150,半径为30,但是要考虑到一点,小圆圆心坐标是变化的,为了方便数据的改变,使用json去存放数据

                var ball=[];
                    ball[0]={
                        x:400,  //小圆起始点横坐标
                        y:150,  //小圆起始点纵坐标
                        r:250,   //大圆的半径
                        num:0,   //小圆转过的角度
                        //必须新建一个小圆的横纵坐标,否则小圆会飞出去。
                        X:400,   //小圆起始点横坐标
                        Y:150     //小圆起始点纵坐标
                    }

    计算运动后下一个圆心的坐标

     setInterval(function(){
                    for(var i=0;i<ball.length;i++){
                        ball[i].num++;         // 圆角度由0-360
                        ball[i].x=Math.sin(ball[i].num*Math.PI/180)*ball[i].r+ball[i].X;  //小圆横坐标
                        ball[i].y=ball[i].r-Math.cos(ball[i].num*Math.PI/180)*ball[i].r+ball[i].Y;//小圆的纵坐标
                    }
    {,1000/60)

    第五点:起始的圆沿曲线走起来

    然后 ball[i].x ball[i].y 附给新画的圆,因为在定时器内,所以就能形成1000/60ms变化一次圆心的效果,进而让圆运动,但是这个运动仅仅是围绕大圆运动的。要想再围绕内小圆运动,就应该再加一个if判断

      setInterval(function(){
                    for(var i=0;i<ball.length;i++){
                        ball[i].num++;         // 圆角度由0-360
                        if(ball[i].num==270){// 如果角度变为270度,改变ball的起始点坐标,就是改变它的轨迹。
                            ball[i].r=200;
                            ball[i].X=350;
                            ball[i].Y=200;
                        }
                        else if(ball[i].num==360+45+45
                        ){
                            confirm('你失败了!点击确定重来!');
                            window.location.reload()
                        }
                                  ball[i].x=Math.sin(ball[i].num*Math.PI/180)*ball[i].r+ball[i].X;  //小圆横坐标
                                  ball[i].y=ball[i].r-Math.cos(ball[i].num*Math.PI/180)*ball[i].r+ball[i].Y;//小圆的纵坐标
                    }
    },1000/60)

    当小圆走到270度时,把ball的起始点坐标改变,就能改变ball 的轨迹。当ball[i].num=450度时,也就是走到末尾圆,代表游戏结束。

    第六点:起始的圆沿曲线走起来,并在曲线初始位置处产生新圆。

     为了产生新的圆,只是开一个定时器,让每隔一段时间产生一个新的json

                var ball=[];
                setInterval(function(){
                    ball.push({
                        x:400,  //小圆起始点横坐标
                        y:150,  //小圆起始点纵坐标
                        r:250,   //大圆的半径
                        num:0,   //小圆转过的角度
                        //必须新建一个小圆的横纵坐标,否则小圆会飞出去。
                        X:400,   //小圆起始点横坐标
                        Y:150     //小圆起始点纵坐标
                    })
                },400);

    第七点:添加图片,这个图片是为了发射子弹

    var oimg= new Image();
            oimg.src='1.jpg' ;
            oimg.onload=function(){
         //让图片顺在中心转起来
                   var picX=(oC.width-oimg.offsetWidth)/2;
                    var picY=(oC.height-oimg.offsetHeight)/2;
                    oCG.save(); //为了不受定时器影响,sava起来
                    oCG.translate(picX,picY);
                    oCG.rotate(-iRotate);//里面的参数是为了控制让图片跟着鼠标旋转
                    oCG.translate(-30,-30);  //为了让图片沿着图片中心转动
                    oCG.drawImage(oimg,0,0);
    //                oCG.drawImage(oimg,(oC.width-oimg.offsetWidth)/2,(oC.height-oimg.offsetHeight)/2)
                    oCG.restore();
    },1000/60);

    8、让图片跟随鼠标动起来

    //让图片跟着鼠标转,原理就是求图片纵坐标与鼠标与图片中心的距离的夹角。把这个夹角附给
                //图片旋转的角度
                var iRotate=0;
                oC.onmousemove=function(ev){
                    oEvent=ev||event;
                    var a=oEvent.clientX-oC.offsetLeft-(oC.width-oimg.offsetWidth)/2;
                    var b=oEvent.clientY-oC.offsetTop-(oC.height-oimg.offsetHeight)/2;
                    iRotate=Math.atan(a/b);
                };

    四角星代表鼠标,角度为a与b的夹角,红色方块代表图片,把获取到角度赋给  ”oCG.rotate(-iRotate);//里面的参数是为了控制让图片跟着鼠标旋转”  

    第九点:让动起来的图片跟随鼠标的位置发送子弹,并让子弹的颜色变红

     

                //让图片吐子弹
                var Buttle=[];
                oC.onmousedown=function(ev){
                    oEvent=ev||event;
                    var a=oEvent.clientX-oC.offsetLeft-(oC.width-oimg.offsetWidth)/2;
                    var b=oEvent.clientY-oC.offsetTop-(oC.height-oimg.offsetHeight)/2;
                    var iSpeed=5;
                    var c=Math.sqrt(a*a+b*b); //鼠标距离图片中心的距离
                    var iSpeedX=iSpeed*a/c;  //横轴分得到的速度
                    var iSpeedY=iSpeed*b/c;  //纵轴分得到的速度
                    Buttle.push({
                        x:(oC.width-oimg.offsetWidth)/2,
                        y:(oC.height-oimg.offsetHeight)/2,
                        iSpeedX:iSpeedX,
                        iSpeedY:iSpeedY
                    })
                }
     //图片吐子弹的路径,获得吐到子弹终点的坐标
                    for(var i=0;i<Buttle.length;i++){
                        Buttle[i].x=Buttle[i].x+Buttle[i].iSpeedX; //子弹终点横坐标
                        Buttle[i].y=Buttle[i].y+Buttle[i].iSpeedY;  //子弹终点纵坐标
                    }
      for(var i=0;i<Buttle.length;i++){
                        oCG.save();
                        oCG.beginPath();
                        oCG.fillStyle='red';
                        oCG.moveTo(Buttle[i].x,Buttle[i].y);
                        oCG.arc(Buttle[i].x,Buttle[i].y,30,0,360*Math.PI/180,false);
                        oCG.fill();
                        oCG.restore();
                    }

    利用新的坐标Buttle[i].x和Buttle[i].y绘制一个圆。

    第10点:图片发射的子弹和轨迹上的小圆碰撞检测

     //构建碰撞检测函数
            function pz(x1,y1,x2,y2){
                var a=x1-x2;
                var b=y1-y2;
                var c=Math.sqrt(a*a+b*b);
                if(c<60){ //如果两圆心的距离小于60
                    return true
                }
                else{
                    return false
                }
    
            }

    第11点:碰撞检测后让发射的子弹和轨迹上的小圆消失

     for(var i=0;i<Buttle.length;i++){
                        for(var j=0;j<ball.length;j++){
                            if(pz(Buttle[i].x,Buttle[i].y,ball[j].x,ball[j].y)){
                                Buttle.splice(i,1);
                                ball.splice(j,1);
                                break;
                            }
                        }
                    }

    让子弹和轨迹上的小圆消失,让构建的两个json splice即可。

    注意,每次绘画的时候,要clearRect,设置在一个1000/60ms定时器内,静态的图形clear后再绘制依旧是静态的,但是动态生成的图形,在经过定时器后,绘制的是1000/60ms后的图形。图片的dragImage必须是在 onload事件下的,为了不影响图片加载,程序也是在onload事件下的。

    以上就是我对这道题的理解。因为时间仓促,里面难免有些语句有错误,恳请大家斧正。

    下面是程序的源代码。

        window.onload=function(){
            var oC=document.getElementById('canvas1');
            var oCG=oC.getContext('2d');
            //设置图形
            var oimg= new Image();
            oimg.src='1.jpg' ;
            oimg.onload=function(){
                //重新绘制实现动画效果,每次先清空上次一次绘画的,过一段时间,然后再画下一次绘画的,静态不变,东西改变,实现了动的效果
                setInterval(function(){
                    oCG.clearRect(0,0,oC.width,oC.height);
                    //外大圆
                    oCG.beginPath();
                    oCG.arc(400,400,250,-90*Math.PI/180,180*Math.PI/180,false);
                    oCG.stroke();
                    //内小圆
                    oCG.beginPath();
                    oCG.arc(350,400,200,180*Math.PI/180,0,false);
                    oCG.stroke();
                    //末尾圆
                    oCG.beginPath();
                    oCG.arc(550,400,30,0,360*Math.PI/180,false);
                    oCG.stroke();
                    //起始圆围绕曲线做圆周运动,把每一个已经动态变过的小圆的横纵坐标赋给新圆坐标,
                    // 达到到新位置1000/60ms,每350ms从原起点生成一个新的ball的效果
                    for(var i=0;i<ball.length;i++){
                        oCG.beginPath();
                        oCG.moveTo(400,150);
                        oCG.arc(ball[i].x,ball[i].y,30,0,360*Math.PI/180,false);
                        oCG.fill();
                    }
                    //设置字体
                    oCG.font="100px impact";
                    oCG.textBaseline='top';
                    oCG.fillText("hello",280,700);
                    //让图片顺在中心转起来
                   var picX=(oC.width-oimg.offsetWidth)/2;
                    var picY=(oC.height-oimg.offsetHeight)/2;
                    oCG.save(); //为了不受定时器影响,sava起来
                    oCG.translate(picX,picY);
                    oCG.rotate(-iRotate);
                    oCG.translate(-30,-30);  //为了让图片沿着图片中心转动
                    oCG.drawImage(oimg,0,0);
    //                oCG.drawImage(oimg,(oC.width-oimg.offsetWidth)/2,(oC.height-oimg.offsetHeight)/2)
                    oCG.restore();
                    //子弹
                    for(var i=0;i<Buttle.length;i++){
                        oCG.save();
                        oCG.beginPath();
                        oCG.fillStyle='red';
                        oCG.moveTo(Buttle[i].x,Buttle[i].y);
                        oCG.arc(Buttle[i].x,Buttle[i].y,30,0,360*Math.PI/180,false);
                        oCG.fill();
                        oCG.restore();
                    }
                },1000/60);
                //循环每一个ball,动态去改变每一个原心的坐标,
                setInterval(function(){
                    for(var i=0;i<ball.length;i++){
                        ball[i].num++;         // 圆角度由0-360
                        if(ball[i].num==270){// 如果角度变为270度,改变ball的起始点坐标,就是改变它的轨迹。
                            ball[i].r=200;
                            ball[i].X=350;
                            ball[i].Y=200;
                        }
                        else if(ball[i].num==360+45+45
                        ){
                            confirm('你失败了!点击确定重来!');
                            window.location.reload()
                        }
                        ball[i].x=Math.sin(ball[i].num*Math.PI/180)*ball[i].r+ball[i].X;  //小圆横坐标
                        ball[i].y=ball[i].r-Math.cos(ball[i].num*Math.PI/180)*ball[i].r+ball[i].Y;//小圆的纵坐标
                    }
                    //图片吐子弹的路径,获得吐到子弹终点的坐标
                    for(var i=0;i<Buttle.length;i++){
                        Buttle[i].x=Buttle[i].x+Buttle[i].iSpeedX; //子弹终点横坐标
                        Buttle[i].y=Buttle[i].y+Buttle[i].iSpeedY;  //子弹终点纵坐标
                    }
                    //碰撞检测
                    for(var i=0;i<Buttle.length;i++){
                        for(var j=0;j<ball.length;j++){
                            if(pz(Buttle[i].x,Buttle[i].y,ball[j].x,ball[j].y)){
                                Buttle.splice(i,1);
                                ball.splice(j,1);
                                break;
                            }
                        }
                    }
                },1000/60);
                //开定时器,每350ms添加一个ball
                var ball=[];
                setInterval(function(){
                    ball.push({
                        x:400,  //小圆起始点横坐标
                        y:150,  //小圆起始点纵坐标
                        r:250,   //大圆的半径
                        num:0,   //小圆转过的角度
                        //必须新建一个小圆的横纵坐标,否则小圆会飞出去。
                        X:400,   //小圆起始点横坐标
                        Y:150     //小圆起始点纵坐标
                    })
                },400);
                //让图片跟着鼠标转,原理就是求图片纵坐标与鼠标与图片中心的距离的夹角。把这个夹角附给
                //图片旋转的角度
                var iRotate=0;
                oC.onmousemove=function(ev){
                    oEvent=ev||event;
                    var a=oEvent.clientX-oC.offsetLeft-(oC.width-oimg.offsetWidth)/2;
                    var b=oEvent.clientY-oC.offsetTop-(oC.height-oimg.offsetHeight)/2;
                    iRotate=Math.atan(a/b);
                };
                //让图片吐子弹
                var Buttle=[];
                oC.onmousedown=function(ev){
                    oEvent=ev||event;
                    var a=oEvent.clientX-oC.offsetLeft-(oC.width-oimg.offsetWidth)/2;
                    var b=oEvent.clientY-oC.offsetTop-(oC.height-oimg.offsetHeight)/2;
                    var iSpeed=5;
                    var c=Math.sqrt(a*a+b*b); //鼠标距离图片中心的距离
                    var iSpeedX=iSpeed*a/c;  //横轴分得到的速度
                    var iSpeedY=iSpeed*b/c;  //纵轴分得到的速度
                    Buttle.push({
                        x:(oC.width-oimg.offsetWidth)/2,
                        y:(oC.height-oimg.offsetHeight)/2,
                        iSpeedX:iSpeedX,
                        iSpeedY:iSpeedY
                    })
                }
        };
            //构建碰撞检测函数
            function pz(x1,y1,x2,y2){
                var a=x1-x2;
                var b=y1-y2;
                var c=Math.sqrt(a*a+b*b);
                if(c<60){ //如果两圆心的距离小于60
                    return true
                }
                else{
                    return false
                }
    
            }
     }
  • 相关阅读:
    delphi编程来记录QQ的聊天记录
    delphi编程模拟发送QQ2008消息!
    C++学习 破冰之旅
    C++ 宏和预编译 预编译头
    C++头文件讲解
    EXTJS将树拖拽到PANEL,drag tree drop into panel 实例
    JS数组声明技巧、数组动态添加元素
    JS二维数组的定义
    EXTJS 按钮添加右键
    提高SQL执行效率的几点建议
  • 原文地址:https://www.cnblogs.com/dirkhe/p/6321738.html
Copyright © 2011-2022 走看看