Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/369.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
多维数组中对象的JavaScript冲突检测_Javascript_Arrays_Canvas_Collision_P5.js - Fatal编程技术网

多维数组中对象的JavaScript冲突检测

多维数组中对象的JavaScript冲突检测,javascript,arrays,canvas,collision,p5.js,Javascript,Arrays,Canvas,Collision,P5.js,我目前正在用p5.js编写一个吃豆人克隆,遇到了一个问题。我创建了一个函数,该函数使用多维数组绘制地图,在1处绘制墙块,在0处绘制空白 这很好,但是我很难检测到播放器和墙壁之间的碰撞。我尝试使用for循环遍历数组,检查x和y坐标以查看是否存在碰撞,但它根本没有注册。这是我用于检测碰撞的代码: for(i=0;i<walls.length;i++){ walls[i].draw(); if(player.x > walls[i].x && player.x <

我目前正在用p5.js编写一个吃豆人克隆,遇到了一个问题。我创建了一个函数,该函数使用多维数组绘制地图,在1处绘制墙块,在0处绘制空白

这很好,但是我很难检测到播放器和墙壁之间的碰撞。我尝试使用for循环遍历数组,检查x和y坐标以查看是否存在碰撞,但它根本没有注册。这是我用于检测碰撞的代码:

for(i=0;i<walls.length;i++){
walls[i].draw();

if(player.x > walls[i].x && player.x < walls[i].x + gridsize && player.y > walls[i].y && player.y < walls[i].y + gridsize){
  console.log('collision')

}
for(i=0;i walls[i].x&&player.xwalls[i].y&&player.y
}

我看不出这个问题在哪里,因为它似乎在其他项目中起了作用。 它在Draw()函数中运行,这意味着它每秒循环30次

这是完整的代码,以防问题出现在其他地方:

var gridsize = 20;
var walls = [];
var dots = [];
var player;
var score =0;
var maps = [[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
            [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
            [1,0,1,1,0,1,1,1,1,1,1,0,1,1,0,1],
            [1,0,1,1,0,0,0,0,0,0,0,0,1,1,0,1],
            [1,0,0,0,0,1,1,1,1,1,1,0,0,0,0,1],
            [1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1],
            [1,0,0,0,0,1,1,0,0,1,1,0,0,0,0,1],
            [1,0,1,0,0,1,0,0,0,0,1,0,0,1,0,1],
            [1,0,1,0,0,1,0,0,0,0,1,0,0,1,0,1],
            [1,0,1,0,0,1,1,1,1,1,1,0,0,1,0,1],
            [1,0,1,0,0,0,0,2,0,0,0,0,0,1,0,1],
            [1,0,1,1,1,0,1,1,1,1,0,1,1,1,0,1],
            [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
            [1,0,0,0,1,1,1,1,1,1,1,1,0,0,0,1],
            [1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
            [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]];
function setup(){
  createCanvas(320,320);
  frameRate(30);
  createMap();
}
function draw(){
  background(51);

  for(i=0;i<walls.length;i++){
    walls[i].draw();

    if(player.x > walls[i].x && player.x < walls[i].x + gridsize && player.y 
> walls[i].y && player.y < walls[i].y + gridsize){
      console.log('collision')

    }
  }
  fill('white');
  text('Score: ' + score, 5,10);
  for(i=0;i<dots.length;i++){
    if(player.x == dots[i].x && player.y == dots[i].y && dots[i].collect == 
false){
      dots[i].collect = true;
      score++;
    }
    dots[i].draw();

  }
  player.update();
  player.draw();

}


 function Block(x,y){
  this.x = x;
  this.y = y;

  this.draw = function(){
    fill('black');
    rect(this.x,this.y,gridsize,gridsize);
  }
}

function Dot(x,y){
  this.x = x;
  this.y = y;
  this.collect = false;
  this.draw = function(){
    if(!this.collect){
      fill('yellow');
      ellipse(this.x+gridsize/2,this.y+gridsize/2,gridsize/3,gridsize/3);
    }else if(this.collect){
      noFill();
      noStroke();
      ellipse(this.x+gridsize/2,this.y+gridsize/2,gridsize/3,gridsize/3);
    }
   }


}
function Player(x,y){
  this.x = x;
  this.y = y;

  this.update = function(){
    if(keyIsDown(UP_ARROW) && frameCount%5 == 0){
      player.y -= gridsize;
    }
    if(keyIsDown(DOWN_ARROW) && frameCount%5 == 0){
      player.y += gridsize;
    }
    if(keyIsDown(LEFT_ARROW) && frameCount%5 == 0){
      player.x -= gridsize;
    }
    if(keyIsDown(RIGHT_ARROW) && frameCount%5 == 0){
      player.x += gridsize;
    }
  }

  this.draw = function(){
    fill('blue');
    ellipse(this.x+gridsize/2,this.y+gridsize/2,gridsize/1.2,gridsize/1.2);
  }

}

function createMap(){
  for(i=0;i<maps.length;i++){
    for(j=0;j<maps[i].length;j++){
      if (maps[i][j] == 1){
        walls.push(new Block(j*gridsize,i*gridsize));
      }else if(maps[i][j] == 0){
        dots.push(new Dot(j*gridsize,i*gridsize))
      }else if(maps[i][j] = 2){
        player = new Player(j*gridsize,i*gridsize)
      }

    }
  }
}
var gridsize=20;
var墙壁=[];
var dots=[];
var播放器;
var得分=0;
var映射=[[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,1,1,0,1,1,1,1,1,1,0,1,1,0,1],
[1,0,1,1,0,0,0,0,0,0,0,0,1,1,0,1],
[1,0,0,0,0,1,1,1,1,1,1,0,0,0,0,1],
[1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1],
[1,0,0,0,0,1,1,0,0,1,1,0,0,0,0,1],
[1,0,1,0,0,1,0,0,0,0,1,0,0,1,0,1],
[1,0,1,0,0,1,0,0,0,0,1,0,0,1,0,1],
[1,0,1,0,0,1,1,1,1,1,1,0,0,1,0,1],
[1,0,1,0,0,0,0,2,0,0,0,0,0,1,0,1],
[1,0,1,1,1,0,1,1,1,1,0,1,1,1,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,0,0,0,1,1,1,1,1,1,1,1,0,0,0,1],
[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]];
函数设置(){
createCanvas(320320);
帧率(30);
createMap();
}
函数绘图(){
背景(51);
对于(i=0;i walls[i].x&&player.x墙[i].y&&player.y对于(i=0;i我不太清楚为什么要使用矩形碰撞检测,而您可以使用基于网格的碰撞检测。您可以直接使用数组

但由于您使用的是矩形-矩形碰撞,因此这条线看起来有点不对劲:

if(player.x > walls[i].x && player.x < walls[i].x + gridsize && player.y > walls[i].y && player.y < walls[i].y + gridsize){
if(player.x>walls[i].x&&player.xwalls[i].y&&player.y
您正在检查播放机的左边缘是否在墙内,以及播放机的上边缘是否在墙内。但您没有检测到其他边缘。通常您希望执行以下操作:

if(rectOneRight > rectTwoLeft && rectOneLeft < rectTwoRight && rectOneBottom > rectTwoTop && rectOneTop < rectTwoBottom){
if(recttonRight>recttonLeft&&recttonLeftrecttonTop&&recttonTop
注意这条
if
语句是如何检查所有边的,而不仅仅是顶部和左侧。但是正如我所说的,您最好只使用网格碰撞检测,因为您已经有了一个墙网格


无耻的自我提升:是一个关于碰撞检测的教程。它是为处理而编写的,但所有内容都应该直接转换为P5.js。

如果玩家不是这里的精灵,那么直接点碰撞检测在这里是合适的

  // point in rect collision detection
    function pointInRect (x, y, rect) {

              return inRange(x, rect.x, rect.x + gridsize) &&
                     inRange(y, rect.y, rect.y + gridsize);
    }
     // check a value is in range or not
    function inRange (value, min, max) {
              return value >= Math.min(min, max) && value <= Math.max(min, max);
    }

     // checking player is hitting the wall or not
     if(pointInRect(player.x,player.y,walls[i].x,walls[i].y))
     {
       console.log('collision')
     }
//直接碰撞检测中的点
函数pointInRect(x,y,rect){
返回范围(x,rect.x,rect.x+gridsize)&&
inRange(y,rect.y,rect.y+gridsize);
}
//检查值是否在范围内
范围内的函数(值、最小值、最大值){
返回值>=数学最小值(最小值、最大值)&值PacMan控件
检查这种类型地图的最佳方法是使用玩家的输入

玩家必须与墙壁对齐,因此假设玩家的位置相对于左上角,并且玩家的宽度和深度为一个地图单位

按键输入请求移动方向
dx
dy
保持一次可以超过一个的方向。如果
dx
dy
不为0,则首先检查播放机是否与通道对齐,如果是,则检查阻塞是否在行驶方向。如果播放机未对齐或阻塞,则设置移动变量为0

检查x和y方向后,如果
dx
dy
具有值,则该移动必须有效

代码更改 从主循环中删除播放器碰撞检查代码,并使用当前地图作为2D原始地图调用播放器更新函数

player.update(maps);  // move the player
更改播放器和更新功能

function Player(x,y){
  this.x = x;
  this.y = y;
  var dx = 0;  // hold current movement
  var dy = 0;
  const speed = 1; // per Frame pixel speed best as an integer (whole number) and evenly divisible into gridSize

  // need the map so that must be passed to the update function 
  this.update = function(map){

    // assuming keys are held to move up to stop
    dx = 0;  // stop by default
    dy = 0; 
    if (keyIsDown(UP_ARROW))   { dy = -speed }
    if (keyIsDown(DOWN_ARROW)) { dy = speed }
    if (keyIsDown(LEFT_ARROW)) { dx = -speed }
    if (keyIsDown(RIGHT_ARROW)){ dx = speed }

    // get player map coords
    var x = Math.floor(this.x / gridSize); // get map coord
    var y = Math.floor(this.y / gridSize); // get map coord
    // the two if statement are best aas function
    // so you can select which one to call first. Depending on the latest
    // new keys down and if the result allows movement in that
    // direction then set the other direction to zero.
    if (dy !== 0) { // is moving up or down?
        if (this.y % gridsize === 0) { // only if lined up
            if (dy > 0){ // is moving down
                 if (map[y + 1][x] === 1) { // down blocked 
                     dy = 0;
                 }
            }else if (map[y - 1][x] === 1) { // up blocked
                 dy = 0;
            }

        } else { // block move if not lined up with passage 
            dy = 0;
        }
    }
    if(dx !== 0){ // is moving left or right?
        if (this.x % gridsize === 0) { // only if lined up
            if (dx > 0) { // is moving right 
                 if (map[y][x + 1] === 1) { // right blocked 
                     dx = 0;
                 }
            } else if (map[y][x - 1] === 1) { // left blocked
                 dx = 0;
            }
        } else { // block move if not lined up with passage 
            dx = 0;
        }
     }
     // could have two moves, but can only move left right or up down
     // you need to add some input smarts to pick which one
     // this just favours up down
     if(dy !== 0) { dx = 0 };

     // only valid moves will come through the filter above.
     // so move the player.
     this.x += dx;
     this.y += dy;
  }
添加更多智能 注意:我改变了播放器的移动方式,我设置了每帧的速度(1像素),必须是
gridSize
的偶数除数

上面的代码是最简单的实现。这种类型的游戏需要一些额外的智能控制。你应该检查最新的向下键的方向。也就是说,如果按下向下和向右移动的玩家,则向右移动应该优先。如果按下向右和向左移动的玩家,则你应该向左移动,而不是一直向右移动。

额外费用 在看这个问题时,我想将映射可视化。作为数组的映射创建和修改非常困难,并且很难在其中发现错误。作为一组字符串,在运行时转换为数组要容易得多

正如我所做的转换一样,没有必要浪费它。
maps
与原始数组相同,但现在更易于阅读和更改

const maps = [
    "################",
    "#              #",
    "# ## ###### ## #",
    "# ##        ## #",
    "#    ######    #",
    "####        ####",
    "#    ##  ##    #",
    "# #  #    #  # #",
    "# #  #    #  # #",
    "# #  ######  # #",
    "# #    2     # #",
    "# ### #### ### #",
    "#              #",
    "#   ########   #",
    "#              #",
    "################"
].map(row => row.split("").map(c => c === "#" ? 1 : c === " " ? 0 : 2));

啊,是的,我记得以前犯过这个错误。我看了你的教程,试着使用网格,从来没有想过,尽管你现在说的很明显!干杯。哦,太好了,那么.map函数然后将其转换为多维数组?@corrigan_sam没有看到你的评论。我也添加了一个答案,稍微多了一点折叠的