简体   繁体   中英

2d Square to rectangle collision detection and action(physics)

so I made this way to detect and react to squares moving and touching other squares. It uses Pythagorean theorem to make a third parameter so you don't get two true if statements when squares touch. I recently have been attempting to use this method on a square to a rectangle, and cannot seem to get it working. I have drawn lines to help visualize what the code is doing. Anybody have any suggestions on how to get this collision working properly?

 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 "I made...". Anywho, when I gave you that code I did specifically say I had hacked it from a method I created to be used on tilemaps. The method works flawless for that purpose although there is more to the code and yes it is built for squares since that's what tiles map mainly are.

I have been playing with alternate methods of doing CD. Here's a shorter method that (so far) seems to be working well. This method still determines the distance between each side but in a different way. Once the broadphase determines a collision has occurred it calls the narrow phase and whichever side has the shortest distance is the side being penetrated. ie when you collide with another block from the player right to the object left we know that even the Y axis penetrates (top and bottom corners of player). This calculates the distance between all three and since the distance between X would be 0 it is the shortest and the CD for moving the player in the Y direction does not get called.

Try the snippet below and see if this works for you.

 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 ie 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,wh) { 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>

To detect collisions between rectangles, use the position of their sides. For instance, they "collide vertically" if:

  • object1's bottom side is below object2's bottom, and object1's top is above object2's bottom
  • or object1's top side is above object2's top, and object1's bottom is below object2's top

Consider they do collide if they collide both "vertically" and "horizontally".

Now once you've determined that, you need to detect from which edge. I'm using the closest one here, evaluating the distance for all that "collide vertically" or "horizontally".

 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>

There's still a different behavior when your controlled player comes from the left or from the right: push speed is not the same. But that's not due to collisions, so I'm letting you figure out this one (maybe it's on purpose too).

Yo, thx Justin for a solution. I took that solution and also added it to a previous question I asked, which was how to do the collision detection and action for two squares that have movement (with arrows and wasd). This is how I added it:

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();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM