球盒碰撞检测

时间:2018-10-30 10:33:35

标签: javascript html collision-detection game-development

var canvas,cxt,h,w,mousePos;
var player= {
    x: 10,
    y: 10,
    height: 20,
    width: 20,
    color: 'black'
};

function init(){
    canvas= document.querySelector('#style');
    cxt= canvas.getContext('2d');
    h= canvas.height;
    w= canvas.width;
    createBalls(10);
    main();
}

function createBalls(c){
    ball= [];
    var i;
    for(i=0;i<c;i++){
        var k= {
            x: h/2,
            y: w/2,
            color: colorGenerate(),
            radius: 5+Math.round(30*Math.random()), 
            a: -5+Math.round(10*Math.random()),
            b: -5+Math.round(10*Math.random())
        }
        ball.push(k);
    }
}

function main(){
    cxt.clearRect(0,0,h,w);
    canvas.addEventListener('mousemove',function(evt){
        mousePos= getMousePos(canvas,evt);
    });
    createPlayer();
    draw(ball.length);
    ballAlive();
    move(ball.length);
    movePlayer();
    requestAnimationFrame(main);
}

function ballAlive(){
    cxt.save();
    cxt.font="30px Arial";
    if(ball.length==0) cxt.fillText("You Win",20,20);
    else cxt.fillText(ball.length,20,40);
    cxt.restore();
}

function getMousePos(canvas,evt){
    var rect= canvas.getBoundingClientRect();
    return{
        x: evt.clientX-rect.left,
        y: evt.clientY-rect.top
    }
}

function createPlayer(){
    cxt.save();
    cxt.translate(0,0);
    cxt.fillStyle= player.color;
    cxt.fillRect(player.x,player.y,player.height,player.width);
    cxt.restore();
}

function movePlayer(){
    if(mousePos !== undefined){
        player.x= mousePos.x;
        player.y= mousePos.y;
    }
}

function draw(d){
    var i;
    for(i=0;i<d;i++){
        cxt.save();
        cxt.translate(0,0);
        cxt.beginPath();
        cxt.fillStyle= ball[i].color;
        cxt.arc(ball[i].x,ball[i].y,ball[i].radius,0,2*Math.PI)
        cxt.fill();
        cxt.restore();
    }
}

function move(m){
    var i;
    for(i=0;i<m;i++){
        ball[i].x+= ball[i].a;
        ball[i].y+= ball[i].b;
        checkCollision(ball[i]);
        checkCollisionPlayer(ball[i],i);
    }
}

function checkCollision(n){
    if(n.x+n.radius>w){
        n.a= -n.a;
        n.x= w-n.radius;
    }
    else if(n.x-n.radius<0){
        n.a= -n.a;
        n.x= n.radius;
    }
    if(n.y+n.radius>h){
        n.b= -n.b;
        n.y= h-n.radius;
    }
    else if(n.y-n.radius<0){
        n.b= -n.b;
        n.y= n.radius;
    }
}

function checkCollisionPlayer(n,j){
    if(overlap(n.x,n.y,n.radius,player.x,player.y,player.height,player.width)){
        ball.splice(j,1);
    }
}

function overlap(cx,cy,r,px,py,ph,pw){
    var testX= cx;
    var testY= cy;
// THESE LINES ARE FOR MOVING THE BALLS TOWARDS THE PLAYER
    if(testX<px) testX=px;
    if(testX>(px+pw)) testX=px+pw;
    if(testY<py) testy=py;
    if(testY>(py+ph)) testY=py+ph;

    //DISTANCE FORMULA FOR CHECKING THE OVERLAPING BETWEEN THE BOX AND CIRCLE
    return((cx-px)*(cx-px)+(cy-py)*(cy-py)<r*r);
}

function colorGenerate(){
    var col= ['green','blue','pink','red','brown','yellow','black','orange','grey','golden'];
    var i= Math.round((col.length-1)*Math.random());  //RETURN VALUES FROM 0 TO 9
    return col[i];
}
 #style{
    border: 4px dotted green;
 }
<!DOCTYPE html>
<html lang= 'en-us'>
    <head>
        <title>Feed The Monster</title>
 
    </head>
    <body onload= 'init();'>
        <canvas id= 'style' height= '400' width= '400'>
            Your browser does not support canvas...
        </canvas>
    </body>
</html>

在玩家(盒子)和球之间发生第一次碰撞后,我的代码中出现错误。 唯一会出错的部分是splice()函数。如果我评论splice()函数,则代码未显示任何错误。 但是,如果我在代码中使用splice()函数部分,那么它将在move函数中显示错误,并且我不知道为什么会这样。 请帮助我...

2 个答案:

答案 0 :(得分:0)

这似乎与move函数内部的循环有关。您可以使用表示m数组长度的参数ball来调用它-但是调用的函数checkCollisionPlayer可以在发生冲突时从数组中删除一个球。这意味着该数组现在更短了,因此,每当您稍后在循环中尝试访问ball[m-1]上的属性时,都会出现此错误。

我敢肯定有很多不同的方法可以解决此问题。我能想到的最简单的方法(是我成功地用自己制作了一个浏览器游戏)是,而不是在碰撞时直接从阵列中删除这些球,而是在它们上设置一个属性以将其标记为“已删除”。然后在循环的末尾添加一个“清理”函数,以将数组过滤为仅那些未标记为已删除的数组。这样可以确保您要遍历的每个对象都确实存在,同时仍可以动态更改长度以反映游戏状态。

答案 1 :(得分:0)

var canvas,cxt,h,w,mousePos;
var player= {
    x: 10,
    y: 10,
    height: 20,
    width: 20,
    color: 'black'
};

function init(){
    canvas= document.querySelector('#style');
    cxt= canvas.getContext('2d');
    h= canvas.height;
    w= canvas.width;
    createBalls(10);
    main();
}

function createBalls(c){
    ball= [];
    var i;
    for(i=0;i<c;i++){
        var k= {
            x: h/2,
            y: w/2,
            color: colorGenerate(),
            radius: 5+Math.round(30*Math.random()), 
            a: -5+Math.round(10*Math.random()),
            b: -5+Math.round(10*Math.random())
        }
        ball.push(k);
    }
}

function main(){
    cxt.clearRect(0,0,h,w);
    canvas.addEventListener('mousemove',function(evt){
        mousePos= getMousePos(canvas,evt);
    });
    createPlayer();
    draw(ball.length);
    ballAlive();
    move(ball);
    movePlayer();
    requestAnimationFrame(main);
}

function ballAlive(){
    cxt.save();
    cxt.font="30px Arial";
    if(ball.length==0) cxt.fillText("You Win",20,20);
    else cxt.fillText(ball.length,20,40);
    cxt.restore();
}

function getMousePos(canvas,evt){
    var rect= canvas.getBoundingClientRect();
    return{
        x: evt.clientX-rect.left,
        y: evt.clientY-rect.top
    }
}

function createPlayer(){
    cxt.save();
    cxt.translate(0,0);
    cxt.fillStyle= player.color;
    cxt.fillRect(player.x,player.y,player.height,player.width);
    cxt.restore();
}

function movePlayer(){
    if(mousePos !== undefined){
        player.x= mousePos.x;
        player.y= mousePos.y;
    }
}

function draw(d){
    var i;
    for(i=0;i<d;i++){
        cxt.save();
        cxt.translate(0,0);
        cxt.beginPath();
        cxt.fillStyle= ball[i].color;
        cxt.arc(ball[i].x,ball[i].y,ball[i].radius,0,2*Math.PI)
        cxt.fill();
        cxt.restore();
    }
}

function move(m){
    var i;
    for(i=0;i<m.length;i++){
        ball[i].x+= ball[i].a;
        ball[i].y+= ball[i].b;
        checkCollision(ball[i]);
        checkCollisionPlayer(ball[i],i);
    }
}

function checkCollision(n){
    if(n.x+n.radius>w){
        n.a= -n.a;
        n.x= w-n.radius;
    }
    else if(n.x-n.radius<0){
        n.a= -n.a;
        n.x= n.radius;
    }
    if(n.y+n.radius>h){
        n.b= -n.b;
        n.y= h-n.radius;
    }
    else if(n.y-n.radius<0){
        n.b= -n.b;
        n.y= n.radius;
    }
}

function checkCollisionPlayer(n,j){
    if(overlap(n.x,n.y,n.radius,player.x,player.y,player.height,player.width)){
        ball.splice(j,1);
    }
}

function overlap(cx,cy,r,px,py,ph,pw){
    var testX= cx;
    var testY= cy;
// THESE LINES ARE FOR MOVING THE BALLS TOWARDS THE PLAYER
    if(testX<px) testX=px;
    if(testX>(px+pw)) testX=px+pw;
    if(testY<py) testy=py;
    if(testY>(py+ph)) testY=py+ph;

    //DISTANCE FORMULA FOR CHECKING THE OVERLAPING BETWEEN THE BOX AND CIRCLE
    return((cx-px)*(cx-px)+(cy-py)*(cy-py)<r*r);
}

function colorGenerate(){
    var col= ['green','blue','pink','red','brown','yellow','black','orange','grey','golden'];
    var i= Math.round((col.length-1)*Math.random());  //RETURN VALUES FROM 0 TO 9
    return col[i];
}
#style{
        border: 4px dotted green;
 }
<!DOCTYPE html>
<html lang= 'en-us'>
    <head>
        <title>Feed The Monster</title>
 
    </head>
    <body onload= 'init();'>
        <canvas id= 'style' height= '400' width= '400'>
            Your browser does not support canvas...
        </canvas>
    </body>
    </html>

如果将数组作为参数传递给move()函数,而不是数组的长度,则您的代码将正常运行。