Chocando con objetos (paredes) [duplicado]

Oct 27 2020

Qué buena práctica para detectar la colisión de 2 objetos (paredes). Sí, no solo detección, sino mayor desplazamiento para que los objetos no entren entre sí. Es decir, para que cuando chocan, se apoyen entre sí, pero no entren.

CÓDIGO

class WallObj {
    constructor(obj) {//x, y, w, h, bern ,thru) {
        this.x = obj.x
        this.y = obj.y
        this.w = obj.w
        this.h = obj.h
        this.bern = obj.bern
        this.thru = obj.thru
        this.hide = obj.hide
        this.id = obj.id
    }

    collusionWall(startPosition, endPosition) {
        var xS = startPosition[0]
        var x = endPosition[0]

        if (xS - x > 0)
            if (x)
                // if wall behind point
                if (this.x < startPosition[0])
                    return endPosition
                else if (this.x + this.w < x)
                    return endPosition

        return endPosition

        // return [this.x, endPosition[1]]
    }

}

Respuestas

2 codeanjero Oct 27 2020 at 16:10

un enfoque ingenuo sería verificar xey:

let ctx = mycan.getContext("2d");
let objects = [];

class player 
{
  constructor()
  {
    this.position = {x:50,y:50};
   this.color = "blue";
    this.size = 32;
    this.stop= false;
    this.prevpos=this.position;
    window.addEventListener("keydown",(e)=>{
      if(this.stop) this.position=this.prevpos;
      else this.displacement(e);
    });
  }
  
   displacement(e)
   {
      this.prevpos = this.position;
      this.position.x+=(e.key=="ArrowRight");
      this.position.x-=(e.key=="ArrowLeft");
      this.position.y+=(e.key=="ArrowDown");
      this.position.y-=(e.key=="ArrowUp");
   }
  
  draw()
  {
    ctx.fillStyle = this.color;  ctx.fillRect(this.position.x,this.position.y,this.size,this.size);
  }
};

class wall
{
  constructor(posx,posy)
  {
   this.position = {x:posx,y:posy};
   this.color = "red";
   this.size = 32;
   }
   
   draw(){
    ctx.fillStyle = this.color;
    ctx.fillRect(this.position.x,this.position.y,this.size,this.size);
   }
};

for(let i = 0; i<mycan.width;i+=32)
{
  objects.push(new wall(i,0));
  objects.push(new wall(i,mycan.height-32));
}

for(let j = 0; j<mycan.height;j+=32)
{
  objects.push(new wall(0,j));
  objects.push(new wall(mycan.width-32,j));
}

let playr=new player;


let collision = (colider)=>{
let colx = false;
let coly = false;
/*******************************************************
here we check if the top left point from our current
wall object is inferior to the top left point of our
player and if the top rignt point of the wall object is
superior to the player top left point.
we need to repeat this for the player top right point 
(so we compare the player top right point is superior
to the wall top left point and inferior to the wall 
top right point)
then we repeat this for y
*******************************************************/
  for(let object of objects)
  {
    colx = (
    (
    (object.position.x<=colider.position.x) && 
    (
    (object.position.x+object.size)>=
    (colider.position.x)
    )
    )||(
 (
 (colider.position.x+colider.size)>=object.position.x) && 
 (
 (colider.position.x+object.size)<=(object.position.x+object.size)
 )
 )
 )
    coly = (
    (
    (object.position.y<=colider.position.y) && 
    (
    (object.position.y+object.size)>=
    (colider.position.y)
    )
    )||(
 (
 (colider.position.y+colider.size)>=object.position.y) && 
 (
 (colider.position.y+object.size)<=(object.position.y+object.size)
 )
 )
 )
 if(colx&&coly) return true;
  }
  return false;
};

setInterval(()=>{
  ctx.clearRect(0,0,mycan.width,mycan.height);
  playr.stop = collision(playr);
  playr.draw();
  for(let obj of objects)
    obj.draw();
},1000/30);
<canvas id="mycan" width=400 height=250></canvas>

Un mejor enfoque sería cortar su mundo 2d en zonas donde la densidad de los objetos que pueden colisionar es más o menos importante (un quadtree).

al igual que :

y una forma más fácil sería mirar si el objeto chocado está en una esfera (esto significaría que las paredes tienen una colisión esférica y difícilmente podrían representarse como un cuadrado) pero podríamos simplemente decir que el jugador es una esfera y verificar si algo ha entrado en su radio.

https://studiofreya.com/3d-math-and-physics/sphere-vs-aabb-collision-detection-test/