canvas 碰撞反弹

作者: 放飞吧自我 | 来源:发表于2017-12-28 20:52 被阅读25次

    之前我们学习js的时候都写过碰撞反弹,canvas里的碰撞反弹也可以用同样的条件判断,现在我们回顾一下之前的判断

    外接矩形碰撞

    4C4433E2-72F6-49FD-8429-3A39A65B5945.png

    我们根据上面的判断来写一下效果

    var canvas = document.getElementById("mycanvas");
    var context = canvas.getContext("2d");
            
    

    运动方块的构造函数

            function Rect(x,y,w,h,color,speedx,speedy){
                this.x = x;
                this.y = y;
                this.w = w;
                this.h = h;
                this.color = color;
                this.speedx = speedx;
                this.speedy = speedy;
            }
            Rect.prototype.draw=function(){
                context.beginPath();
                context.fillStyle = this.color;
                context.fillRect(this.x,this.y,this.w,this.h);
            }
            Rect.prototype.move=function(){
                this.x +=this.speedx;
                this.y +=this.speedy;
                //碰壁检测
                if(this.x<0||this.x>canvas.width-this.w){
                    this.speedx *=-1;
                }
                if(this.y<0||this.y>canvas.height-this.h){
                    this.speedy *=-1;
                }
            }
    

    实例化方块,运动的函数

    方式一:通过判断方块位置
            var rect1 = new Rect(0,0,50,50,"green",1,3)
            var rect2 = new Rect(450,0,50,50,"red",2,4)
            function act1(){
                context.clearRect(0,0,canvas.width,canvas.height);
                rect1.draw();
                rect1.move();
                rect2.draw();
                rect2.move();
                //碰撞检测
                if((rect1.x+rect1.w)>rect2.x&&rect1.x<(rect2.x+rect2.w) && (rect1.y+rect1.h)>rect2.y&&rect1.y<(rect2.y+rect2.h)){
                    console.log(11111111111)
                    rect1.speedx *=-1;
                    rect1.speedy *=-1;
                    rect2.speedx *=-1;
                    rect2.speedy *=-1;
                }
                          window.requestAnimationFrame(act1);
            }
            act1()
    
    通过判断方块是否重叠
    var rect1 = new Rect(0,0,50,50,"green",1,3)
            var rect2 = new Rect(450,0,50,50,"red",2,4)
            function act1(){
                context.clearRect(0,0,canvas.width,canvas.height);
                rect1.draw();
                rect1.move();
                rect2.draw();
                rect2.move();
                //像素碰撞
                if(isCrash(rect1,rect2)){
                    console.log(22222222)
                    rect1.speedx *=-1;
                    rect1.speedy *=-1;
                    rect2.speedx *=-1;
                    rect2.speedy *=-1;
                };
                window.requestAnimationFrame(act1);
            }
            act1()
            
            function isCrash(rect1,rect2){
                var min1x = rect1.x;
                var max1x = rect1.x+rect1.w;
                var min2x = rect2.x;
                var max2x = rect2.x+rect2.w;
                
                var min1y = rect1.y;
                var max1y = rect1.y+rect1.h;
                var min2y = rect2.y;
                var max2y = rect2.y+rect2.h;
                
                //假设碰撞出新的方块
                var nminx = Math.max(min1x,min2x);
                var nmaxx = Math.min(max1x,max2x);
                
                var nminy = Math.max(min1y,min2y);
                var nmaxy = Math.min(max1y,max2y);
                
                if(nmaxx >nminx && nmaxy>nminy){
                    return true;
                }
            }
    

    外接圆碰撞

    480C32A5-3801-4BF2-B936-864601260910.png
    var canvas = document.getElementById("mycanvas");
            var context = canvas.getContext("2d");
            
            function Ball(x,y,r,color,speedx,speedy){
                this.x = x;
                this.y = y;
                this.r = r;
                this.color = color;
                this.speedx = speedx;
                this.speedy = speedy;
            }
            Ball.prototype.draw=function(){
                context.beginPath();
                context.fillStyle = this.color;
                context.arc(this.x,this.y,this.r,0,Math.PI*2);
                context.fill();
            }
            Ball.prototype.move=function(){
                this.x +=this.speedx;
                this.y +=this.speedy;
                //碰壁检测
                if(this.x<this.r||this.x>canvas.width-this.r){
                    this.speedx *=-1;
                }
                if(this.y<this.r||this.y>canvas.height-this.r){
                    this.speedy *=-1;
                }
            }
            var Ball1 = new Ball(50,50,25,"green",1,3)
            var Ball2 = new Ball(450,50,20,"red",2,4)
            function act1(){
                context.clearRect(0,0,canvas.width,canvas.height);
                Ball1.draw();
                Ball1.move();
                Ball2.draw();
                Ball2.move();
                
                //碰撞检测
                if(Math.pow(Ball1.x-Ball2.x,2)+Math.pow(Ball1.y-Ball2.y,2)<Math.pow(Ball1.r+Ball2.r,2)){
                    Ball1.speedx *=-1;
                    Ball1.speedy *=-1;
                    Ball2.speedx *=-1;
                    Ball2.speedy *=-1;
                }
                window.requestAnimationFrame(act1);
            }
            act1()
    

    最后显示:

    QQ20171228-204510-HD.gif

    像素碰撞

    F43640B5-94DF-49B0-89A5-3E7A2A8BA681.png

    还存在一种碰撞叫做像素的碰撞,虽然图像所在矩形碰撞,但是不代表图像之间发生碰撞;
    我们需要检测图像所在矩形是否相较,同时检测两图在相交矩形内的像素,存在一点在两个图上的 alpha 值不为 0,则发生碰撞。

    我们利用上面矩形碰撞的方式二来写像素碰撞,方式一我们不能得到重叠的矩形

    var canvas = document.getElementById("mycanvas");
            var context = canvas.getContext("2d");
            var img = new Image();
            img.src = "Chat.png";
            var play = new Image();
            play.src = "Play.png";
            img.onload = function(){
                context.beginPath();
                context.drawImage(img,100,100);
                var rect1 = new Rect(100,100,img.width,img.height);
                canvas.onmousedown = function(){
                    canvas.onmousemove = function(e){
                        var ev = e||window.event;
                        var x = ev.clientX-canvas.offsetLeft;
                        var y = ev.clientY-canvas.offsetTop;
                        context.clearRect(0,0,canvas.width,canvas.height);
                        context.drawImage(play,x,y)
    //                  context.drawImage(play,x-play.width/2,y-(play.height/2))
                        var rect2 = new Rect(x,y,play.width,play.height);
                        //实例化
                        context.drawImage(img,100,100);
                        var res = isCrash(rect1,rect2)
                        if(res.judge){
                            var newRect = res.rect;
                            //分别遍历碰撞区域的像素点
                            //清除某一区域的画布
                            context.clearRect(0,0,canvas.width,canvas.height)
                            //画蓝色图
                            context.drawImage(img,100,100);
                            //获取蓝图的像素点
                            var imgData1 = context.getImageData(res.rect.x,res.rect.y,res.rect.w,res.rect.h);
                            
                            context.clearRect(0,0,canvas.width,canvas.height)
                            //画绿色图
                            context.drawImage(play,x,y);
                            //获取绿色图的像素点
                            var imgData2 = context.getImageData(res.rect.x,res.rect.y,res.rect.w,res.rect.h);
                            context.drawImage(img,100,100);
                            for(var i=0;i<imgData1.data.length;i+=4){
                                if(imgData1.data[i+3]>0 && imgData2.data[i+3]>0){
                                    console.log("像素碰撞了")
                                    break;
                                }
                            }
                        };
                    }
                }
            }
            canvas.onmouseup =function (){
                canvas.onmousemove = null;
            }
            function Rect(x,y,w,h){
                this.x = x;
                this.y = y;
                this.w = w;
                this.h = h;
            }
            function isCrash(rect1,rect2){
                var min1x = rect1.x;
                var max1x = rect1.x+rect1.w;
                var min2x = rect2.x;
                var max2x = rect2.x+rect2.w;
                
                var min1y = rect1.y;
                var max1y = rect1.y+rect1.h;
                var min2y = rect2.y;
                var max2y = rect2.y+rect2.h;
                
                //假设碰撞出新的方块
                var nminx = Math.max(min1x,min2x);
                var nmaxx = Math.min(max1x,max2x);
                
                var nminy = Math.max(min1y,min2y);
                var nmaxy = Math.min(max1y,max2y);
                
                var obj = new Rect(nminx,nminy,(nmaxx-nminx),(nmaxy-nminy));
                
                if(nmaxx >nminx && nmaxy>nminy){
                    return {
                        judge:true,
                        rect:obj
                    };
                }else{
                    return {
                        judge:false
                    };
                }
            }
    

    相关文章

      网友评论

        本文标题:canvas 碰撞反弹

        本文链接:https://www.haomeiwen.com/subject/esnvgxtx.html