Javascript 如何在2D平铺游戏地图中检测碰撞

Javascript 如何在2D平铺游戏地图中检测碰撞,javascript,canvas,2d,tile,Javascript,Canvas,2d,Tile,我做了一个基本的游戏,我画了一张地图和一个玩家,玩家可以在任何地方移动,但是我怎么做才能使它在地图的瓷砖[1]上不会移动呢? 另外,当我试图检查player.x是否大于50时,它可能会向左移动,但如果我一次单击两个键,它就会通过 const context=document.querySelector(“canvas”).getContext(“2d”) var rgb='rgb('+Math.random()*256+'、'+Math.random()*256+'、'+Math.random(

我做了一个基本的游戏,我画了一张地图和一个玩家,玩家可以在任何地方移动,但是我怎么做才能使它在地图的瓷砖[1]上不会移动呢? 另外,当我试图检查player.x是否大于50时,它可能会向左移动,但如果我一次单击两个键,它就会通过 const context=document.querySelector(“canvas”).getContext(“2d”)

var rgb='rgb('+Math.random()*256+'、'+Math.random()*256+'、'+Math.random()*256+'、'+Math.random()++');
document.onload=Loop();
可变宽度=1500;
var高度=800;
函数循环(){
可变宽度=1500;
var高度=800;
context.canvas.height=高度;
context.canvas.width=宽度;
this.interval=setInterval(更新,1000/100);
}
常量播放器=函数(x、y、w、h、颜色){
这个.x=x;这个.y=y;这个.w=w;这个.h=h;
this.speedY=0;this.speedX=0;
this.Draw=function(){
context.fillStyle=this.color;
context.fillRect(this.x,this.y,this.w,this.h);
};
this.Move=function(){
this.x+=this.speedX;
this.y+=this.speedY;
};
};<代码>
var玩家=新玩家(100100,50,50,rgb);
var Key={};
函数更新(){
clearRect(0,0,宽度,高度);
Map();
player.Draw();
player.Move();
onkeydown=onkeyup=功能(e){
player.speedX=0;
player.speedY=0;
e=e | |事件;
Key[e.keyCode]=e.type=='keydown';
如果(键[37]| |键[65]){player.speedX-=2}
如果(键[38]| |键[87]){player.speedY-=2}
如果(键[39]| |键[68]){player.speedX+=2}
如果(键[40]| |键[83]){player.speedY+=2}
如果(键[32]){player.color='rgb('+Math.random()*256+','+Math.random()*256+','+Math.random()*256+','+Math.random()*1+');}
};
}
变量映射=[
1, 1, 1, 1, 1,
1, 0, 0, 0, 1,
1, 0, 0, 0, 1,
1, 0, 0, 0, 1,
1, 1, 1, 1, 1
];
var行=5;
var列=5;
函数映射(){
for(设y=-1;y
首先,查看您的代码,您缺少一些实现基本碰撞检测所需的功能,这些功能包括:

  • 玩家当前移动的方向。这一点很重要,因为它允许确定碰撞检测的功能区分检查碰撞的哪一侧(上、下、左或右),因为玩家一次只能与一侧碰撞

  • 瓷砖的位置和尺寸。这一点也非常重要,因为与第一点一样,玩家只能碰撞瓷砖的一面,知道大小和位置可以根据玩家的大小和位置确定是否发生碰撞

  • 另外,由于您提到这是一个基本的游戏,下面的实现是一个基本的碰撞检测。如果要制作更复杂、更大的游戏,您应该尝试查看四叉树以实现更高效的碰撞检测:

    现在,这是用于检测碰撞的函数,为了可读性和简洁性,p将表示播放器对象,t将表示平铺对象。此函数根据玩家的移动方向返回玩家是否与瓷砖发生碰撞

    function isColliding(p, t){
      if (p.direction == 'up') {
       return p.y +(p.height/2)-p.speedY< t.y + t.height && p.y > t.y
          && p.x + p.width > t.x && p.x < t.x + t.width;
      }
      if (p.direction == 'down') {
        return p.y + (p.height/2)+p.speedY > t.y && p.y < t.y
          && p.x + p.width > t.x && p.x < t.x + t.width;
      }
      if (p.direction == 'right') {
        return p.x + p.width+p.speedX > t.x && p.x < t.x
          && p.y +(p.height/2)> t.y && p.y + p.height < t.y +t.height+ (p.height / 2);
      }
      if (p.direction == 'left') {
        return p.x -p.speedX< t.x + t.width && p.x > t.x
          && p.y +(p.height/2)> t.y && p.y + p.height < t.y +t.height+ (p.height / 2);
      }
      return false;
    }
    
    另一个简单的例子是每当玩家移动时(用户按下向下键):

    这些只是如何实现检测的示例。您应该将其作为实现代码功能的参考,因为我并不是根据您发布的内容编写的

    PS.


    确保在用户停止按键后将方向转换为false

    首先,看看您的代码,有一些东西缺少,这是实现基本碰撞检测所必需的,它们是:

  • 玩家当前移动的方向。这一点很重要,因为它允许确定碰撞检测的功能区分检查碰撞的哪一侧(上、下、左或右),因为玩家一次只能与一侧碰撞

  • 瓷砖的位置和尺寸。这一点也非常重要,因为与第一点一样,玩家只能碰撞瓷砖的一面,知道大小和位置可以根据玩家的大小和位置确定是否发生碰撞

  • 另外,由于您提到这是一个基本的游戏,下面的实现是一个基本的碰撞检测。如果要制作更复杂、更大的游戏,您应该尝试查看四叉树以实现更高效的碰撞检测:

    现在,这是用于检测碰撞的函数,为了可读性和简洁性,p将表示播放器对象,t将表示平铺对象。此函数根据玩家的移动方向返回玩家是否与瓷砖发生碰撞

    function isColliding(p, t){
      if (p.direction == 'up') {
       return p.y +(p.height/2)-p.speedY< t.y + t.height && p.y > t.y
          && p.x + p.width > t.x && p.x < t.x + t.width;
      }
      if (p.direction == 'down') {
        return p.y + (p.height/2)+p.speedY > t.y && p.y < t.y
          && p.x + p.width > t.x && p.x < t.x + t.width;
      }
      if (p.direction == 'right') {
        return p.x + p.width+p.speedX > t.x && p.x < t.x
          && p.y +(p.height/2)> t.y && p.y + p.height < t.y +t.height+ (p.height / 2);
      }
      if (p.direction == 'left') {
        return p.x -p.speedX< t.x + t.width && p.x > t.x
          && p.y +(p.height/2)> t.y && p.y + p.height < t.y +t.height+ (p.height / 2);
      }
      return false;
    }
    
    另一个简单的例子是每当玩家移动时(用户按下向下键):

    这些只是如何实现检测的示例。您应该将其作为实现代码功能的参考,因为我并不是根据您发布的内容编写的

    PS.

    确保在用户停止按键后将方向转换为false

    
    身体{
    背景色:黑色;
    }
    帆布{
    显示:块;
    保证金:自动;
    边框:纯色1px白色;
    边界半径:10px;
    }
    剧本{
    显示:无;
    }
    空函数(){
    “严格使用”;
    //班级
    功能摄像机(x,y){
    这个.x=x | | 0.0;
    这个.y=y | | 0.0;
    }
    
    document.onkeydown = function(event){
        if (event.keyCode == 87)
            player.up = true;
        else if (event.keyCode == 65)
            player.left = true;
        else if (event.keyCode == 83)
            player.down = true;
        else if (event.keyCode == 68)
            player.right = true;
    }
    
    const Player= function(/*Param stuff*/){
      /*Property stuff*/
      //tileArray is the array (or object, your choice) of all the current tiles in the map
      this.move=function(tileArray){
        //Go through all tiles to see if player is colliding with any of them
        for(var t in tileArray){
          if(this.up){
            if(isColliding(this, tileArray[t]){
              //functionality for when player collides
            }else{
              //functionality for when player doesn't collide
            }
          }
          //check if player is going down, left, etc
        }
      }
    }