PHP前端开发

分享一个用html5实现炮弹自由落体的实例代码

百变鹏仔 3个月前 (10-18) #H5教程
文章标签 自由落体

html5仿大炮炮弹的自由落体实现

  html5的魅力相信大家不会陌生,希望各位大大浏览器们早点支持这个特性哦,,还有先吐槽一句,微信的那个broser简直弱爆了就简单的动画,比如滑动,就jquery的show(1000),hide(1000)都卡的不行,还是qq浏览器的内核,qq浏览器,,,算了,,我先冷静下。。。。

还有就是前几天看到的这个!!!


都不支持要他干嘛?????

回归主题大炮

整体思路就是将每个打出来的炮弹看做一个对象,他的x,y转换成canvas的x,y,其中vecior就是个控制力度的一个选项后文会提到。

var cannonBall = function (x,y,vector){        var gravity=0,        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);                ctx.fill();                ctx.closePath();                }             };

其中大炮炮弹的对象势必涉及到了向量计算,自己封装了个个方法,,有现成的Vector.js,但觉得太重(对于我们后端每次前端说不用模板,说太重,我们心里都默想重你妹呀,,哈哈哈),很简单,实现简单功能可以,大型游戏强烈建议使用现成的。

var vector2d= function (x,y){    var vec={        vx:x,        vy:y,        scale: function (scale){            vec.vx*=scale;            vec.vy*=scale;        },        add:function (vec2){            vec.vx+=vec2.vx;            vec.vy+=vec2.vy;        },        sub:function (vec2){            vec.vx-=vec2.vx;            vec.vy-=vec2.vy;        },        negate: function(){            vec.vx=-vec.vx;            vec.vy=-vec.vy;        },        length:function (){            return Math.sqrt(vec.vx * vec.vx + vec.vy * vec.vy);        },        normalize:function (){            var len=this.length();            if(len){                vec.vx /=len;                vec.vy /=len;            }            return len;        },        rotate:function (angle){            var vx = vec.vx;            var vy = vec.vy;            vec.vx = vx * Math.cos(angle) - vy * Math.sin(angle)            vec.vy = vx * Math.sin(angle) + vy * Math.cos(angle);        },        toString:function(){            return '(' + vec.vx.toFixed(3) + ',' + vec.vy.toFixed(3) + ')' ;        }    };    return vec;};

好了,接着就是个计算角度再加上setInterval了,,其他没啥说的,这里我着重说下canvas.save();和canvas.restore();这里稍微解释一下,
当我们对画布进行旋转,缩放,平移等操作的时候其实我们是想对特定的元素进行操作,比如图片,一个矩形等,但是当你用canvas的方法来进行这些操作的时候,其实是对整个画布进行了操作,那么之后在画布上的元素都会受到影响,所以我们在操作之前调用canvas.save()来保存画布当前的状态,当操作之后取出之前保存过的状态,这样就不会对其他的元素进行影响

立即学习“前端免费学习笔记(深入)”;

全部代码

<!doctype html><html lang="en"><head>    <meta charset="UTF-8">    <meta author=&#39;gongbangwei&#39;>    <title>大炮</title></head><body>    <p id=&#39;lidu&#39;>        <span>选择大炮的</span>        <input type="radio" checked=&#39;checked&#39; value=&#39;25&#39;>大        <input type="radio"  value=&#39;20&#39;>中        <input type="radio"  value=&#39;15&#39;>小    </p>    <canvas id=&#39;can&#39; width="640" height="480" style=" border:2px solid">no support html5</canvas>    <script src=&#39;vector2d.js&#39;></script>    <script src=&#39;jquery/jquery-1.7.2.min.js&#39;></script>    <script>    var gameObj=[],    canvas=document.getElementById(&#39;can&#39;),    ctx=canvas.getContext(&#39;2d&#39;);    var cannonBall = function (x,y,vector){        var gravity=0,        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,8,0,Math.PI * 2);                ctx.fill();                ctx.closePath();                }             };        return that;    }    var cannon= function (x,y,lidu){        var mx=0,        my=0,        angle=0,        that={            x: x,            y: y,            lidu:lidu,            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);                //平移,将画布的坐标原点向左右方向移动x,向上下方向移动y.canvas的默认位置是在(0,0)                ctx.rotate(angle);                //画布旋转                ctx.strokeRect(0,-5,50,10);                ctx.moveTo(0,0);                ctx.beginPath();                ctx.arc(0,0,15,0,Math.PI * 2 );                ctx.fill();                ctx.closePath();                ctx.restore();            }        };//end that        canvas.onmousedown = function(){            //在这里调用向量的那个js            var vec = vector2d(mx-that.x,my-that.y);            vec.normalize();            //console.log(lidu);            vec.scale(lidu);            gameObj.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,&#39;#00BFFF&#39;);        linGrad.addColorStop(0.5,&#39;white&#39;);        linGrad.addColorStop(0.5,&#39;#55dd00&#39;);        linGrad.addColorStop(1,&#39;white&#39;);        ctx.fillStyle=linGrad;        ctx.fillRect(0,0,canvas.width, canvas.height);        ctx.restore();    }    ///////main/////////////    var lidu=$(&#39;#lidu&#39;).find("input:checked").val();    gameObj.push(cannon(50,canvas.height-150,lidu));    $(&#39;#lidu&#39;).click(function (event){        var cl=event.target;        $(this).find(&#39;input&#39;).each(function(){            $(this).attr(&#39;checked&#39;,false)        });        $(cl).attr(&#39;checked&#39;,true);        lidu=$(cl).val();        gameObj.splice(0,gameObj.length);        gameObj.push(cannon(50,canvas.height-150,lidu));    })    setInterval( function (){        drawSkyAndGrass();        var gameObj_fresh=[];        for (var i = 0; i < gameObj.length; i++) {            gameObj[i].move();            gameObj[i].draw();            if(gameObj[i].removeMe === false){                gameObj_fresh.push(gameObj[i]);            }        }        gameObj=gameObj_fresh;    },50);    </script></body></html>

结束语

一个真正的前端绝不是ui,一个前端游戏工程师也绝对是个数学家。