ชนกับวัตถุ (ผนัง) [ซ้ำ]
Oct 27 2020
วิธีปฏิบัติที่ดีในการตรวจจับการชนกันของวัตถุ 2 ชิ้น (ผนัง) ใช่ไม่ใช่แค่การตรวจจับ แต่เป็นการกระจัดเพิ่มเติมเพื่อไม่ให้วัตถุเข้ามาหากัน นั่นคือเมื่อพวกเขาชนกันพวกเขาจะวางตัวต่อกัน แต่อย่าเข้าไป
รหัส
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]]
}
}
คำตอบ
2 codeanjero Oct 27 2020 at 16:10
วิธีการที่ไร้เดียงสาคือการตรวจสอบ x และ 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>
วิธีที่ดีกว่าคือการตัดโลก 2 มิติของคุณให้เป็นโซนที่ความหนาแน่นของวัตถุที่ชนกันได้นั้นมีความสำคัญมากหรือน้อย (ควอดทรี)
ดังนี้:
และวิธีที่ง่ายกว่าคือดูว่าวัตถุที่มีสีอยู่ในทรงกลมหรือไม่ (ซึ่งหมายความว่าผนังมีการชนกันของทรงกลมและแทบจะไม่สามารถแสดงเป็นสี่เหลี่ยมจัตุรัสได้) แต่เราสามารถพูดได้ว่าผู้เล่นเป็นทรงกลมและตรวจสอบว่ามีอะไร ได้เข้ามาในรัศมีของเขา
https://studiofreya.com/3d-math-and-physics/sphere-vs-aabb-collision-detection-test/