Why does the ball stick to the ground after an arbitrary amount of time?

I have the following code that drops a few balls along the screen using physics, and Jupiter's gravity divided by 10 for testing purposes.

var canvas = document.getElementById("canvas"),
    ctx = canvas.getContext('2d');

//jupiter gravity divided by 10 for testing purposes
g = 24.79/10;
canvas.width = window.innerWidth - 50;
canvas.height = window.innerHeight - 22.5;
bounciness = (1/2)
var spawnrate = 16;
var inertia = 0.00075;
var gravity = g/25;
players = []
then = new Date()/1000;
moved = false;
function getPosition(event){
	mouseX = event.clientX;
	mouseY = event.clientY;
	if(moved == false){
		update();
		moved = true;
	}
}
function addCircle(){
    players.push({x: mouseX, y: mouseY, color: '#000000', radius: 10, velY: 0, velX: 2, jumped: false, jump: 0.02, max: 0});
}
first = new Date();
function update(){
        ctx.clearRect(0, 0, canvas.width, canvas.height);
	t = new Date() - first;
	now = new Date() / 1000;
	if(now-then >= 1/spawnrate){
		then = now;
		addCircle();
	}
	for(var c = 0; c < players.length; c++){
		circle = players[c];
		circle.y+=circle.velY;
		circle.x+=circle.velX;
		circle.velX-=inertia;
		circle.velY+=gravity;
		if(Math.abs(circle.velY) > Math.abs(circle.max)){
			circle.max = circle.velY;
		}
		if(circle.y + circle.radius/2 > canvas.height){
			circle.velY*=-Math.sqrt(bounciness);
		}
		updateCircle(circle);
		if(circle.x > canvas.width){
			players.splice(c, 1);
		}

	}
        setTimeout(update, 10);
}

function drawLine(x1, y1, x2, y2){
	ctx.beginPath();
	ctx.moveTo(x1, y1);
	ctx.lineTo(x2, y2);
	ctx.stroke();
}

function updateCircle(player){
        ctx.fillStyle = player.color;
        ctx.beginPath();
        ctx.arc(player.x, player.y, player.radius, 0, Math.PI * 2);
        ctx.fill();
}

window.addEventListener("mousemove", getPosition, false);
if(moved == true){
	update();
}
#canvas{
    display: block;
}
<!DOCTYPE html>
<html>
	<head>
		<title>Bounce</title>
	</head>
	<body>
		<canvas id="canvas"></canvas>
	</body>
</html>
Run codeHide result

If you don’t see an error after executing the code snippet, try moving the mouse around the screen arbitrarily.

However, after I move the mouse, I noticed that some of the balls seem to stick to the bottom of the screen.

enter image description here

I have been working on this for the last 8 hours, just to be dumbfounded. The code is relatively simple, so I don't think it was an obvious mistake.

By the way, I'm going to add +500 bounty in 2 days

+4
source share
1 answer

Your problem is collision detection:

if (circle.y + circle.radius/2 > canvas.height) {
    circle.velY*=-Math.sqrt(bounciness);
}

, . , , - , , , , ...

, , "" :

var inGround = circle.y + circle.radius - canvas.height;
if (inGround >= 0) {
    circle.velY *= -Math.sqrt(bounciness);
    circle.y -= 2*inGround;
}

:

var canvas = document.getElementById("canvas"),
    ctx = canvas.getContext('2d');

//jupiter gravity divided by 10 for testing purposes
g = 24.79/10;
canvas.width = window.innerWidth - 50;
canvas.height = window.innerHeight - 22.5;
bounciness = (1/2)
var spawnrate = 16;
var inertia = 0.00075;
var gravity = g/25;
players = []
then = new Date()/1000;
moved = false;
function getPosition(event){
	mouseX = event.clientX;
	mouseY = event.clientY;
	if(moved == false){
		update();
		moved = true;
	}
}
function addCircle(){
    players.push({x: mouseX, y: mouseY, color: '#000000', radius: 10, velY: 0, velX: 2, jumped: false, jump: 0.02, max: 0});
}
first = new Date();
function update(){
        ctx.clearRect(0, 0, canvas.width, canvas.height);
	t = new Date() - first;
	now = new Date() / 1000;
	if(now-then >= 1/spawnrate){
		then = now;
		addCircle();
	}
	for(var c = 0; c < players.length; c++){
		circle = players[c];
		circle.y+=circle.velY;
		circle.x+=circle.velX;
		circle.velX-=inertia;
		circle.velY+=gravity;
		if(Math.abs(circle.velY) > Math.abs(circle.max)){
			circle.max = circle.velY;
		}
        var inGround = circle.y + circle.radius - canvas.height;
		if(inGround >= 0){
			circle.velY *= -Math.sqrt(bounciness);
            circle.y -= 2*inGround;
		}
		updateCircle(circle);
		if(circle.x > canvas.width){
			players.splice(c, 1);
		}

	}
        setTimeout(update, 10);
}

function drawLine(x1, y1, x2, y2){
	ctx.beginPath();
	ctx.moveTo(x1, y1);
	ctx.lineTo(x2, y2);
	ctx.stroke();
}

function updateCircle(player){
        ctx.fillStyle = player.color;
        ctx.beginPath();
        ctx.arc(player.x, player.y, player.radius, 0, Math.PI * 2);
        ctx.fill();
}

window.addEventListener("mousemove", getPosition, false);
if(moved == true){
	update();
}
#canvas{
    display: block;
}
<!DOCTYPE html>
<html>
	<head>
		<title>Bounce</title>
	</head>
	<body>
		<canvas id="canvas"></canvas>
	</body>
</html>
Hide result
+7

All Articles