我正在制作一个Atari Breakout克隆&我想知道如何判断球是否击中了一个区块的某一侧

时间:2017-10-23 15:53:51

标签: javascript html arrays canvas

我已经得到了当球与挡块碰撞的部分,它会删除挡块,但我也想知道球是否击中挡块的顶部或底部或左侧或右侧并相应地反弹。我试过了,但它的工作做得不对。它只是吓坏了跳来跳去。我已从下面的代码中删除了该部分,因为它不起作用。任何人都可以帮我解决这个问题吗?也许举个例子或者告诉我它是如何起作用的?

<canvas id="can" height="500" width="1000"></canvas>


        var c = document.getElementById("can");
        var ctx = c.getContext("2d");
        var blocks= [];
        var paddle = {x:450,y:480,h:10,w:100};
        var ball = {r:7,x:500,y:469};
        var rows=[0,1,2,3,4];
        var px = paddle.x, py = paddle.y;
        var pxv=0;
        var by = ball.y, bx = ball.x;
        var bxv = -1.5, byv = -1.5;


        function Block(h,w,x,y,c) {
            this.h = h;
            this.w = w;
            this.x = x;
            this.y = y;
            this.c = c;
        }
        for(var i =0, len=rows.length;i<len;i++){
            for(var j=0; j<20;j++) {
            blocks.push(new Block(20,50,j*50,i*20,rows[i]))
        }
        }
        document.addEventListener("keydown",keyPush);
        document.addEventListener("keyup",keyRelease);
        function keyRelease(evt) {
            switch(evt.keyCode) {
                case 37: 
                    pxv=0;
                    break;
                case 39: 
                    pxv=0;
                    break;
            }
        }
        function keyPush(evt) {
            switch(evt.keyCode) {
                case 37: 
                    pxv=-5;
                    break;
                case 39: 
                    pxv=5
                    break;
            }
        }
        function AABBIntersect(ax, ay, aw, ah, bx, by, bw, bh) {
            return ax < bx+bw && bx < ax+aw && ay < by+bh && by < ay+ah;
        };
        function draw(){
        ctx.clearRect(0,0,1000,500)
        bx+=bxv;
        by+=byv;
        px+=pxv;

        if(px > 900) {
            px = 900;
        }
        else if(px < 0) {
            px = 0;
        }
        for(var i = 0, len=blocks.length;i<len;i++) {
            var bl = blocks[i];
            if(AABBIntersect(bx,by,ball.r,ball.r,bl.x,bl.y,bl.w,bl.h)) {
                blocks.splice(i,1);
                i--;
                len--;
            }
        }
        if(bx < 0) {
            bxv = bxv*-1;
        }
        if(bx > 1000) {
            bxv = bxv*-1;
        }
        ctx.fillStyle = "#ff4b38"
        ctx.fillRect(px,py,paddle.w,paddle.h);
        for(var i = 0, len=blocks.length; i<len; i++){

                if(blocks[i].c === 0) {
                    ctx.fillStyle = "#ff4b38"
                }
                else if(blocks[i].c === 1) {
                    ctx.fillStyle = "#ffba19"
                }
                else if(blocks[i].c === 2) {
                    ctx.fillStyle = "#fcee25"
                }
                else if(blocks[i].c === 3) {
                    ctx.fillStyle = "#26db02"
                }
                else if(blocks[i].c === 4) {
                    ctx.fillStyle = "#2d69ff"
                }
                  ctx.fillRect(blocks[i].x,blocks[i].y,blocks[i].w,blocks[i].h);
                  ctx.beginPath();
                  ctx.arc(bx,by,ball.r,0,2*Math.PI,false);
                  ctx.fillStyle = "gray";
                  ctx.fill();

        }
        }
        setInterval(draw,10);

1 个答案:

答案 0 :(得分:1)

我确信有更多方法可以做到,但这就是我要做的。

在碰撞检测功能中,您应该使用if语句来检测是从x侧还是在y侧。你需要调整它,因为不确定它是否会在以后发生错误,但所有这一切都是这样的:

function AABBIntersect(ax, ay, aw, ah, bx, by, bw, bh) {
    var bool = ax < bx + bw && bx < ax + aw && ay < by + bh && by < ay + ah;
    if(bool){
        if(ax == bx || ax == bx + bw){
            bxv *= -1;
            cl("x");
        }else{
            byv *= -1;
            cl("y");
        }
    }   

    return bool;
};

你的下一个问题是没有桨式碰撞检测,所以它会反弹,但它会通过你的桨。因此,您可以在draw()函数中执行以下操作。我把它放在你的if(bx > 1000)

之后
if(bx >= px && bx <= px + paddle.w && by >= py && by <= py + paddle.h){
    byv *= -1;
}

我还会将你的setInterval放在一个var上,这样你就可以在所有的棋子都消失或你的球落到球拍下方时清除它。否则它就会无限地到处走。