2
\$\begingroup\$

I am making a Diep.io Clone, and everything was going smooth until I made a collision resolution system for when a shape collides with another shape. Instead of them bouncing off of each other, they teleport to the center of the map and don't move. The collision resolution for when a bullet hits a shape works just fine, but I cannot figure out why this is happening and how I can fix it. Thanks

Here is the collision resolution code:

this.update = function() {
    this.x -= this.velx;
    this.y -= this.vely;
    this.x -= this.pushx;
    this.y -= this.pushy;
    this.rot -= this.r;
    if(this.pushx > 0) {
        this.pushx -= this.acc;
    }
    if(this.pushy > 0) {
        this.pushy -= this.acc;
    }
    if(this.pushx < 0) {
        this.pushx += this.acc;
    }
    if(this.pushy < 0) {
        this.pushy += this.acc;
    }
    if(Math.abs(this.pushx) < this.acc) {
        this.pushx = 0;
    }
    if(Math.abs(this.pushy) < this.acc) {
        this.pushy = 0;
    }
};

this.gothit = function(other) {
    switch(other.constructor.name){
        case "shape":
            this.pushx += other.xvel * 5;
            this.pushy += other.yvel * 5;
            break;
        case "bullet":
            this.pushx += (other.dx / other.mag) * other.ms;
            this.pushy += (other.dy / other.mag) * other.ms;
            break;     
    }
}

And here is the full code, if needed.

			var canvas = document.getElementById("canvas");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
var c = canvas.getContext("2d");
c.lineCap = "round";
var mouseIsPressed = false;
var mouseClicked = false;
var autofire = false;
var autospin = false;
var tanks = [];
var keys = [];
var bullets = [];
var shapes = [];
var xpamt = [
0,
4,
13,
28,
50,
78,
113,
157,
211,
272,
350,
437,
536,
653,
784,
938,
1109,
1301,
1516,
1757,
2026,
2325,
2653,
3017,
3416,
3854,
4334,
4857,
5428,
6048,
6720,
7448,
8235,
9084,
9998,
10981,
12036,
13167,
14377,
15671,
17053,
18526,
20094,
21762,
23545
];
var tankstats = {
basic: {
	knockback: 1,
	reload: 500,
	bspeed: 3,
	bdamage: 3,
	bpenetration: 1,
	spread: 5
},
sniper: {
	knockback: 3,
	reload: 1000,
	bspeed: 5,
	bdamage: 3,
	bpenetration: 3,
	spread: 2
},
twin: {
	knockback: 1,
	reload: 250,
	bspeed: 0,
	bdamage: 3,
	bpenetration: 3,
	spread: 5
},
flankguard: {
	knockback: 0,
	reload: 500,
	bspeed: 1,
	bdamage: 3,
	bpenetration: 3,
	spread: 5
},
machinegun: {
	knockback: 2,
	reload: 150,
	bspeed: 3,
	bdamage: 3,
	bpenetration: 3,
	spread: 10
},
flamethrower: {
	knockback: 0.5,
	reload: 0,
	bspeed: 4,
	bdamage: 0.5,
	bpenetration: 1,
	spread: 20
},
overseer: {
	knockback: 0,
	reload: 3000,
	bspeed: 3,
	bdamage: 5,
	bpenetration: 3,
	spread: 0
},
};
var camx = 0;
var camy = 0;
var mousex = 0;
var mousey = 0;
var millis = 0;

function shape(x, y, id) {
this.x = x;
this.y = y;
this.id = id;
this.r = 0.01 - Math.random() / 50;
this.rot = 0;
this.velx = Math.random() / 10;
this.vely = Math.random() / 10;
this.pushx = 0;
this.pushy = 0;
this.acc = 0.1;
this.update = function() {
	this.x -= this.velx;
	this.y -= this.vely;
	this.x -= this.pushx;
	this.y -= this.pushy;
	this.rot -= this.r;
	if(this.pushx > 0) {
		this.pushx -= this.acc;
	}
	if(this.pushy > 0) {
		this.pushy -= this.acc;
	}
	if(this.pushx < 0) {
		this.pushx += this.acc;
	}
	if(this.pushy < 0) {
		this.pushy += this.acc;
	}
	if(Math.abs(this.pushx) < this.acc) {
		this.pushx = 0;
	}
	if(Math.abs(this.pushy) < this.acc) {
		this.pushy = 0;
	}
};
this.gothit = function(other) {
	switch(other.constructor.name) {
		case "shape":
			this.pushx += other.xvel * 5;
			this.pushy += other.yvel * 5;
			break;
		case "bullet":
			this.pushx += (other.dx / other.mag) * other.ms;
			this.pushy += (other.dy / other.mag) * other.ms;
			break;
	}
}
this.show = function() {
	c.save();
	c.translate(this.x, this.y);
	c.rotate(this.rot);
	switch(this.id) {
		case 0:
			c.fillStyle = "rgb(250, 250, 150)";
			c.strokeStyle = "rgb(200, 200, 100)";
			c.fillRect(-18, -18, 36, 36);
			c.beginPath();
			c.moveTo(-18, -18);
			c.lineTo(18, -18);
			c.stroke();
			c.beginPath();
			c.moveTo(18, -18);
			c.lineTo(18, 18);
			c.stroke();
			c.beginPath();
			c.moveTo(18, 18);
			c.lineTo(-18, 18);
			c.stroke();
			c.beginPath();
			c.moveTo(-18, 18);
			c.lineTo(-18, -18);
			c.stroke();
			break;
		case 1:
			c.fillStyle = "rgb(250, 150, 150)";
			c.strokeStyle = "rgb(200, 100, 100)";
			c.beginPath();
			c.moveTo(-20, 12);
			c.lineTo(0, -23);
			c.lineTo(20, 12);
			c.fill();
			c.beginPath();
			c.moveTo(20, 12);
			c.lineTo(0, -23);
			c.stroke();
			c.beginPath();
			c.moveTo(0, -23);
			c.lineTo(-20, 12);
			c.stroke();
			c.beginPath();
			c.moveTo(-20, 12);
			c.lineTo(20, 12);
			c.stroke();
			break;
		case 2:
			c.fillStyle = "rgb(150, 150, 250)";
			c.strokeStyle = "rgb(120, 120, 200)";
			c.beginPath();
			c.moveTo(0, 30);
			c.lineTo(29, 9);
			c.lineTo(18, -24);
			c.lineTo(-18, -24);
			c.lineTo(-29, 9);
			c.lineTo(0, 30);
			c.fill();
			c.beginPath();
			c.moveTo(0, 30);
			c.lineTo(29, 9);
			c.stroke();
			c.beginPath();
			c.moveTo(29, 9);
			c.lineTo(18, -24);
			c.stroke();
			c.beginPath();
			c.moveTo(18, -24);
			c.lineTo(-18, -24);
			c.stroke();
			c.beginPath();
			c.moveTo(-18, -24);
			c.lineTo(-29, 9);
			c.stroke();
			c.beginPath();
			c.moveTo(-29, 9);
			c.lineTo(0, 30);
			c.stroke();
			break;
	}
	c.restore();
};
}

function bullet(x, y, dx, dy, r, id, t, s, d, p) {
this.x = x;
this.y = y;
this.dx = this.x - dx;
this.dy = this.y - dy;
this.mag = Math.sqrt(this.dx * this.dx + this.dy * this.dy);
this.r = r;
this.id = id;
this.t = t;
this.ms = s;
this.xs = 0;
this.ys = 0;
this.d = d;
this.p = p;
this.update = function() {
	if(this.id != 1) {
		this.x -= (this.dx / this.mag) * this.ms;
		this.y -= (this.dy / this.mag) * this.ms;
		this.p -= 0.01;
	} else {
		this.xs = Math.abs(this.x - this.dx) / 20;
		if(this.xs > this.ms) this.xs = this.ms;
		if(Math.abs(this.x - this.dx) > 7) {
			this.x -= (this.dx / this.mag) * this.xs;
		}
		this.ys = Math.abs(this.y - this.dy) / 20;
		if(this.ys > this.ms) this.ys = this.ms;
		if(Math.abs(this.y - this.dy) > 7) {
			this.y -= (this.dy / this.mag) * this.ys;
		}
		this.dx = this.x - (-camx + mousex);
		this.dy = this.y - (-camy + mousey);
		this.mag = Math.sqrt(this.dx * this.dx + this.dy * this.dy);
	}
};
this.show = function() {
	c.beginPath();
	switch(this.id) {
		case 0:
			switch(this.t) {
				case 0:
					c.fillStyle = "rgb(100, 200, 250)";
					c.strokeStyle = "rgb(50, 150, 200)";
					break;
				case 1:
					c.fillStyle = "rgb(250, 150, 150)";
					c.strokeStyle = "rgb(200, 100, 100)";
					break;
				case 2:
					c.fillStyle = "rgb(150, 250, 150)";
					c.strokeStyle = "rgb(100, 200, 100)";
					break;
				case 3:
					c.fillStyle = "rgb(250, 150, 250)";
					c.strokeStyle = "rgb(200, 100, 200)";
					break;
			}
			c.arc(this.x, this.y, this.r, 0, 2 * Math.PI);
			c.fill();
			c.stroke();
		case 1:
			switch(this.t) {
				case 0:
					c.fillStyle = "rgb(100, 200, 250)";
					c.strokeStyle = "rgb(50, 150, 200)";
					break;
				case 1:
					c.fillStyle = "rgb(250, 150, 150)";
					c.strokeStyle = "rgb(200, 100, 100)";
					break;
				case 2:
					c.fillStyle = "rgb(150, 250, 150)";
					c.strokeStyle = "rgb(100, 200, 100)";
					break;
				case 3:
					c.fillStyle = "rgb(250, 150, 250)";
					c.strokeStyle = "rgb(200, 100, 200)";
					break;
			}
			c.arc(this.x, this.y, this.r, 0, 2 * Math.PI);
			c.fill();
			c.stroke();
	}
};
}

function tank(x, y, r, t, n, xp, lvl, id, inv) {
this.x = x;
this.y = y;
this.velx = 0;
this.vely = 0;
this.acc = 0.075;
this.maxSpeed = 3;
this.knockback = tankstats.basic.knockback;
this.bulletP = tankstats.basic.bpenetration;
this.bulletS = tankstats.basic.bspeed;
this.bulletD = tankstats.basic.bdamage;
this.r = r;
this.t = t;
this.n = n;
this.xp = xp;
this.lvl = lvl;
this.id = id;
this.inv = inv;
this.reload = tankstats.basic.reload;
this.reloading = false;
this.cooldown = this.reload;
this.timetill = 0;
this.update = function(r) {
	this.r = r;
	if(keys[87] && !keys[83]) {
		this.vely -= this.acc;
	}
	if(keys[83] && !keys[87]) {
		this.vely += this.acc;
	}
	if(keys[65] && !keys[68]) {
		this.velx -= this.acc;
	}
	if(keys[68] && !keys[65]) {
		this.velx += this.acc;
	}
	if(this.velx > this.maxSpeed) {
		this.velx = this.maxSpeed;
	}
	if(this.velx < -this.maxSpeed) {
		this.velx = -this.maxSpeed;
	}
	if(this.vely > this.maxSpeed) {
		this.vely = this.maxSpeed;
	}
	if(this.vely < -this.maxSpeed) {
		this.vely = -this.maxSpeed;
	}
	if(!keys[87] && !keys[83]) {
		if(this.vely < 0) {
			this.vely += this.acc;
		}
		if(this.vely > 0) {
			this.vely -= this.acc;
		}
		if(Math.abs(this.vely) <= this.acc) {
			this.vely = 0;
		}
	}
	if(!keys[65] && !keys[68]) {
		if(this.velx < 0) {
			this.velx += this.acc;
		}
		if(this.velx > 0) {
			this.velx -= this.acc;
		}
		if(Math.abs(this.velx) < this.acc) {
			this.velx = 0;
		}
	}
	this.x += this.velx;
	this.y += this.vely;
	if(mouseIsPressed || keys[32] || autofire) {
		if(this.cooldown === this.reload && !this.reloading) {
			switch(this.id) {
				case 0:
					bullets.push(new bullet(this.x + Math.sin(this.r) * 50, this.y - Math.cos(this.r) * 50, this.x + Math.sin(this.r) * 70, this.y - Math.cos(this.r) * 70, 10, 0, this.t, this.bulletS, this.bulletD, this.bulletP));
					break;
				case 6:
					bullets.push(new bullet(this.x + Math.sin(this.r) * 50, this.y - Math.cos(this.r) * 50, mousex, mousey, 10, 1, this.t, this.bulletS, this.bulletD, this.bulletP));
					break;
			}
			this.dx = Math.sin(this.r);
			this.dy = -Math.cos(this.r);
			this.mag = Math.sqrt(this.dx * this.dx + this.dy * this.dy);
			this.velx -= ((this.dx / this.mag) * this.knockback);
			this.vely -= ((this.dy / this.mag) * this.knockback);
			this.reloading = true;
			return;
		}
	}
	if(this.reloading) {
		this.cooldown -= 100;
		this.timetill = millis;
	}
	if(this.cooldown <= 0) {
		this.cooldown = 0;
		this.reloading = false;
	}
	if(this.cooldown !== this.reload && !this.reloading) {
		if(this.cooldown < this.reload) {
			this.cooldown = millis - this.timetill;
		} else {
			this.cooldown = this.reload;
		}
	}
};
this.show = function() {
	c.save();
	c.translate(this.x, this.y);
	c.rotate(this.r);
	c.fillStyle = "rgb(200, 200, 200)";
	c.strokeStyle = "rgb(150, 150, 150)";
	c.fillRect(-9, 0, 18, -45 * (1 - (this.reload - this.cooldown) / 3000));
	c.beginPath();
	c.moveTo(-9, 0);
	c.lineTo(-9, -45 * (1 - (this.reload - this.cooldown) / (this.reload * 8)));
	c.stroke();
	c.beginPath();
	c.moveTo(-9, -45 * (1 - (this.reload - this.cooldown) / (this.reload * 8)));
	c.lineTo(9, -45 * (1 - (this.reload - this.cooldown) / (this.reload * 8)));
	c.stroke();
	c.beginPath();
	c.moveTo(9, 0);
	c.lineTo(9, -45 * (1 - (this.reload - this.cooldown) / (this.reload * 8)));
	c.stroke();
	switch(this.t) {
		case 0:
			c.fillStyle = "rgb(100, 200, 250)";
			c.strokeStyle = "rgb(50, 150, 200)";
			break;
		case 1:
			c.fillStyle = "rgb(250, 150, 150)";
			c.strokeStyle = "rgb(200, 100, 100)";
			break;
		case 2:
			c.fillStyle = "rgb(150, 250, 150)";
			c.strokeStyle = "rgb(100, 200, 100)";
			break;
		case 3:
			c.fillStyle = "rgb(250, 150, 250)";
			c.strokeStyle = "rgb(200, 100, 200)";
			break;
	}
	c.beginPath();
	c.arc(0, 0, 25, 0, 2 * Math.PI);
	c.fill();
	c.stroke();
	c.restore();
};
}
tanks.push(new tank(50, 50, 0, 0, "test", 0, 0, 0, 1));
for(var i = 0; i < 1000 - (shapes.length - 1); i++) {
shapes.push(new shape(Math.round(Math.random() * 6000) - 3000, Math.round(Math.random() * 6000) - 3000, Math.round(Math.random() * 2)));
}

function draw() {
millis = new Date();
millis = millis.getTime();
if(autospin) {
	mousex = (canvas.width / 2) + Math.sin(millis / 1500) * 200;
	mousey = (canvas.height / 2) + Math.cos(millis / 1500) * 200;
}
camx = (canvas.width / 2) - tanks[0].x;
camy = (canvas.height / 2) - tanks[0].y;
c.fillStyle = "rgb(220, 220, 220)";
c.fillRect(0, 0, canvas.width, canvas.height);
c.strokeStyle = "rgb(200, 200, 200)";
c.lineWidth = 1;
for(var i = 0; i < canvas.width / 20; i++) {
	c.beginPath();
	c.moveTo(0, (i * 25) - tanks[0].y % 25);
	c.lineTo(canvas.width, (i * 25) - tanks[0].y % 25);
	c.stroke();
	c.beginPath();
	c.moveTo((i * 25) - tanks[0].x % 25, 0);
	c.lineTo((i * 25) - tanks[0].x % 25, canvas.height);
	c.stroke();
}
c.lineWidth = 3;
c.save();
c.translate(camx, camy);
for(var i = shapes.length - 1; i >= 0; i--) {
	shapes[i].show();
	shapes[i].update();
	for(var j = shapes.length - 1; j >= 0; j--) {
		if(i !== j) {
			if(Math.abs(shapes[i].x - shapes[j].x) < 50 && Math.abs(shapes[i].y - shapes[j].y) < 50) {
				shapes[i].gothit(shapes[j]);
				shapes[j].gothit(shapes[i]);
			}
		}
	}
	for(var j = bullets.length - 1; j >= 0; j--) {
		if(Math.abs(shapes[i].x - bullets[j].x) < 18 + bullets[j].r && Math.abs(shapes[i].y - bullets[j].y) < 18 + bullets[j].r) {
			shapes[i].gothit(bullets[j]);
			bullets[j].p--;
		}
	}
}
for(var i = bullets.length - 1; i >= 0; i--) {
	bullets[i].show();
	bullets[i].update();
	if(bullets[i].p <= 0) {
		bullets.splice(i, 1);
	}
}
for(var i = tanks.length - 1; i >= 0; i--) {
	tanks[i].show();
	tanks[i].update(Math.atan2(-(tanks[i].x - (mousex - camx)), (tanks[i].y - (mousey - camy))));
}
c.restore();
mouseClicked = false;
c.beginPath();
c.arc(mousex, mousey, 5, 0, 2 * Math.PI);
c.fill();
window.requestAnimationFrame(draw);
}
window.requestAnimationFrame(draw);
window.addEventListener("mousemove", function(e) {
if(!autospin) {
	mousex = e.clientX;
	mousey = e.clientY;
}
});
window.addEventListener("mousedown", function() {
mouseIsPressed = true;
});
window.addEventListener("mouseup", function() {
mouseIsPressed = false;
mouseClicked = true;
});
window.addEventListener("keydown", function(e) {
keys[e.keyCode] = true;
});
window.addEventListener("keyup", function(e) {
if(keys[69]) {
	if(!autofire) autofire = true;
	else autofire = false;
}
if(keys[67]) {
	if(!autospin) autospin = true;
	else autospin = false;
}
keys[e.keyCode] = false;
});
			
            
@font-face {
font-family: 'Ubuntu';
src: url("Ubuntu-B.ttf") format('ttf');
}

html, body, canvas, p {
			
margin: 0;
font-family: "Ubuntu";
padding: 0;
overflow: hidden;
			
}
			
<!DOCTYPE html>
<html>
	<head>
		<title>peip.io</title>
	</head>
	<body>
		<canvas id="canvas" width="800px" height="600px"></canvas>
	</body>
</html>

Additional info:

Edit: I halfway figured out the problem, and by logging the collision variables, I found out that they were NaN, so I will experiment further to find out why

\$\endgroup\$
2
\$\begingroup\$

Nobody will really read your whole code, but one thing I can tell you is, maybe you should use a physics engine to take care of this for you. Here I will link Box2D for Javascript:

http://box2d-js.sourceforge.net/

There is a little guide there too, but you can find other tutorials! Good luck!

\$\endgroup\$
  • \$\begingroup\$ Could you explain how this would be done? Currently, this answer could be considered as a link only answer because it does not tell the OP how they could solve their particular issue. \$\endgroup\$ – Alexandre Vaillancourt Apr 13 '18 at 14:47
  • \$\begingroup\$ It pretty much means deleting your physics code you have now and use the physics engine instead! \$\endgroup\$ – Joza100 Apr 13 '18 at 14:54
  • \$\begingroup\$ Thanks for the answer @Joza100, but I'm looking for an answer that will help me fix my code, not replace it \$\endgroup\$ – Priswall Apr 13 '18 at 15:14
  • \$\begingroup\$ That's ok but your code is too big. I don't know who will have patience to read it. One LAST thing that i can suggest is trying to rewrite it. When you rewrite it you might get it right and not make the mistake you have just made \$\endgroup\$ – Joza100 Apr 13 '18 at 16:34
2
\$\begingroup\$

It turns out, I was calling this.xvel and this.yvel, when I defined them as this.velx and this.vely

\$\endgroup\$
  • \$\begingroup\$ Good ol' typos, get's ya every time. \$\endgroup\$ – NetOperator Wibby Apr 20 '18 at 3:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.