canvas 碰撞反弹

之前我们学习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
                };
            }
        }
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,530评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,403评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,120评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,770评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,758评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,649评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,021评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,675评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,931评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,751评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,410评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,004评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,969评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,042评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,493评论 2 343

推荐阅读更多精彩内容