二维正方形到矩形碰撞检测和动作(物理学)



所以我用这种方式来检测移动和触摸其他方块的方块并对其做出反应。它使用勾股定理来生成第三个参数,这样当正方形接触时,就不会得到两个true if语句。我最近一直试图在正方形到矩形上使用这种方法,但似乎无法实现。我画了一些线来帮助可视化代码正在做的事情。有人对如何使碰撞正常工作有什么建议吗?

const canvas = document.getElementById('canvas');
const context = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
let gravity = 1.5;
let friction = 0.9;
//CHARACTER:
class Player {
constructor(x, y, w, h, vx, vy, c, j) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.vx = vx;
this.vy = vy;
this.color = c;
this.jumping = j;
}
draw() {
context.fillStyle = this.color;
context.fillRect(this.x, this.y, this.w, this.h);
}
canvasCollision() {
if (this.x <= 0) this.x = 0;
if (this.y <= 0) this.y = 0;
if (this.x + this.w >= canvas.width) this.x = canvas.width - this.w;
if (this.y + this.h >= canvas.height) {this.y = canvas.height - this.h; this.vy = 0; this.jumping = false};
}
update() {
this.draw(); 
this.vy += gravity;
this.x += this.vx;
this.y += this.vy;
this.vx *= friction;
this.vy *= friction;
this.canvasCollision() //must be after other updates
}
}
let player1 = new Player(75, canvas.height/2 + 75, 75, 75, 0, 0, '#8DAA9D', false); 
function controlPlayer1(obj) {
//this order matters. If update is before jump then obj won't jump when on top of other block.
if (controller1.up1 && !obj.jumping) { obj.vy -= 25; obj.jumping = true };
if (controller1.left1) { obj.vx -= 0.5 };
if (controller1.right1) { obj.vx += 0.5 };
obj.update();
}
//MOVEMENT:
class Controller {
constructor() {
this.left1  = false;
this.up1    = false;
this.right1 = false;
this.down1  = false;
let controller1 = (e) => {
if (e.code === 'KeyD')   { this.right1 = e.type === 'keydown' }
if (e.code === 'KeyA')   { this.left1 = e.type === 'keydown' }
if (e.code === 'KeyW')   { this.up1 = e.type === 'keydown' }    
if (e.code === 'KeyS')  { this.down1 = e.type === 'keydown' }       
}

window.addEventListener('keydown', controller1);
window.addEventListener('keyup', controller1);
}
}
let controller1 = new Controller();
//PLATFORM
class Platform {
constructor(x, y, w, h, yv, c) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.yv = yv;
this.color = c;
}
draw(){
context.fillStyle = this.color;
context.fillRect(this.x, this.y, this.w, this.h);
}
update(){
this.draw();
this.y += this.yv;
this.yv *= 0.9;// friction
}
}
let platform1 = new Platform(canvas.width/2, canvas.height - 150, 100, 30, 0, '#202020');
let platform2 = new Platform (canvas.width/4, canvas.height/2, 75, 75, 0, '#202020');
//COLLISION DETECTION
function platformDetection(obj, obj2){
//center point of each side of obj1
let objLeft = {x: obj.x,  y: obj.y + obj.h/2};
let objTop = {x: obj.x + obj.w/2, y: obj.y};
let objRight = {x: obj.x + obj.w, y: obj.y + obj.h/2};
let objBottom = {x: obj.x + obj.w/2, y: obj.y + obj.h};
//center point of each side a obj2
let obj2Left = {x: obj2.x, y: obj2.y + obj2.h/2};
let obj2Top = {x: obj2.x + obj2.w/2, y: obj2.y};
let obj2Right = {x: obj2.x + obj2.w, y: obj2.y + obj2.h/2};
let obj2Bottom = {x: obj2.x + obj2.w/2, y: obj2.y + obj2.h};
//distance between obj1 and obj2 opposing sides
let rightDistX = objRight.x - obj2Left.x;
let rightDistY = objRight.y - obj2Left.y;
let leftDistX = objLeft.x - obj2Right.x;
let leftDistY = objLeft.y - obj2Right.y;
let topDistX =  objTop.x - obj2Bottom.x;
let topDistY = objTop.y - obj2Bottom.y;
let bottomDistX = objBottom.x - obj2Top.x;
let bottomDistY = objBottom.y - obj2Top.y;
//pythagorean theorem for distance. dRight is from the right side of obj1 to the left of obj2. the rest follow suit.
let dRight = Math.sqrt(rightDistX*rightDistX + rightDistY*rightDistY);
let dLeft = Math.sqrt(leftDistX*leftDistX + leftDistY*leftDistY);
let dTop = Math.sqrt(topDistX*topDistX + topDistY*topDistY);
let dBottom = Math.sqrt(bottomDistX*bottomDistX + bottomDistY*bottomDistY);
//Math.min return the smallest value thus variable minimum will be which ever sides are closest together
let minimum = Math.min(dRight, dLeft, dBottom, dTop);
let val = 0;
//compare minimum to pythagorean theorem and set val based on which ever side is closest
if (dTop == minimum) {
val = 1;
//the context stuff can be deleted. It's just here for visual. The if statements can be one line each.
context.lineWidth = 2;
context.strokeStyle = 'blue';
context.beginPath();
context.moveTo(objTop.x, objTop.y); 
context.lineTo(obj2Bottom.x, obj2Bottom.y);
context.stroke();
}
else if (dRight == minimum) {
val = 2;
context.strokeStyle = 'orange';
context.beginPath();
context.moveTo(objRight.x, objRight.y); 
context.lineTo(obj2Left.x, obj2Left.y);
context.stroke();
}
else if (dBottom == minimum) {
val = 3;
context.strokeStyle = 'green';
context.beginPath();
context.moveTo(objBottom.x, objBottom.y); 
context.lineTo(obj2Top.x, obj2Top.y);
context.stroke();
}
else if (dLeft == minimum) {
val = 4;
context.strokeStyle = 'pink';
context.beginPath();
context.moveTo(objLeft.x, objLeft.y); 
context.lineTo(obj2Right.x, obj2Right.y);
context.stroke();
}
//pass the objects and val 
platformAction(obj, obj2, val);
}
//ACTION
function platformAction(obj, obj2, val){
//player1 top to player2 bottom
if (obj.y <= obj2.y + obj2.h && obj2.y + obj2.h >= obj.y && val == 1) {
obj2.y = obj.y - obj2.h; 
obj.y = obj2.y + obj2.h;
obj2.vy = 0;
obj2.jumping = false;
obj.jumping = true;
}
//player1 right to player2 left
if (obj.x + obj.w >= obj2.x && obj2.x <= obj.x + obj.w && val == 2) {
obj2.x = obj.x + obj.w;
obj.x = obj2.x - obj.w - 1;
obj2.vx = 0;
}
//player1 bottom to player2 top
if (obj.y + obj.h >= obj2.y && obj2.y <= obj.y + obj.h && val == 3) {
obj.y = obj2.y - obj.h;
obj2.y = obj.y + obj.h;
obj.vy = 0;
obj.jumping = false;
obj2.jumping = true;
}
//player1 left to player2 right
if (obj.x <= obj2.x + obj2.w && obj2.x + obj2.w >= obj.x && val == 4) {
obj2.x = obj.x - obj2.w;
obj.x = obj2.x + obj2.w + 1;
obj.vx = 0;
obj2.vx = 0;
}
}
function initObj(obj){
obj.update();
}
function loop() {
context.clearRect(0, 0, canvas.width, canvas.height); 
context.fillStyle = 'grey';
context.fillRect(0, 0, canvas.width, canvas.height);
//PLATFORM
initObj(platform1);
initObj(platform2);
//PLATFORM DETECTION
platformDetection(player1, platform1);
platformDetection(player1, platform2);
//PLAYER
controlPlayer1(player1); 
requestAnimationFrame(loop)
}
loop();
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, height=device-height, target-densitydpi=device-dpi">
<title>Tone.io</title>
<style>
body {
height:100vh;
width:100vh;
margin: 0;
}
</style>
</head>

<body>
<canvas id="canvas"></canvas>
<script src = "Js/Tone.js" type = "text/javascript"></script>
</body>
</html>

@MPdoor2"我做了&";。任何人,当我给你那个代码时,我确实特别说我从一个我创建的用于tilemaps的方法中入侵了它。该方法可以完美地实现这一目的,尽管代码中还有更多内容,是的,它是为正方形构建的,因为这就是瓦片图的主要功能。

我一直在玩CD的替代方法。这里有一个较短的方法(到目前为止(似乎效果很好。这种方法仍然以不同的方式确定每一侧之间的距离。一旦宽相位确定发生了碰撞,它就称之为窄相位,距离最短的一侧就是被穿透的一侧。即,当你与从玩家右侧到对象左侧的另一个块碰撞时,我们知道即使是Y轴也会穿透(玩家的上角和下角(。这将计算三者之间的距离,并且由于X之间的距离为0,因此它是最短的,并且不会调用用于在Y方向上移动播放器的CD。

试试下面的片段,看看这是否适合你。

const canvas = document.getElementById('canvas');
const context = canvas.getContext('2d');
canvas.width = 700;
canvas.height = 500;
let gravity = 1.5;
let friction = 0.9;
//CHARACTER:
class Player {
constructor(x, y, vx, vy, c, j) {
//each player must have separate values for control purposes i.e. velocity/jump/attack etc.
this.x = x;
this.y = y;
this.w = 50;
this.h = 50;
this.vx = vx;
this.vy = vy;
this.color = c;
this.jumping = j;
this.center = {x: this.x + this.w/2,  y: this.y + this.h/2};
this.topLeft = {x: this.x, y: this.y};
this.topRight = {x: this.x + this.w, y: this.y};
this.bottomRight = {x: this.x + this.w, y: this.y + this.h};
this.bottomLeft = {x: this.x, y: this.y + this.h};
}
draw() {
context.fillStyle = this.color;
context.fillRect(this.x, this.y, this.w, this.h);
}
canvasCollision() {
if (this.x <= 0) this.x = 0;
if (this.y <= 0) this.y = 0;
if (this.x + this.w >= canvas.width) this.x = canvas.width - this.w;
if (this.y + this.h >= canvas.height) {this.y = canvas.height - this.h; this.vy = 0; this.jumping = false};
}
update() {
this.draw(); 
this.vy += gravity;
this.x += this.vx;
this.y += this.vy;
this.vx *= friction;
this.vy *= friction;
this.center = {x: this.x + this.w/2,  y: this.y + this.h/2};
this.topLeft = {x: this.x, y: this.y};
this.topRight = {x: this.x + this.w, y: this.y};
this.bottomRight = {x: this.x + this.w, y: this.y + this.h};
this.bottomLeft = {x: this.x, y: this.y + this.h};
this.canvasCollision() //must be after other updates
}
}
let player = new Player(0, 0, 0, 0, 'red', false); 
function controlPlayer1(obj) {
if (controller1.up1 && !obj.jumping) { obj.vy -= 25; obj.jumping = true };
if (controller1.left1) { obj.vx -= 0.5 };
if (controller1.right1) { obj.vx += 0.5 };
obj.update();
}
class Platform {
constructor(x,y,w,h) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.center = {x: this.x + this.w/2,  y: this.y + this.h/2};
this.topLeft = {x: this.x, y: this.y};
this.topRight = {x: this.x + this.w, y: this.y};
this.bottomRight = {x: this.x + this.w, y: this.y + this.h};
this.bottomLeft = {x: this.x, y: this.y + this.h};
}
draw() {
context.fillStyle = 'blue';
context.fillRect(this.x, this.y, this.w, this.h);
}
}
let platforms = [];
function createPlatforms() {
for (let i=0; i<4; i++) {
platforms.push(new Platform(200 * i, 450 - (i * 75), 100, 25));
}
}
createPlatforms();
let platform1 = platforms.push(new Platform(300, 400, 50, 100));
let platform2 = platforms.push(new Platform(400, 400, 50, 50));
//MOVEMENT:
class Controller {
constructor() {
this.left1  = false;
this.up1    = false;
this.right1 = false;
this.left2  = false;
this.up2    = false;
this.right2 = false;
let controller1 = (e) => {
if (e.code === 'ArrowRight') { this.right1 = e.type === 'keydown' }
if (e.code === 'ArrowLeft')  { this.left1 = e.type === 'keydown' }
if (e.code === 'ArrowUp')    { this.up1 = e.type === 'keydown' }           
}

window.addEventListener('keydown', controller1);
window.addEventListener('keyup', controller1);
}
}
let controller1 = new Controller();
function collisionDetection(obj) {
if (player.x + player.w < obj.x ||
player.x > obj.x + obj.w ||
player.y + player.h < obj.y ||
player.y > obj.y + obj.h) {
return
}
narrowPhase(obj);
}
function narrowPhase(obj) {
let playerTop_ObjBottom = Math.abs(player.y - (obj.y + obj.h));
let playerRight_ObjLeft = Math.abs((player.x + player.w) - obj.x);
let playerLeft_ObjRight = Math.abs(player.x - (obj.x + obj.w));
let playerBottom_ObjTop = Math.abs((player.y + player.h) - obj.y);
if ((player.y <= obj.y + obj.h && player.y + player.h > obj.y + obj.h) && (playerTop_ObjBottom < playerRight_ObjLeft && playerTop_ObjBottom < playerLeft_ObjRight)) {
player.y = obj.y + obj.h;
player.vy = 0;
}
if ((player.y + player.h >= obj.y && player.y < obj.y) && (playerBottom_ObjTop < playerRight_ObjLeft && playerBottom_ObjTop < playerLeft_ObjRight)) {
player.y = obj.y - player.h; 
player.jumping = false;
player.vy = 0;
}
if ((player.x + player.w >= obj.x && player.x < obj.x) && (playerRight_ObjLeft < playerTop_ObjBottom && playerRight_ObjLeft < playerBottom_ObjTop)) {
player.x = obj.x - player.w;
player.vx = 0; 
}
if ((player.x <= obj.x + obj.w && player.x + player.w > obj.x + obj.w) && (playerLeft_ObjRight < playerTop_ObjBottom && playerLeft_ObjRight < playerBottom_ObjTop)) {
player.x = obj.x + obj.w;
player.vx = 0; 
}
}
function animate() {
context.clearRect(0, 0, canvas.width, canvas.height); 
context.fillStyle = 'grey';
context.fillRect(0, 0, canvas.width, canvas.height);
controlPlayer1(player); 
for (let i=0;i<platforms.length;i++) {
platforms[i].draw();
collisionDetection(platforms[i])
};
requestAnimationFrame(animate)
}
animate();
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, height=device-height">
<title>CD</title>
</head>
<body>
<canvas id="canvas"></canvas>
<script src="squareRectCollision2.js"></script>
</body>
</html>

要检测矩形之间的碰撞,请使用矩形边的位置。例如,他们";"垂直碰撞";if:

  • 对象1的底侧位于对象2的底部下方,对象1的顶部位于对象2底部上方
  • 或者对象1的上侧在对象2的顶部上方,对象1的底部在对象2顶部下方

如果它们同时碰撞";"垂直";以及";"水平";。

现在,一旦你确定了这一点,你就需要从哪个边缘进行检测。我在这里使用最接近的一个,评估所有";"垂直碰撞";或";"水平";。

const canvas = document.getElementById('canvas');
const context = canvas.getContext('2d');
canvas.width = Math.min(window.innerWidth - 3, 800);
canvas.height = Math.min(window.innerHeight - 3, 200);
let gravity = 1.5;
let friction = 0.9;
//CHARACTER:
class Player {
constructor(x, y, w, h, vx, vy, c, j) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.vx = vx;
this.vy = vy;
this.color = c;
this.jumping = j;
}
draw() {
context.fillStyle = this.color;
context.fillRect(this.x, this.y, this.w, this.h);
}
canvasCollision() {
if (this.x <= 0) this.x = 0;
if (this.y <= 0) this.y = 0;
if (this.x + this.w >= canvas.width) this.x = canvas.width - this.w;
if (this.y + this.h >= canvas.height) {
this.y = canvas.height - this.h;
this.vy = 0;
this.jumping = false
};
}
update() {
this.draw();
this.vy += gravity;
this.x += this.vx;
this.y += this.vy;
this.vx *= friction;
this.vy *= friction;
this.canvasCollision() //must be after other updates
}
}
let player1 = new Player(75, canvas.height / 2 + 75, 75, 75, 0, 0, '#8DAA9D', false);
function controlPlayer1(obj) {
//this order matters. If update is before jump then obj won't jump when on top of other block.
if (controller1.up1 && !obj.jumping) {
obj.vy -= 25;
obj.jumping = true
};
if (controller1.left1) {
obj.vx -= 0.5
};
if (controller1.right1) {
obj.vx += 0.5
};
obj.update();
}
//MOVEMENT:
class Controller {
constructor() {
this.left1 = false;
this.up1 = false;
this.right1 = false;
this.down1 = false;
let controller1 = (e) => {
if (e.code === 'KeyD') {
this.right1 = e.type === 'keydown'
}
if (e.code === 'KeyA') {
this.left1 = e.type === 'keydown'
}
if (e.code === 'KeyW') {
this.up1 = e.type === 'keydown'
}
if (e.code === 'KeyS') {
this.down1 = e.type === 'keydown'
}
}
window.addEventListener('keydown', controller1);
window.addEventListener('keyup', controller1);
}
}
let controller1 = new Controller();
//PLATFORM
class Platform {
constructor(x, y, w, h, yv, c) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.yv = yv;
this.color = c;
}
draw() {
context.fillStyle = this.color;
context.fillRect(this.x, this.y, this.w, this.h);
}
update() {
this.draw();
this.y += this.yv;
this.yv *= 0.9; // friction
}
}
let platform1 = new Platform(canvas.width / 2, canvas.height - 150, 100, 30, 0, '#202020');
let platform2 = new Platform(canvas.width / 4, canvas.height / 2, 75, 75, 0, '#202020');
//COLLISION DETECTION
function platformDetection(obj, obj2) {
let ol1 = obj.x;
let ot1 = obj.y;
let or1 = ol1 + obj.w;
let ob1 = ot1 + obj.h;
let ol2 = obj2.x;
let ot2 = obj2.y;
let or2 = ol2 + obj2.w;
let ob2 = ot2 + obj2.h;
let [collideTop, collideBottom, collideRight, collideLeft] = [-1, -1, -1, -1];
if (ob1 >= ob2) {
if (ot1 <= ob2) {
collideTop = ob2 - ot1;
}
}
if (ol1 <= ol2) {
if (or1 >= ol2) {
collideRight = or1 - ol2;
}
}
if (ot1 <= ot2) {
if (ob1 >= ot2) {
collideBottom = ob1 - ot2;
}
}
if (or1 >= or2) {
if (ol1 <= or2) {
collideLeft = or2 - ol1;
}
}
let min = minOfVals(collideTop, collideRight, collideBottom, collideLeft);
let val = 0;
if (min >= 0) {
if (min == collideTop && (collideLeft >= 0 || collideRight >= 0)) {
val = 1;
} else if (min == collideRight && (collideTop >= 0 || collideBottom >= 0)) {
val = 2;
} else if (min == collideBottom && (collideLeft >= 0 || collideRight >= 0)) {
val = 3;
} else if (min == collideLeft && (collideTop >= 0 || collideBottom >= 0)) {
val = 4;
}
}
if (val) console.log(val, min, collideTop, collideRight, collideBottom, collideLeft);
//pass the objects and val 
platformAction(obj, obj2, val);
}
function minOfVals(...vals) {
let min = -1;
function isBelowMin(v) {
return v >= 0 && (min < 0 || v < min);
}
for (v of vals) {
if (isBelowMin(v)) min = v;
}
return min;
}
//ACTION
function platformAction(obj, obj2, val) {
//player1 top to player2 bottom
if (val == 1) {
console.log("colliding from top");
obj2.y = obj.y - obj2.h;
//obj.y = obj2.y + obj2.h; //useless
obj2.vy = 0;
obj2.jumping = false;
obj.jumping = true;
}
//player1 right to player2 left
if (val == 2) {
console.log("colliding from right");
obj2.x = obj.x + obj.w;
obj.x = obj2.x - obj.w - 1;
obj2.vx = 0;
}
//player1 bottom to player2 top
if (val == 3) {
console.log("colliding from bottom");
obj.y = obj2.y - obj.h;
//obj2.y = obj.y + obj.h; //useless
obj.vy = 0;
obj.jumping = false;
obj2.jumping = true;
}
//player1 left to player2 right
if (val == 4) {
console.log("colliding from left");
obj2.x = obj.x - obj2.w;
obj.x = obj2.x + obj2.w + 1;
obj.vx = 0;
obj2.vx = 0;
}
}
function initObj(obj) {
obj.update();
}
function loop() {
context.clearRect(0, 0, canvas.width, canvas.height);
context.fillStyle = 'grey';
context.fillRect(0, 0, canvas.width, canvas.height);
//PLATFORM
initObj(platform1);
initObj(platform2);
//PLATFORM DETECTION
platformDetection(player1, platform1);
platformDetection(player1, platform2);
//PLAYER
controlPlayer1(player1);
requestAnimationFrame(loop)
}
loop();
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, height=device-height, target-densitydpi=device-dpi">
<title>Tone.io</title>
<style>
html {
margin: 0;
padding: 0;
}
body {
height: 100vh;
width: 100vh;
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script src="Js/Tone.js" type="text/javascript"></script>
</body>
</html>

当你的受控球员从左边或右边来时,仍然有不同的行为:推送速度不一样。但这并不是因为碰撞,所以我让你弄清楚这一点(也许这也是故意的(。

Yo,thx Justin用于解决方案。我采用了这个解决方案,并将其添加到我之前问的一个问题中,即如何对两个有运动的正方形(带箭头和wasd(进行碰撞检测和动作。这就是我添加它的方式:

const canvas = document.getElementById('canvas');
const context = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
let gravity = 1.5;
let friction = 0.9;
//CHARACTER:
class Player {
constructor(x, y, w, h, vx, vy, c, j) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.vx = vx;
this.vy = vy;
this.color = c;
this.jumping = j;
this.center = {x: this.x + this.w/2,  y: this.y + this.h/2};
this.topLeft = {x: this.x, y: this.y};
this.topRight = {x: this.x + this.w, y: this.y};
this.bottomRight = {x: this.x + this.w, y: this.y + this.h};
this.bottomLeft = {x: this.x, y: this.y + this.h};
}
draw() {
context.fillStyle = this.color;
context.fillRect(this.x, this.y, this.w, this.h);
}
canvasCollision() {
if (this.x <= 0) this.x = 0;
if (this.y <= 0) this.y = 0;
if (this.x + this.w >= canvas.width) this.x = canvas.width - this.w;
if (this.y + this.h >= canvas.height) {this.y = canvas.height - this.h; this.vy = 0; this.jumping = false};
}
update() {
this.draw(); 
this.vy += gravity;
this.x += this.vx;
this.y += this.vy;
this.vx *= friction;
this.vy *= friction;
this.canvasCollision() //must be after other updates
}
}
let player1 = new Player(canvas.width/2, canvas.height/2 + 75, 75, 75, 0, 0, 'darkgrey', false); 
let player2 = new Player(75, canvas.height/2 + 75, 75, 75, 0, 0, '#8DAA9D', false); 

function controlPlayer1(obj) {
//this order matters. If update is before jump then obj won't jump when on top of other block.
if (controller1.up1 && !obj.jumping) { obj.vy -= 25; obj.jumping = true };
if (controller1.left1) { obj.vx -= 0.5 };
if (controller1.right1) { obj.vx += 0.5 };
obj.update();
}
function controlPlayer2(obj) {
if (controller2.up2 && !obj.jumping) { obj.vy -= 25; obj.jumping = true };
if (controller2.right2) { obj.vx += 0.5 };
if (controller2.left2) { obj.vx -= 0.5 };
obj.update();
}
//MOVEMENT:
class Controller {
constructor() {
this.left1  = false;
this.up1    = false;
this.right1 = false;
this.left2  = false;
this.up2    = false;
this.right2 = false;
this.down  = false;
let controller1 = (e) => {
if (e.code === 'ArrowRight') { this.right1 = e.type === 'keydown' }
if (e.code === 'ArrowLeft')  { this.left1 = e.type === 'keydown' }
if (e.code === 'ArrowUp')    { this.up1 = e.type === 'keydown' }   
if (e.code === 'ArrowDown')      { this.down = e.type === 'keydown' }          
}

let controller2 = (e) => {
if (e.code === 'KeyD')   { this.right2 = e.type === 'keydown' }
if (e.code === 'KeyA')   { this.left2 = e.type === 'keydown' }
if (e.code === 'KeyW')   { this.up2 = e.type === 'keydown' }    
if (e.code === 'KeyS')  { this.down = e.type === 'keydown' }         
}  
window.addEventListener('keydown', controller1);
window.addEventListener('keyup', controller1);
window.addEventListener('keydown', controller2);
window.addEventListener('keyup', controller2);
}
}
let controller1 = new Controller();
let controller2 = new Controller();
//COLLISION DETECTION
function collisionDetection(obj, obj2){
if (obj.x + obj.w <= obj2.x ||
obj.x >= obj2.x + obj2.w ||
obj.y + obj.h < obj2.y ||
obj.y > obj2.y + obj2.h)
return
collisionAction(obj, obj2);
}
//ACTION 
function collisionAction(obj, obj2){
let playerTop_ObjBottom = Math.abs(obj.y - (obj2.y + obj2.h));
let playerRight_ObjLeft = Math.abs((obj.x + obj.w) - obj2.x);
let playerLeft_ObjRight = Math.abs(obj.x - (obj2.x + obj2.w));
let playerBottom_ObjTop = Math.abs((obj.y + obj.h) - obj2.y);

//virtical obj 1 top 
if ((obj.y <= obj2.y + obj2.h && obj.y + obj.h > obj2.y + obj2.h) && (playerTop_ObjBottom < playerRight_ObjLeft && playerTop_ObjBottom < playerLeft_ObjRight)) {
obj2.y = obj.y - obj2.h;
obj2.jumping = false;
obj2.vy = 0;}

//virtical obj 1 bottom 
if ((obj.y + obj.h >= obj2.y && obj.y < obj2.y) && (playerBottom_ObjTop < playerRight_ObjLeft && playerBottom_ObjTop < playerLeft_ObjRight)) {
obj.y = obj2.y - obj.h; 
obj.jumping = false;
obj.vy = 0;}
//horizontal obj 1 right 
if ((obj.x + obj.w >= obj2.x && obj.x < obj2.x) && (playerRight_ObjLeft < playerTop_ObjBottom && playerRight_ObjLeft < playerBottom_ObjTop)) {
obj2.x = obj.x + obj.w;
obj.x = obj2.x - obj.w;
obj.vx = 0;
obj2.vx = 0;}
//horizontal obj1 left 
if ((obj.x <= obj2.x + obj2.w && obj.x + obj.w > obj2.x + obj2.w) && (playerLeft_ObjRight < playerTop_ObjBottom && playerLeft_ObjRight < playerBottom_ObjTop)) {
obj2.x = obj.x - obj2.w;
obj.x = obj2.x + obj2.w;
obj.vx = 0;
obj2.vx = 0;}
}
function loop() {
context.clearRect(0, 0, canvas.width, canvas.height); 
context.fillStyle = 'grey';
context.fillRect(0, 0, canvas.width, canvas.height);
//PLAYER
controlPlayer1(player1); 
controlPlayer2(player2);

collisionDetection(player1, player2)
requestAnimationFrame(loop)
}
loop();

最新更新