Javascript Collision Detection

I create a game in Javascript using a canvas that requires collision detection, in this case, if the game sprite falls into the field, the player should not be allowed to pass through the field.

I have a global array called blockList that contains all the rectangles drawn on the canvas. It looks like this:

 var blockList = [[50, 400, 100, 100]]; 

And they are drawn to the canvas as follows:

 c.fillRect(blockList[0][0], blockList[0][1], blockList[0][2], blockList[0][3]); 

I also have a player object that has an update method and a draw method. The update sets the position of the player based on keyboard input, etc., And drawing is used by the main game loop to draw the player on canvas. The player is drawn as follows:

 this.draw = function(timestamp) { if(this.state == "idle") { c.drawImage(this.idleSprite, this.idleSprite.frameWidth * this.idleSprite.frameCount, 0, this.idleSprite.frameWidth, this.idleSprite.frameHeight, this.xpos, this.ypos, this.idleSprite.frameWidth, this.idleSprite.frameHeight); if(timestamp - this.lastDraw > this.idleSprite.updateInterval) { this.lastDraw = timestamp; if(this.idleSprite.frameCount < this.idleSprite.frames - 1) { this.idleSprite.frameCount++; } else { this.idleSprite.frameCount = 0; } } } else if(this.state == "running") { var height = 0; if(this.facing == "left") { height = 37; } c.drawImage(this.runningSprite, this.runningSprite.frameWidth * this.runningSprite.frameCount, height, this.runningSprite.frameWidth, this.runningSprite.frameHeight, this.xpos, this.ypos, this.runningSprite.frameWidth, this.runningSprite.frameHeight); if(timestamp - this.lastDraw > this.runningSprite.updateInterval) { this.lastDraw = timestamp; if(this.runningSprite.frameCount < this.runningSprite.frames - 1) { this.runningSprite.frameCount++; } else { this.runningSprite.frameCount = 0; } } } } 

Now the player has certain properties: player.xpos , player.ypos , player.width , player.height . The same properties exist for blocks. Therefore, I have everything I need to implement collision detection, I just don’t know how to do it. I tried to do things like:

 if(player.x > blockList[0][0] && player.y > blockList[0][1]) 

but it is far from ideal or reproducible.

Does anyone know of a simple method or function to be able to return true or false based on whether two objects collide?

+6
source share
3 answers

I use the following function to detect collisions between two rectangles:

 rect_collision = function(x1, y1, size1, x2, y2, size2) { var bottom1, bottom2, left1, left2, right1, right2, top1, top2; left1 = x1 - size1; right1 = x1 + size1; top1 = y1 - size1; bottom1 = y1 + size1; left2 = x2 - size2; right2 = x2 + size2; top2 = y2 - size2; bottom2 = y2 + size2; return !(left1 > right2 || left2 > right1 || top1 > bottom2 || top2 > bottom1); }; 

This determines whether two squares centered on (x1, y1) and (x2, y2) 2*size1 with side lengths of 2*size1 and 2*size2 respectively. It should be easy enough to change the definitions of left1 , right1 , etc., to deal with common rectangles, not squares, and use a different data format.

In particular, left1 is the left side of the first square, right1 is the right side, etc. Notice that in my coordinate system the y axis is inverted ( top1 < bottom1 ).

+8
source

Do you just want to know if two rectangles overlap?

Here is an armored function for you:

 // returns true if there is any overlap // params: x,y,w,h of two rectangles function intersects(x1, y1, w1, h1, x2, y2, w2, h2) { if (w2 !== Infinity && w1 !== Infinity) { w2 += x2; w1 += x1; if (isNaN(w1) || isNaN(w2) || x2 > w1 || x1 > w2) return false; } if (y2 !== Infinity && h1 !== Infinity) { h2 += y2; h1 += y1; if (isNaN(h1) || isNaN(y2) || y2 > h1 || y1 > h2) return false; } return true; } 

If your program can be sure that the numbers will always be finite, you can use a simpler version:

 // returns true if there is any overlap // params: x,y,w,h of two rectangles function intersects(x1, y1, w1, h1, x2, y2, w2, h2) { w2 += x2; w1 += x1; if (x2 > w1 || x1 > w2) return false; h2 += y2; h1 += y1; if (y2 > h1 || y1 > h2) return false; return true; } 

What is his search for, where are the right side and the bottom side of the two rectangles, then he sees whether the second will start outside the first, or if the first starts outside the second.

If any rectangle begins after the other is finished, then a collision does not occur. Otherwise there should be a collision.

+2
source

In my opinion, I am not a fan of functions that require a lot of parameters.

Here's how I would do it:

 function collisionCheckRectRect(rectOne, rectTwo){ var x1=rectOne.x, y1 = rectOne.y, height1 = rectOne.height, width1 = rectOne.width; var x2=rectTwo.x, y2 = rectTwo.y, height2 = rectTwo.height, width2 = rectTwo.width; return x1 < x2+width2 && x2 < x1+width1 && y1 < y2+height2 && y2 < y1+height1; } 
0
source

Source: https://habr.com/ru/post/900831/


All Articles