Collisione con oggetti (muri) [duplicato]
Che buona pratica per rilevare la collisione di 2 oggetti (muri). Sì, non solo rilevamento, ma ulteriore spostamento in modo che gli oggetti non entrino tra loro. Cioè, in modo che quando si scontrano, si appoggiano l'uno contro l'altro, ma non entrano.
CODICE
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]]
}
}
Risposte
un approccio ingenuo sarebbe controllare x e y:
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 approccio migliore sarebbe tagliare il tuo mondo 2d in zone in cui la densità degli oggetti che possono entrare in collisione è più o meno importante (un quadtree).
così :
e un modo più semplice sarebbe guardare se l'oggetto freddo è in una sfera (ciò significherebbe che i muri hanno una collisione sferica e difficilmente potrebbero essere rappresentati come un quadrato) ma potremmo semplicemente dire che il giocatore è una sfera e controllare se qualcosa è entrato nel suo raggio.
https://studiofreya.com/3d-math-and-physics/sphere-vs-aabb-collision-detection-test/