简体   繁体   中英

Ball-Box Collision Detection

 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){ na= -na; nx= wn.radius; } else if(nx-n.radius<0){ na= -na; nx= n.radius; } if(n.y+n.radius>h){ nb= -nb; ny= hn.radius; } else if(ny-n.radius<0){ nb= -nb; ny= n.radius; } } function checkCollisionPlayer(n,j){ if(overlap(nx,ny,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> 

I am getting error in my code as soon as the first collision takes place between the player(box) and the balls. The only part which is giving error is the splice() function. If I comment the splice() function then code is not showing any error. But if I use splice() function part in my code then it is showing error in the move function and I don't know why this is happening. Please help me…

This appears to be to do with the loop inside your move function. You call it with the parameter m representing the lengh of the ball array - but the function checkCollisionPlayer which is called within that can remove a ball from the array if there is a collision. This means that the array is now shorter, so whenever you try to access a property on ball[m-1] later in the loop, as you will, you'll get this error.

I'm sure there are lots of different ways to fix this. The easiest I can think of (which I have successfully used myself in making a browser game) is to, instead of directly deleting the balls from the array upon collision, set a property on them to mark them as "deleted". Then add a "cleanup" function onto the end of the loop to filter the array into only those that are not marked as deleted. This ensures that every object you are looping over actually exists, while still changing the length dynamically to reflect the game state.

 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){ na= -na; nx= wn.radius; } else if(nx-n.radius<0){ na= -na; nx= n.radius; } if(n.y+n.radius>h){ nb= -nb; ny= hn.radius; } else if(ny-n.radius<0){ nb= -nb; ny= n.radius; } } function checkCollisionPlayer(n,j){ if(overlap(nx,ny,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> 

If you pass the array as an argument in the move() function not the length of the array then your code will work perfectly.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM