Reputation: 51
i'm trying to develop a game using HTML5 canvas with javascript and I am having problems detecting collisions without hard coding it using the (x,y) coordinates of the two objects. In my code based from research, found out the common algorithm in checking if the two objects are colliding which is
Object1 = a moving player
Object2 = fixed (x,y) points. Non movable object
(object1.x < object2.x + object2.width && object1.x + object1.width > object2.x &&
object1.y < object2.y + object2.height && object1.y + object1.height > object2.y)
I tried it and developed it with other codes and it works, it detects the collisions. But I have an issue with the collisions, it works with the condition in the left side
but when the object1
goes to the top, bottom or right
of the object2 it goes back to the object2's left side
. In other words, if the object1 goes to the top/bottom or right it goes back to the left side. Any kind of help would be much appreciated.
function collide(object1, object2){
//object1 player
this.x = object1.x;
this.y = object1.y;
this.w = object1.w;
this.h = object1.h;
//object2 any object
this.x2 = object2.x;
this.y2 = object2.y;
this.w2 = object2.w;
this.h2 = object2.h;
//collisions
var isCorrect = false;
var side = 0;
if ((this.x < this.x2 + this.w2) && (this.x + this.w > this.x2)
&& (this.y < this.y2 + this.h2) && (this.h + this.y > this.y2)){
isCorrect = true;
}
if (this.x + this.w > this.x2){
//left check
side = 1;
}else if (this.x < this.x2 + this.w2){
//right check
side = 2;
}else if (this.y + this.h > this.y2){
//bottom check
side = 3;
}else if (this.y < this.y2 + this.h2){
//top check
side = 4;
}
if (isCorrect){
if ((this.x + this.w > this.x2) && side == 1){
playerObj.x -= 5;
}else if ((this.x < this.x2 + this.w2) && side == 2){
playerObj.x += 5;
}else if ((this.y + this.h > this.y2) && side == 3){
playerObj.y += 5;
}else if ((this.y < this.y2 + this.h2) && side == 4){
playerObj.y -= 5;
}
}
}
Upvotes: 5
Views: 5914
Reputation: 105035
This collision function will tell you which side of rect2 collided with rect1:
And of course, the opposite side of rect1 collided with rect2.
This function is a 2-pass test:
Test1: Check if the 2 rectangle's centers are close enough to be colliding
Test2: If yes, check the intersection depths to determine which side was most involved in the collision.
The collision function
function collide(r1,r2){
var dx=(r1.x+r1.w/2)-(r2.x+r2.w/2);
var dy=(r1.y+r1.h/2)-(r2.y+r2.h/2);
var width=(r1.w+r2.w)/2;
var height=(r1.h+r2.h)/2;
var crossWidth=width*dy;
var crossHeight=height*dx;
var collision='none';
//
if(Math.abs(dx)<=width && Math.abs(dy)<=height){
if(crossWidth>crossHeight){
collision=(crossWidth>(-crossHeight))?'bottom':'left';
}else{
collision=(crossWidth>-(crossHeight))?'right':'top';
}
}
return(collision);
}
Here's example code and a Demo:
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
function reOffset(){
var BB=canvas.getBoundingClientRect();
offsetX=BB.left;
offsetY=BB.top;
}
var offsetX,offsetY;
reOffset();
window.onscroll=function(e){ reOffset(); }
var rects=[];
var rect1={ x:100,y:100,w:85,h:85,fill:'red'}
var rect2={ x:10,y:10,w:40,h:60,fill:'gold'}
$("#canvas").mousemove(function(e){handleMouseMove(e);});
draw();
function collide(r1,r2){
var dx=(r1.x+r1.w/2)-(r2.x+r2.w/2);
var dy=(r1.y+r1.h/2)-(r2.y+r2.h/2);
var width=(r1.w+r2.w)/2;
var height=(r1.h+r2.h)/2;
var crossWidth=width*dy;
var crossHeight=height*dx;
var collision='none';
//
if(Math.abs(dx)<=width && Math.abs(dy)<=height){
if(crossWidth>crossHeight){
collision=(crossWidth>(-crossHeight))?'bottom':'left';
}else{
collision=(crossWidth>-(crossHeight))?'right':'top';
}
}
return(collision);
}
function draw(){
ctx.clearRect(0,0,cw,ch);
ctx.fillStyle=rect1.fill;
ctx.fillRect(rect1.x,rect1.y,rect1.w,rect1.h);
ctx.fillStyle=rect2.fill;
ctx.fillRect(rect2.x,rect2.y,rect2.w,rect2.h);
var side=collide(rect1,rect2);
ctx.fillStyle='green'
if(side=='top'){ ctx.fillRect(rect2.x,rect2.y,rect2.w,3); }
if(side=='right'){ ctx.fillRect(rect2.x+rect2.w,rect2.y,3,rect2.h); }
if(side=='bottom'){ ctx.fillRect(rect2.x,rect2.y+rect2.h,rect2.w,3); }
if(side=='left'){ ctx.fillRect(rect2.x,rect2.y,3,rect2.h); }
}
function handleMouseMove(e){
// tell the browser we're handling this event
e.preventDefault();
e.stopPropagation();
mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
rect2.x=mouseX;
rect2.y=mouseY;
draw();
}
body{ background-color: ivory; }
#canvas{border:1px solid red;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<h4>Move the mouse to drag the gold rect<br>Any colliding side of gold rect will highlight</h4>
<canvas id="canvas" width=300 height=300></canvas>
Upvotes: 18