解决两个2D元素的碰撞

时间:2016-07-29 00:20:57

标签: javascript canvas collision-detection move

我试图让我的玩家在另一个玩家周围移动,在X轴上似乎没问题,但Y轴无法正常工作。就像我希望它检测“边界”一样,就好像它是一个块一样,我想阻止玩家与敌人重叠......

if ((87 in keysDown) && player.y > 0) {
  if ((player.x < player2.x -50 || player.x > player2.x+50))
    if( player.y < player2.y+50){
      player.y -= player.speed;
    }
}

1 个答案:

答案 0 :(得分:2)

2D无逃脱

阻止元素移动到地图/舞台之外

 // After new x and y are set:
 this.x = Math.min(Math.max(0,this.x), Stage.w-this.w);
 this.y = Math.min(Math.max(0,this.y), Stage.h-this.h);
 // Where `this` is the moving element and `Stage` is the game area.

2D碰撞检测

function collision(A, B) {
  return !(((A.y+A.h)<(B.y))||(A.y>(B.y+B.h))||((A.x+A.w)<B.x)||(A.x>(B.x+B.w)));
}

使用类似:

if( collision(Player,Enemy) ) {
   // explodePlayer(); // or whatever, they collided!
}

2D解决碰撞

如果您不想要被动碰撞检测,而是要解决移动玩家的碰撞:

function resolveCollision(A, B) {
    // get the vectors to check against
    var vX = (A.x + (A.w / 2))  - (B.x + (B.w / 2)),
        vY = (A.y + (A.h / 2)) - (B.y + (B.h / 2)),
        // Half widths and half heights of the objects
        ww2 = (A.w / 2) + (B.w / 2),
        hh2 = (A.h / 2) + (B.h / 2),
        colDir = "";

    // if the x and y vector are less than the half width or half height,
    // they we must be inside the object, causing a collision
    if (Math.abs(vX) < ww2 && Math.abs(vY) < hh2) {
        // figures out on which side we are colliding (top, bottom, left, or right)
        var oX = ww2 - Math.abs(vX),
            oY = hh2 - Math.abs(vY);
        if (oX >= oY) {
            if (vY > 0) {
                colDir = "TOP";
                A.y += oY;
            } else {
                colDir = "BOTTOM";
                A.y -= oY;
            }
        } else {
            if (vX > 0) {
                colDir = "LEFT";
                A.x += oX;
            } else {
                colDir = "RIGHT";
                A.x -= oX;
            }
        }
    }
    return colDir; // If you need info of the side that collided
}

使用类似:

resolveCollision(Player, Enemy);

或:

var res = resolveCollision(Player, Enemy);
console.log( res ); // "TOP", "BOTTOM"... (the side that collided uppercase)

行动中的示例:

// Collision boolean (useful for passive collision detection)
function collision(A, B) {
  return !(((A.y+A.h)<(B.y))||(A.y>(B.y+B.h))||((A.x+A.w)<B.x)||(A.x>(B.x+B.w)));
}

// Resolve collision
function resolveCollision(A, B) {
  // get the vectors to check against
  var vX = (A.x + (A.w / 2))  - (B.x + (B.w / 2)),
      vY = (A.y + (A.h / 2)) - (B.y + (B.h / 2)),
      // Half widths and half heights of the objects
      ww2 = (A.w / 2) + (B.w / 2),
      hh2 = (A.h / 2) + (B.h / 2),
      colDir = "";

  // if the x and y vector are less than the half width or half height,
  // they we must be inside the object, causing a collision
  if (Math.abs(vX) < ww2 && Math.abs(vY) < hh2) {
    // figures out on which side we are colliding (top, bottom, left, or right)
    var oX = ww2 - Math.abs(vX),
        oY = hh2 - Math.abs(vY);
    if (oX >= oY) {
      if (vY > 0) {
        colDir = "TOP";
        A.y += oY;
      } else {
        colDir = "BOTTOM";
        A.y -= oY;
      }
    } else {
      if (vX > 0) {
        colDir = "LEFT";
        A.x += oX;
      } else {
        colDir = "RIGHT";
        A.x -= oX;
      }
    }
  }
  return colDir;
}


// Elements
var cvs= document.createElement("canvas"),
    ctx= cvs.getContext("2d"),
    EL_collisionInfo = document.getElementById("collisionInfo");


// Game variables
var Stage = {
  w: 300,
  h: 200
},
    Keys = {},
    Player = {
      x: 0,
      y: 0,
      w: 30,
      h: 30,
      color: "blue",
      velocity: 4,
      move: function() {
        if(Keys[65]) { // A
          this.x -= this.velocity;
        } 
        if(Keys[87]) { // W
          this.y -= this.velocity; 
        }
        if(Keys[68]) { // D
          this.x += this.velocity;
        } 
        if(Keys[83]) { // S
          this.y += this.velocity; 
        }

        // General Collision / Touching
        var orgColor = "";
        if(collision(this, Enemy)) {
          this.color = "red";
        } else { // not colliding
          this.color = "blue";
        }

        // Resolve collision
        var coll = resolveCollision(this, Enemy);
        // And write info on screen
        EL_collisionInfo.innerHTML = coll;

        // Prevent go out of Stage
        this.x = Math.min(Math.max(0,this.x), Stage.w-this.w);
        this.y = Math.min(Math.max(0,this.y), Stage.h-this.h);
      }
    },
    Enemy = {
      x: 130,
      y: 80,
      w: 50,
      h: 50,
      color: "red"
    };


// INIT canvas and size
document.body.appendChild(cvs);
cvs.width = Stage.w;
cvs.height = Stage.h;


function canvasDraw( el ) {
  ctx.beginPath();
  ctx.fillStyle = el.color;
  ctx.fillRect(el.x, el.y, el.w, el.h);
}

// /////
// KEYBOARD LISTENERS
document.addEventListener("keydown", function(e){
  Keys[e.which] = 1;
}, false);
document.addEventListener("keyup", function(e){
  delete Keys[e.which];
}, false);


// /////
// ENGINE
(function engine() {

  Player.move();
  // Clear canvas and draw
  ctx.clearRect(0, 0, cvs.width, cvs.height);
  canvasDraw( Player );
  canvasDraw( Enemy );

  window.requestAnimationFrame( engine );
}());
*{box-sizing:border-box; -webkit-box-sizing:border-box;}
html, body{height:100%; margin:0; font:16px/20px sans-serif;}
canvas{background: #eee;}
#collisionInfo{position:absolute;}
WASD to move<br>
<p id="collisionInfo"></p>

相关问题