Reputation: 10206
I am starting on a physics/particle simulator and I am having some trouble with collision detection:
http://mmhudson.com/physics.html
Im not so much looking for a code solution, but someone to explain the issue to me conceptually.
The way it works is I check to see if the particle is going to be inside/intersect with the object when it is next moved. If it is, the gravity multiplier is reversed so its direction is reversed.
The equation for movement I use is:
Next location = current speed + rate of gravity + current location
Where speed is the gravity multiplier
Hopefully someone has seen an issue like this before or is willing to check out the source of my page.
Any help at all is greatly appreciated
Upvotes: 0
Views: 195
Reputation: 517
No conceptual explanation, but a bunch of random observations:
I'd recommend adding canvas width/height variables and comparing them against the particle position. Right now, your particles keep falling even if they drop off the canvas. Something like:
if( particles[i][1] > height )
particles.splice(i,1);
newPY < objects[k][2] + objects[k][3] + radius
is really weird. What are you getting from this? Adding the width and height of the objects and the particle radius? If you remove this part, particles will bounce off objects as long as they have "momentum".
As for momentum, I assume you want to figure out how to stop the particles from falling through the objects. Given current code, I'd do this: add a fifth variable to the particle, defaulting to the height of the canvas. Then, once you find out that you have an impact, save the impact position to the particle and after the loop, check if the particle is below that point. If so, reset it to that point. Dirty fix, but hey, it works. I've added the complete loop below that worked for me. To stop the objects from being wiped out by the clearRect method, maybe consider redrawing them.
You are checking for particles on top of the objects only, but I assume the "falling through" aspect is part of the bug you asked about, so not too important at the moment:
particles[i][1] < objects[k][1] + objects[k][3] + radius
Could be however, if you decided to play around and reduce gravity, so that particles would instead gain momentum and bounce against objects above.
As for your objCheck variable, you confuse the width for y in the last && part. It should be:
mY < objects[i][1] + objects[i][3] + radius
instead of
mY < objects[i][2] + objects[i][3] + radius
Right now, your objCheck is not working.
Also
for(var i=0; i < particles.length; i++) {
var clrRadius = 2*radius;
canvas.clearRect(particles[i][0]-radius, particles[i][1]-radius, clrRadius, clrRadius);
}
is better than
for(var i=0; i < particles.length; i++){
var clrRadius = radius + 4;
canvas.clearRect(particles[i][0]-(clrRadius/2), particles[i][1]-(clrRadius/2), clrRadius, clrRadius);
}
edit: Seems you changed the code, since I last checked it, so the above might no longer be relevant!
edit2: added particle stopping fix. Here's the complete gravity loop:
for(var i=0; i<particles.length; i++){
var clrRadius = 2*radius;
canvas.clearRect(particles[i][0]-radius, particles[i][1]-radius, clrRadius, clrRadius);
}
for(var i=0; i < particles.length; i++){
var newPY = particles[i][1] += particles[i][2] + particles[i][3];
for(var k=0; k<objects.length; k++){
if(
//particle
particles[i][0] > objects[k][0] - radius &&
particles[i][0] < objects[k][0] + objects[k][2] + radius &&
particles[i][1] > objects[k][1] - radius &&
particles[i][1] < objects[k][1] + objects[k][3] + radius //&&
){
//reverse gravity
particles[i][2] = particles[i][2] * -1;
particles[i][5] = objects[k][1] - radius;
}
}
particles[i][2] += particles[i][3]*weight;
particles[i][1] += particles[i][2];
if( particles[i][1] > particles[i][5] )
particles[i][1] = particles[i][5];
if( particles[i][1] > height )
particles.splice(i,1);
}
for(var i=0; i <particles.length; i++){
canvas.fillStyle = "#000";
canvas.beginPath();
canvas.arc(particles[i][0], particles[i][1], radius, 0, Math.PI*2, true);
canvas.closePath();
canvas.fill();
}
Upvotes: 2
Reputation: 1
I wouldn't use a gravity multiplier.
Each object should look something like this:
var circle = {
x: 0, // x position
y: 0, // y position
dx: 0, // x velocity
dy: 0 // y velocity
}
To update the particle, multiply velocity (dx, dy) by some time interval and add this to the current position.
Every cycle, add some change in velocity as a result of gravity.
If you detect a collision change the velocity so the circles bounce off each other. An example of this would be:
// In a collision, simply reverse the direction of movement
// so the circles move away from each other.
function onCollision(circleA, circleB) {
circleA.dx *= -1;
circleA.dy *= -1;
circleB.dx *= -1;
circleB.dy *= -1;
}
Upvotes: 0