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函数中显示错误,我不知道为什么会发生这种情况。请帮帮我…
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((函数中将数组作为参数而不是数组的长度传递,那么您的代码将完美工作。
这似乎与move
函数内的循环有关。调用它时,参数m
表示ball
数组的长度,但在其中调用的函数checkCollisionPlayer
可以在发生碰撞时从数组中移除球。这意味着数组现在更短了,所以无论何时在循环的稍后尝试访问ball[m-1]
上的属性,都会出现此错误。
我相信有很多不同的方法可以解决这个问题。我能想到的最简单的方法(我已经成功地将其用于制作浏览器游戏(是,不要在碰撞时直接从阵列中删除球,而是在球上设置一个属性,将其标记为"已删除"。然后在循环的末尾添加一个"cleanup"函数,将数组过滤为只包含那些未标记为已删除的数组。这样可以确保您循环的每个对象都确实存在,同时仍然动态更改长度以反映游戏状态。