画布中类似Arcanoid的游戏,碰撞检测

时间:2017-05-14 13:39:44

标签: canvas collision-detection

我试图用简单的类似arcanoid的游戏在球和砖之间做碰撞。

我不知道为什么但是当我输入代码进行碰撞时,球会完全消失并停止用画布绘制。谢谢你的帮助。 这是我的代码:

<html>
<body>
<canvas width="300" height="200" id="canvas">
</canvas>

<script>
    var i =5;
    var j = 16;
    var r = 5;
    var play ;
    var sz;
    var zmniejszony = 0;
    var poziom,pion;
    var pozX, pozY;
    var mozliwosc_wyboru_poziomu = 1;
    var canvas = document.getElementById('canvas');
    var c = canvas.getContext('2d');

    function Brick(x,y,width,height,color){
    this.x = x;
    this.y = y;
    this.width = width;
    this.height = height;
    this.color = color;
}   

 bricks = [
        new Brick(50,20,50,10,"blue"),
        new Brick(101,20,50,10,"blue"),
        new Brick(152,20,50,10,"blue"),
        new Brick(203,20,50,10,"gray"),
        new Brick(254,20,50,10,"blue"),
    ];

         function Poziomki()
         {
         var wybor = document.getElementById("poziomek").value;
         if(mozliwosc_wyboru_poziomu == 1){
         if (wybor==1){
         bricks = [
        new Brick(50,20,50,10,"blue"),
        new Brick(101,20,50,10,"blue"),
        new Brick(152,20,50,10,"blue"),
        new Brick(203,20,50,10,"gray"),
        new Brick(254,20,50,10,"blue"),
    ];
}

         if(wybor ==2){
             bricks = [
        new Brick(50,20,50,10,"blue"),
        new Brick(101,20,50,10,"blue"),
        new Brick(152,20,50,10,"blue"),
        new Brick(203,20,50,10,"gray"),
        new Brick(254,20,50,10,"blue"),

        new Brick(50,30,50,10,"red"),
        new Brick(101,30,50,10,"gray"),
        new Brick(152,30,50,10,"red"),
        new Brick(203,30,50,10,"red"),
        new Brick(254,30,50,10,"red"),
    ];
 }

         if(wybor ==3){
             bricks = [
         new Brick(50,20,50,10,"blue"),
        new Brick(101,20,50,10,"blue"),
        new Brick(152,20,50,10,"blue"),
        new Brick(203,20,50,10,"gray"),
        new Brick(254,20,50,10,"blue"),

        new Brick(50,30,50,10,"red"),
        new Brick(101,30,50,10,"gray"),
        new Brick(152,30,50,10,"red"),
        new Brick(203,30,50,10,"red"),
        new Brick(254,30,50,10,"red"),

        new Brick(50,40,50,10,"green"),
        new Brick(101,40,50,10,"green"),
        new Brick(152,40,50,10,"green"),
        new Brick(203,40,50,10,"green"),
        new Brick(254,40,50,10,"green"),
    ];
         }

         document.getElementById("wyb").innerHTML='Wybrano poziom: ' + wybor;
         }
         return
 }

    function blockrys(){
            for(var i = 0; i < bricks.length; i++){
c.save();
        c.fillStyle = bricks[i].color;
        c.fillRect(bricks[i].x,bricks[i].y,bricks[i].width,bricks[i].height);
        c.restore();
    }
    }

    function draw() {

             c.clearRect(0,0,300, 200);
           blockrys();

            // c.fillRect(i,j,10,10); 
            // if(zmniejszony==1){ c.fillRect(pozX-25,180,sz-5,10);zmniejszony = 0;}

        c.fillStyle = "pink";
    c.beginPath();
    c.arc(i,j,r,0,Math.PI*2);
    c.fill();

             c.fillRect(pozX-25,180,sz,10);
             //kierunek kulki
             if (poziom==1) i++;
             else i--;
             if (pion==1) j++;
             else j--;
             document.getElementById("X").innerHTML='X: ' + i;
            document.getElementById("Y").innerHTML='Y: ' + j;
             //wykrycie scian
             if (i==0) poziom=1; //ide w prawo, odbicie od lewej sciany
             if (i==300) poziom=-1; //ide w lewo, odbicie od prawej sciany
             if (j==0) pion=1; //ide w dol, odbicie od gornej sciany

             if (j==180 && (i>pozX-35 && i<pozX+35)){pion=-1;c.fillStyle="rgb(255,0,0)";}
             else {c.fillStyle="rgb(255,0,255)";}
            /////////////////////////////////////////////////////////////////////////

                var dx = Math.floor(Math.random()*4+4); 
                var dy = Math.floor(Math.random()*4+4);

                var ax1 = x-r;
    var ay1 = j-r;
    var ax2 = x+r;
    var ay2 = j+r;
    var bx1;
    var bx2;
    var bx2;
    var by2;
    for(var i = 0; i < bricks.length; i++){
        bx1 = bricks[i].x;
        by1 = bricks[i].y;
        bx2 = bricks[i].x+bricks[i].width;
        by2 = bricks[i].y+bricks[i].height;
        if(!(ax2 <= bx1 || bx2 <= ax1 || ay2 <= by1 || by2 <= ay1)){
            prevX = i - dx - r;
            prevY = j - dy - r;
            if((prevX > bx2 || prevX < bx1) && prevY >= by1 && prevY <= by2){
                dx = -dx;   
            } else {
                dy = -dy;
            }
            bricks.splice(i,1);

        }
    }

            if (j==200){ alert("Przegrales, nacisnij OK, by sprobowac ponownie (mozesz tez wybrac inny poziom)"); mozliwosc_wyboru_poziomu = 1;}//pion=-1;//ide do gory, odbicie od dolnej sciany


    }

    function play(){
        i=5;
        j=16;
        x=10;
        sz=50;
        zmniejszony = 0;
        mozliwosc_wyboru_poziomu = 0;
        pion=1;//lecim w dol
        poziom=1;//lecin w prawo
        setInterval('draw()',x);
    }

    function pozycjaMyszki(e) {
     pozX = 0;
     pozY = 0;
    if (!e) var e = window.event;
    if (e.pageX || e.pageY) {
         pozX = e.pageX;
         pozY = e.pageY;
    } else if (e.clientX || e.clientY) {
         pozX = e.clientX + document.body.scrollLeft;
         pozY = e.clientY + document.body.scrollTop;
    }
    document.getElementById("text").innerHTML='X: ' + pozX;
    document.getElementById("text2").innerHTML='Y: ' + pozY;
    return {pozX,pozY}
}


 document.onmousemove = function(e){
 pozycjaMyszki(e);
}
</script>
<br>
<button onClick="play()">Play/Reset</button><br>
Wybierz poziom przed rozpoczeciem gry! (od 1 do 3): <br>

<input id="poziomek" type="range" min="1" max="3" step="1" onchange="Poziomki()" value="1">  <p id="wyb"></p>
<br>
Kursor:<br>
<div id="text">pozycja</div>
<div id="text2">pozycja</div>
Kulka:<br>
<div id="X">pozycja</div>
<div id="Y">pozycja</div>
</body>
</html>

这里恰好是碰撞代码:

 var ax1 = x-r;
    var ay1 = j-r;
    var ax2 = x+r;
    var ay2 = j+r;
    var bx1;
    var bx2;
    var bx2;
    var by2;
    for(var i = 0; i < bricks.length; i++){
        bx1 = bricks[i].x;
        by1 = bricks[i].y;
        bx2 = bricks[i].x+bricks[i].width;
        by2 = bricks[i].y+bricks[i].height;
        if(!(ax2 <= bx1 || bx2 <= ax1 || ay2 <= by1 || by2 <= ay1)){
            prevX = i - dx - r;
            prevY = j - dy - r;
            if((prevX > bx2 || prevX < bx1) && prevY >= by1 && prevY <= by2){
                dx = -dx;   
            } else {
                dy = -dy;
            }
            bricks.splice(i,1);

        }
    }

1 个答案:

答案 0 :(得分:1)

您的问题是您使用全局变量 i 和范围。您声明全局 i

var i =5;

从我看到,这个全局非常重要,因为它用于渲染你的球,但是draw()函数中的以下循环使用i:

 for(var i = 0; i < bricks.length; i++)

这个循环正在压缩你的全局var i (以及阻塞函数)。

快速解决方法是使用let keyword远离全局范围:

for(let i = 0; i < bricks.length; i++)

但是我建议给你的全局 i var一个更有意义的名称并严格保留名称 i 以用作代码中的循环变量。

此处有a good SO Q/A article关于javascript范围,Here's a plunkr使用 let 补丁展示您的代码。