NTNUJAVA Virtual Physics LaboratoryEnjoy the fun of physics with simulations! Backup site http://enjoy.phy.ntnu.edu.tw/ntnujava/
May 26, 2020, 08:21:18 am

Establish Good support system. ...Wisdom

 Pages: 1 ... 4 5 [6]   Go Down
 Author Topic: 2D Collision  (Read 500297 times) 0 Members and 3 Guests are viewing this topic. Click to toggle author information(expand message area).
Fu-Kwun Hwang
Hero Member

Offline

Posts: 3085

 « Embed this message Reply #150 on: October 08, 2010, 06:06:57 pm » posted from:Taipei,T'ai-pei,Taiwan

You have the following code
Code:
dt = (r1+r2-d)/(vp1-vp2);
What if vp1==vp2???

You also have the following code

Code:
CGFloat d=sqrt(dx*dx+dy*dy);
//First calculate the component of velocity in the direction of (dx,dy)
CGFloat vp1= speed.x*dx/d+speed.y*dy/d;
CGFloat vp2= collideeSpeed.x*dx/d+collideeSpeed.y*dy/d;

What if d==0???

It could also be other kind of bug in your code. You need to trace the code (find out value for variables) and try to find out the problem.
It is not easy to find the bug.  Good luck!
 Logged
mediakitchen
Newbie

Offline

Posts: 9

 « Embed this message Reply #151 on: October 08, 2010, 11:12:46 pm » posted from:Wantage,Oxfordshire,United Kingdom

I am very pleased to have found this site and especially this thread. I am creating a ball based game in a language called Lua and have been trying to use your code as follows:

I have multiple balls in the game. The code is so close to working perfectly - just occasionally I get a badly behaved ball that appears to shoot off the screen extremely fast.

Would appreciate if you can spot any issues. I have a maximum speed of 14. Also please note I have a tempX and tempY property for each ball. Once I have checked for all the collisions with all the balls. I then set their actual screen x and y positions.

Hope you can help me identify any issues with my code.

Thanks

Paul

Code:

local function checkForCollisionWithBall( firstBallRef, secondBallRef )

-- ------------------
-- Set some constants
-- ------------------

local D = 14 -- Radius of ball
local D2 = (2 * D) * (2 * D) -- Radius squared

-- ---------------------------------------------
-- Calculate distance between balls on both axis
-- ---------------------------------------------

local dx = secondBallRef.tempX - firstBallRef.tempX -- horizontal distance between the 2 balls
local dy = secondBallRef.tempY - firstBallRef.tempY -- vertical distance between the 2 balls

local dxy = (dx * dx) + (dy * dy)

if (dxy < 0.00001) then

return

end

if (dxy < D2) then

-- --------------------
-- We have a collision!
-- --------------------

-- ------------------------------------------------------------------------------
-- We now perform the square root to calculate the distance between the two balls
-- ------------------------------------------------------------------------------

dxy = mSqrt(dxy)

local cs = dx/dxy
local sc = dy/dxy

-- -----------------------------------------------------------
-- Calculate component of velocity in the direction of (dx,dy)
-- -----------------------------------------------------------

local vp1 = firstBallRef.horizontalVelocity * cs + firstBallRef.verticalVelocity * sc
local vp2 = secondBallRef.horizontalVelocity * cs + secondBallRef.verticalVelocity * sc

local dt = (D + D - dxy) / (vp1 - vp2)

firstBallRef.tempX = firstBallRef.tempX - (firstBallRef.horizontalVelocity * dt)
firstBallRef.tempY = firstBallRef.tempY - (firstBallRef.verticalVelocity * dt)

secondBallRef.tempX = secondBallRef.tempX - (secondBallRef.horizontalVelocity * dt)
secondBallRef.tempY = secondBallRef.tempY - (secondBallRef.verticalVelocity * dt)

dx = secondBallRef.tempX - firstBallRef.tempX -- horizontal distance between the 2 balls
dy = secondBallRef.tempY - firstBallRef.tempY -- vertical distance between the 2 balls

local distance = mSqrt(dx * dx + dy * dy)
local ax = dx/distance
local ay = dy/distance

local va1 = (firstBallRef.horizontalVelocity * ax + firstBallRef.verticalVelocity * ay)
local vb1 = (-1 * firstBallRef.horizontalVelocity * ay + firstBallRef.verticalVelocity * ax)

local va2 = (secondBallRef.horizontalVelocity * ax + secondBallRef.verticalVelocity * ay)
local vb2 = (-1 * secondBallRef.horizontalVelocity * ay + secondBallRef.verticalVelocity * ax)

local vaP1 = va1 + (1 + 1) * (va2 - va1)/(1 + 1/1)
local vaP2 = va2 + (1 + 1) * (va1 - va2)/(1 + 1/1)

firstBallRef.horizontalVelocity = vaP1 * ax - vb1 * ay
firstBallRef.verticalVelocity = vaP1 * ay + vb1 * ax

secondBallRef.horizontalVelocity = vaP2 * ax - vb2 * ay
secondBallRef.verticalVelocity = vaP2 * ay + vb2 * ax

firstBallRef.tempX = firstBallRef.tempX + firstBallRef.horizontalVelocity * dt
firstBallRef.tempY = firstBallRef.tempY + firstBallRef.verticalVelocity * dt

secondBallRef.tempX = secondBallRef.tempX + secondBallRef.horizontalVelocity * dt
secondBallRef.tempY = secondBallRef.tempY + secondBallRef.verticalVelocity * dt

end

end

 Logged
lunayo
Newbie

Offline

Posts: 6

 « Embed this message Reply #152 on: October 09, 2010, 02:57:47 am » posted from:Jakarta,Jakarta Raya,Indonesia

I am very pleased to have found this site and especially this thread. I am creating a ball based game in a language called Lua and have been trying to use your code as follows:

I have multiple balls in the game. The code is so close to working perfectly - just occasionally I get a badly behaved ball that appears to shoot off the screen extremely fast.

Would appreciate if you can spot any issues. I have a maximum speed of 14. Also please note I have a tempX and tempY property for each ball. Once I have checked for all the collisions with all the balls. I then set their actual screen x and y positions.

Hope you can help me identify any issues with my code.

Thanks

Paul

Code:

local function checkForCollisionWithBall( firstBallRef, secondBallRef )

-- ------------------
-- Set some constants
-- ------------------

local D = 14 -- Radius of ball
local D2 = (2 * D) * (2 * D) -- Radius squared

-- ---------------------------------------------
-- Calculate distance between balls on both axis
-- ---------------------------------------------

local dx = secondBallRef.tempX - firstBallRef.tempX -- horizontal distance between the 2 balls
local dy = secondBallRef.tempY - firstBallRef.tempY -- vertical distance between the 2 balls

local dxy = (dx * dx) + (dy * dy)

if (dxy < 0.00001) then

return

end

if (dxy < D2) then

-- --------------------
-- We have a collision!
-- --------------------

-- ------------------------------------------------------------------------------
-- We now perform the square root to calculate the distance between the two balls
-- ------------------------------------------------------------------------------

dxy = mSqrt(dxy)

local cs = dx/dxy
local sc = dy/dxy

-- -----------------------------------------------------------
-- Calculate component of velocity in the direction of (dx,dy)
-- -----------------------------------------------------------

local vp1 = firstBallRef.horizontalVelocity * cs + firstBallRef.verticalVelocity * sc
local vp2 = secondBallRef.horizontalVelocity * cs + secondBallRef.verticalVelocity * sc

local dt = (D + D - dxy) / (vp1 - vp2)

firstBallRef.tempX = firstBallRef.tempX - (firstBallRef.horizontalVelocity * dt)
firstBallRef.tempY = firstBallRef.tempY - (firstBallRef.verticalVelocity * dt)

secondBallRef.tempX = secondBallRef.tempX - (secondBallRef.horizontalVelocity * dt)
secondBallRef.tempY = secondBallRef.tempY - (secondBallRef.verticalVelocity * dt)

dx = secondBallRef.tempX - firstBallRef.tempX -- horizontal distance between the 2 balls
dy = secondBallRef.tempY - firstBallRef.tempY -- vertical distance between the 2 balls

local distance = mSqrt(dx * dx + dy * dy)
local ax = dx/distance
local ay = dy/distance

local va1 = (firstBallRef.horizontalVelocity * ax + firstBallRef.verticalVelocity * ay)
local vb1 = (-1 * firstBallRef.horizontalVelocity * ay + firstBallRef.verticalVelocity * ax)

local va2 = (secondBallRef.horizontalVelocity * ax + secondBallRef.verticalVelocity * ay)
local vb2 = (-1 * secondBallRef.horizontalVelocity * ay + secondBallRef.verticalVelocity * ax)

local vaP1 = va1 + (1 + 1) * (va2 - va1)/(1 + 1/1)
local vaP2 = va2 + (1 + 1) * (va1 - va2)/(1 + 1/1)

firstBallRef.horizontalVelocity = vaP1 * ax - vb1 * ay
firstBallRef.verticalVelocity = vaP1 * ay + vb1 * ax

secondBallRef.horizontalVelocity = vaP2 * ax - vb2 * ay
secondBallRef.verticalVelocity = vaP2 * ay + vb2 * ax

firstBallRef.tempX = firstBallRef.tempX + firstBallRef.horizontalVelocity * dt
firstBallRef.tempY = firstBallRef.tempY + firstBallRef.verticalVelocity * dt

secondBallRef.tempX = secondBallRef.tempX + secondBallRef.horizontalVelocity * dt
secondBallRef.tempY = secondBallRef.tempY + secondBallRef.verticalVelocity * dt

end

end

You have the following code
Code:
dt = (r1+r2-d)/(vp1-vp2);
What if vp1==vp2???

You also have the following code

Code:
CGFloat d=sqrt(dx*dx+dy*dy);
//First calculate the component of velocity in the direction of (dx,dy)
CGFloat vp1= speed.x*dx/d+speed.y*dy/d;
CGFloat vp2= collideeSpeed.x*dx/d+collideeSpeed.y*dy/d;

What if d==0???

It could also be other kind of bug in your code. You need to trace the code (find out value for variables) and try to find out the problem.
It is not easy to find the bug.  Good luck!

@prof, i've found the bug , it's on collision.
@mediakitchen i have multiple balls , how do you compare each array without having compare the same one.
for example Array 1 (ball1,ball2,ball3), Array 2 (ball1,ball2,ball3) how do you skip the same last one?
 Logged
Fu-Kwun Hwang
Hero Member

Offline

Posts: 3085

 « Embed this message Reply #153 on: October 09, 2010, 10:31:14 am » posted from:,,Taiwan

Make a double loop
i=0 to n
j=i+1 to n

 Logged
lunayo
Newbie

Offline

Posts: 6

 « Embed this message Reply #154 on: October 09, 2010, 01:13:07 pm » posted from:Jakarta,Jakarta Raya,Indonesia

Make a double loop
i=0 to n
j=i+1 to n

Thank you professor, I made it!!  . You are a very good teacher.
 Logged
mediakitchen
Newbie

Offline

Posts: 9

 « Embed this message Reply #155 on: October 09, 2010, 02:00:49 pm » posted from:Wantage,Oxfordshire,United Kingdom

Thank you for the reply. I should have included my code that shows where I call the collision function.

I loop through all balls and check each against all the others whilst ensuring that I do not compare the same one with itself

Code:

for (var i = 0; i < howManyBalls; i++) {

ball1 = ballObjects[i]

for (var j = 0; i < howManyBalls; j++) {

ball2 = ballObjects[j]

if (ball1 != ball2) {

checkForCollisionWithBall(ball1, ball2 )
}

}

}

Is this equivalent to the double loop?

Quote
You have the following code
Code:

dt = (r1+r2-d)/(vp1-vp2);

What if vp1==vp2???

You also have the following code

Code:

CGFloat d=sqrt(dx*dx+dy*dy);
//First calculate the component of velocity in the direction of (dx,dy)
CGFloat vp1= speed.x*dx/d+speed.y*dy/d;
CGFloat vp2= collideeSpeed.x*dx/d+collideeSpeed.y*dy/d;

What if d==0???

It could also be other kind of bug in your code. You need to trace the code (find out value for variables) and try to find out the problem.
It is not easy to find the bug.  Good luck!

How do I deal with the situation where vp1 = vp2 or d = 0?

Thank you

Paul
 Logged
Fu-Kwun Hwang
Hero Member

Offline

Posts: 3085

 « Embed this message Reply #156 on: October 09, 2010, 02:54:03 pm » posted from:,,Taiwan

The problem is due to your double loops.

For example: when i=0, j=0 it is not collision between two different balls.
Think about what you were doing and you will understand why it is not working.

You should change the second loop to
Code:
for (var j = i; i < howManyBalls; j++)
 Logged
mediakitchen
Newbie

Offline

Posts: 9

 « Embed this message Reply #157 on: October 09, 2010, 03:02:19 pm » posted from:Wantage,Oxfordshire,United Kingdom

Thank you for the fast reply.

Surely my line of code that says if (ball1 != ball2) will prevent checking one ball against itself? There was a small typo in my code I typed in

Code:

for (var j = 0; i < howManyBalls; j++) {

Should have been

Code:

for (var j = 0; j < howManyBalls; j++) {

Code:

for (var i = 0; i < howManyBalls; i++) {

ball1 = ballObjects[i]

for (var j = 0; j < howManyBalls; j++) {

ball2 = ballObjects[j]

if (ball1 != ball2) {

checkForCollisionWithBall(ball1, ball2 )
}

}

If I use the following:

Code:
for (var j = i; i < howManyBalls; j++)

Surely if i = 2 then j will never have a value of 0 or 1?

Thank you

Paul
 Logged
mediakitchen
Newbie

Offline

Posts: 9

 « Embed this message Reply #158 on: October 09, 2010, 04:04:48 pm » posted from:London,London, City of,United Kingdom

With multiple balls and when looping through all balls checking for collision. If 2 balls collide we use dt to reposition them at point of collision. Do we also need to reposition all other balls to their position based on dt? Just wondered if this was possible cause of problem?

Though perhaps my double loop is still not right?

Thank you so much for help

Paul
 Logged
Fu-Kwun Hwang
Hero Member

Offline

Posts: 3085

 « Embed this message Reply #159 on: October 09, 2010, 05:34:28 pm » posted from:,,Taiwan

There is another problem even you rule out case for  i==j

Try to set howManyBalls to 3 and following the loop.
Write down what you were asking the computer to do.
And you will find out what is the problem.

After you figure out the problem, then check out my previous suggestion for the double loop.

You need to figure out by yourself!

Code:
Surely if i = 2 then j will never have a value of 0 or 1?

The collision between 0-1 and 0-2 should have been processed when outer loop i=0, right?
 Logged
mediakitchen
Newbie

Offline

Posts: 9

 « Embed this message Reply #160 on: October 09, 2010, 05:54:45 pm » posted from:Wantage,Oxfordshire,United Kingdom

Thank so very much. I will try what you suggested and hope I find the problem.
 Logged
mediakitchen
Newbie

Offline

Posts: 9

 « Embed this message Reply #161 on: October 10, 2010, 04:19:18 am » posted from:Wantage,Oxfordshire,United Kingdom

I have spent the day trying to figure this out with no joy.

I have created two test movies using Flash, one with 3 balls and one with 5, the links are as follows:

http://www.mediakitchen.co.uk/physics/testFile3balls.html
http://www.mediakitchen.co.uk/physics/testFile5balls.html

Simply click on the ball at the bottom and drag mouse to launch the ball towards the other balls. If you pull it back as much as possible before releasing mouse it will propell the ball faster. It is when it goes faster the problem occurs, especially when you aim towards the middle of the group of upper balls. It is random when it doesn't work so please try a few times.

Ok I thought I  found the problem and changed my loop to a double loop. I could really do with help fixing this problem.

Thanks

Paul

Code:

function initialiseGameConstants() {

objGame.friction = 0.8;

objGame.dV = 0.08;

objGame.D = 14; // Ball radius
objGame.D2 = (2 * objGame.D) * (2 * objGame.D)

}

function moveBallObjects(e:Event):void {

var howManyBallObjects:Number = objGame.ballObjects.length;

for (var i:Number = 0; i < howManyBallObjects; i++) {

var ballObject = objGame.ballObjects[i];

var V = (ballObject.horizontalVelocity * ballObject.horizontalVelocity) + (ballObject.verticalVelocity * ballObject.verticalVelocity);

if (V == 0) {

continue;
}

V = Math.sqrt(V);

var k = (V - objGame.dV) / V;

if (k < 0)
{
k = 0;
} // end if

ballObject.horizontalVelocity = ballObject.horizontalVelocity * k;
ballObject.verticalVelocity = ballObject.verticalVelocity * k;

ballObject.tempX = ballObject.tempX + ballObject.horizontalVelocity;
ballObject.tempY = ballObject.tempY + ballObject.verticalVelocity;

objGame.numTotalBalls = 3;

for (var j:Number = 0; j < objGame.numTotalBalls; j++) {

var firstBallObject = objGame.ballObjects[j];

for (var f:Number = (j + 1); f < objGame.numTotalBalls; f++) {

var otherBallMC = objGame.ballObjects[f];

checkForCollisionWithBall(firstBallObject, otherBallMC);

}

}

// ---------------------------------
// Update Position of Ball On Screen
// ---------------------------------

ballObject.x = ballObject.tempX;
ballObject.y = ballObject.tempY;

}

}

function checkForCollisionWithBall(firstBallRef:MovieClip, secondBallRef:MovieClip):void {

var dx = secondBallRef.tempX - firstBallRef.tempX // horizontal distance between the 2 balls
var dy = secondBallRef.tempY - firstBallRef.tempY // vertical distance between the 2 balls

var dxy = (dx * dx) + (dy * dy)

if (dxy < 0.00001) {

return

}

if (dxy < objGame.D2) {

// --------------------
// We have a collision!
// --------------------

// ------------------------------------------------------------------------------
// We now perform the square root to calculate the distance between the two balls
// ------------------------------------------------------------------------------

dxy = Math.sqrt(dxy)

var cs = dx/dxy
var sc = dy/dxy

// -----------------------------------------------------------
// Calculate component of velocity in the direction of (dx,dy)
// -----------------------------------------------------------

var vp1 = firstBallRef.horizontalVelocity * cs + firstBallRef.verticalVelocity * sc
var vp2 = secondBallRef.horizontalVelocity * cs + secondBallRef.verticalVelocity * sc

var dt = (objGame.D + objGame.D - dxy) / (vp1 - vp2)

firstBallRef.tempX = firstBallRef.tempX - (firstBallRef.horizontalVelocity * dt)
firstBallRef.tempY = firstBallRef.tempY - (firstBallRef.verticalVelocity * dt)

secondBallRef.tempX = secondBallRef.tempX - (secondBallRef.horizontalVelocity * dt)
secondBallRef.tempY = secondBallRef.tempY - (secondBallRef.verticalVelocity * dt)

dx = secondBallRef.tempX - firstBallRef.tempX // horizontal distance between the 2 balls
dy = secondBallRef.tempY - firstBallRef.tempY // vertical distance between the 2 balls

var distance = Math.sqrt(dx * dx + dy * dy)
var ax = dx/distance
var ay = dy/distance

var va1 = (firstBallRef.horizontalVelocity * ax + firstBallRef.verticalVelocity * ay)
var vb1 = (-1 * firstBallRef.horizontalVelocity * ay + firstBallRef.verticalVelocity * ax)

var va2 = (secondBallRef.horizontalVelocity * ax + secondBallRef.verticalVelocity * ay)
var vb2 = (-1 * secondBallRef.horizontalVelocity * ay + secondBallRef.verticalVelocity * ax)

var vaP1 = va1 + (1 + 1) * (va2 - va1)/(1 + 1/1)
var vaP2 = va2 + (1 + 1) * (va1 - va2)/(1 + 1/1)

firstBallRef.horizontalVelocity = vaP1 * ax - vb1 * ay
firstBallRef.verticalVelocity = vaP1 * ay + vb1 * ax

secondBallRef.horizontalVelocity = vaP2 * ax - vb2 * ay
secondBallRef.verticalVelocity = vaP2 * ay + vb2 * ax

firstBallRef.tempX = firstBallRef.tempX + firstBallRef.horizontalVelocity * dt
firstBallRef.tempY = firstBallRef.tempY + firstBallRef.verticalVelocity * dt

secondBallRef.tempX = secondBallRef.tempX + secondBallRef.horizontalVelocity * dt
secondBallRef.tempY = secondBallRef.tempY + secondBallRef.verticalVelocity * dt

}

}

 Logged
mediakitchen
Newbie

Offline

Posts: 9

 « Embed this message Reply #162 on: October 10, 2010, 04:36:07 am » posted from:Wantage,Oxfordshire,United Kingdom

Further to my last post, I have printed some variable values to the screen when the problem occurs as follows:

Code:

dxy = 11.183594089759662
cs = -0.9113209567523853
sc = -0.41169662833683374
vp1 = 10.423261322708719
vp2 = 0
dt = 1.6133535742410243
firstBallRef.tempX = 150.00761013707466
firstBallRef.tempY = 179.69153092093967
secondBallRef.tempX = 120.18423352873543
secondBallRef.tempY= 104.91271705850214
firstBallRef.horizontalVelocity = 5.118247803194922
firstBallRef.verticalVelocity = -1.4318442742343485
secondBallRef.horizontalVelocity = -6.0840764405175305
secondBallRef.verticalVelocity = -21.748043021508227
dxy = 20.415665302423797
cs = 0.9706157589148952
sc = -0.24063467860236176
vp1 = -0.6719671288981877
vp2 = 0
dt = -11.286764443391895
firstBallRef.tempX = 32.46887484970526
firstBallRef.tempY = -133.54646421285148
secondBallRef.tempX = 227.71535867903015
secondBallRef.tempY= 338.4591812713536
firstBallRef.horizontalVelocity = 1.6874473756267157
firstBallRef.verticalVelocity = -0.6207144175197532
secondBallRef.horizontalVelocity = -7.771523816144245
secondBallRef.verticalVelocity = -21.12732860398847
dxy = 21.703543611196096
cs = -0.23089377668368133
sc = 0.9729789637442047
vp1 = -2.342372578705536
vp2 = -18.295318544168257
dt = 0.3946892569206588
firstBallRef.tempX = 179.14739832875304
firstBallRef.tempY = 163.96685005743075
secondBallRef.tempX = 174.03981574604762
secondBallRef.tempY= 200.25638673254542
firstBallRef.horizontalVelocity = 4.778078082260453
firstBallRef.verticalVelocity = -20.52327562601023
secondBallRef.horizontalVelocity = -7.70027935503791
secondBallRef.verticalVelocity = -1.3810100832728573
dxy = 14.346250582823185
cs = -0.9694056603163411
sc = -0.24546418424413502
vp1 = 0.4042924324869883
vp2 = 0
dt = 33.77196385593056
firstBallRef.tempX = 37.17943584519696
firstBallRef.tempY = 836.9689122027011
secondBallRef.tempX = 316.72790067410847
secondBallRef.tempY= -553.4474215064265
firstBallRef.horizontalVelocity = 0.4152722629195494
firstBallRef.verticalVelocity = 0.08786827300331551
secondBallRef.horizontalVelocity = 4.344665927632815
secondBallRef.verticalVelocity = -20.53322763415942

I notice the value of dt is very high e.g dt = 33.77196385593056

Should dt have such a high value and if not, any idea why it is having this value?

Thank you

Paul
 « Last Edit: October 10, 2010, 04:39:00 am by mediakitchen » Logged
Fu-Kwun Hwang
Hero Member

Offline

Posts: 3085

 « Embed this message Reply #163 on: October 10, 2010, 09:04:32 am » posted from:,,Taiwan

As I have said several time, there is an assumption for the code I presented (to process the collision).
It require : the time step is smaller enough so that the movement of each ball should be smaller than radius of both balls.
i.e. v*dt<< r

Code:
ballObject.tempX = ballObject.tempX + ballObject.horizontalVelocity;
Your time step is always 1.
You should change the time step to a small value when velocity is too large.

Or you should make another loop to make the ball move with smaller steps.
i.e. ballObject.tempX = ballObject.tempX + ballObject.horizontalVelocity*dt;
with proper dt value.

Another issue is you are processing collision before all the particles are moving to the next time step.
You have loop i to move particle , inside loop i
you have loop j and loop f to process collision,

I would suggest you move loop j and loop f outside loop i.
Process collision after all particles have move one time step.

And for loop j and loop f: you are still have both loop from 0-numTotalBalls.
It seems that you did not listen to my suggestion. The code was processing collision twice.
for example: if you have three particles  j loop from 0-2, f:loop from 0-2
your code is doing the following (j,f) pairs
(0,0): self collision --- not real
(0,1):collision between particle 0 and particle 1
(0,2):collision between particle 0 and particle 2
(1,0):collision between particle 1 and particle 0--- this should have been take care in (0,1)
(1,1):self collision --- not real
(1,2):collision between particle 2 and particle 0--- this should have been take care in (0,2)
(2,0):collision between particle 2 and particle 1--- this should have been take care in (1,2)
(2,1):collision between particle 2 and particle 2
(2,2); self collision --- not real

You should spend some time try to draw a conceptual flow to understand what you were really doing.
 Logged
mediakitchen
Newbie

Offline

Posts: 9

 « Embed this message Reply #164 on: October 10, 2010, 12:17:42 pm » posted from:Wantage,Oxfordshire,United Kingdom

With regards the time, my movie is running at 30FPS therefore I was under the impression that the largest time slot was 1/30 seconds. I assume that the "actionLoop" function (see below) is being called 30 times per second.  Please can you explain this.

I thought my loop was correct as when I traced which balls it was comparing it had the following:

Code:

firstBallRef = ball1
secondBallRef = ball2
firstBallRef = ball1
secondBallRef = ball3
firstBallRef = ball1
secondBallRef = ball4
firstBallRef = ball1
secondBallRef = ball5
firstBallRef = ball2
secondBallRef = ball3
firstBallRef = ball2
secondBallRef = ball4
firstBallRef = ball2
secondBallRef = ball5
firstBallRef = ball3
secondBallRef = ball4
firstBallRef = ball3
secondBallRef = ball5
firstBallRef = ball4
secondBallRef = ball5

I have moved my code to do the collision detection after the code to calculate all the ball object new positions based on your recommendation:

Quote
Another issue is you are processing collision before all the particles are moving to the next time step.

Code:
function actionLoop(e:Event):void {

calculateBallObjectNewPositions()
checkForCollisions()
updateBallPositions()

}

Unfortunately I am still getting the same error (New version here http://www.mediakitchen.co.uk/physics/testFile5v2balls.html ) but assume this must be due to the dt problem as the following is an example of my variable values when the issue occurs.

Code:
firstBallRef.tempX = 164.12788355997395
firstBallRef.tempY = 172.2370476331055
secondBallRef.tempX = 115.87211644002605
secondBallRef.tempY= 112.1629523668944
firstBallRef.horizontalVelocity = 9.36283073039942
firstBallRef.verticalVelocity = -4.751832309742385
secondBallRef.horizontalVelocity = -9.36283073039942
secondBallRef.verticalVelocity = -18.44816769025763
firstBallRef = ball1
secondBallRef = ball3
firstBallRef = ball1
secondBallRef = ball4
firstBallRef = ball1
secondBallRef = ball5
firstBallRef = ball2
secondBallRef = ball3
firstBallRef = ball2
secondBallRef = ball4
dxy = 27.020217899991174
cs = 0.8929566611667419
sc = -0.4501426454780135
vp1 = -0.056295059772248024
vp2 = 0
dt = -17.404406425230103
firstBallRef.tempX = -70.12509047107508
firstBallRef.tempY = -194.96160633456583
secondBallRef.tempX = 325.9972069111011
secondBallRef.tempY= 407.12455870146016
firstBallRef.horizontalVelocity = 1.3239575671590866
firstBallRef.verticalVelocity = -0.8017997994089945
secondBallRef.horizontalVelocity = -10.686788297558504
secondBallRef.verticalVelocity = -17.646367890848634

Note that the position of secondBallRef jumps from being x = 115 to x = 407, a very large movement and hence the issue I am experiencing.

Here is my updated code:

Code:
function actionLoop(e:Event):void {

calculateBallObjectNewPositions()
checkForCollisions()
updateBallPositions()

}

function calculateBallObjectNewPositions():void {

var howManyBallObjects:Number = objGame.ballObjects.length;

for (var i:Number = 0; i < howManyBallObjects; i++) {

var ballObject = objGame.ballObjects[i];

if (ballObject.alpha < 1) {

var newScale = ballObject.scaleX * 0.98;

ballObject.alpha = ballObject.alpha - 0.1;
ballObject.scaleX = newScale;
ballObject.scaleY = newScale;

if (ballObject.alpha <= 0) {

ballObject.horizontalVelocity = 0;
ballObject.verticalVelocity = 0;

continue;

} // end if

}

var V = (ballObject.horizontalVelocity * ballObject.horizontalVelocity) + (ballObject.verticalVelocity * ballObject.verticalVelocity);

if (V == 0)
{
continue;
} else {

}

V = Math.sqrt(V);

var k = (V - objGame.dV) / V;

if (k < 0)
{
k = 0;
} // end if

ballObject.horizontalVelocity = ballObject.horizontalVelocity * k;
ballObject.verticalVelocity = ballObject.verticalVelocity * k;

ballObject.tempX = ballObject.tempX + ballObject.horizontalVelocity;
ballObject.tempY = ballObject.tempY + ballObject.verticalVelocity;

}

}

function checkForCollisions():void {

objGame.numTotalBalls = 5;

for (var j:Number = 0; j < objGame.numTotalBalls; j++) {

var firstBallObject = objGame.ballObjects[j];
for (var f:Number = (j + 1); f < objGame.numTotalBalls; f++) {

var otherBallMC = objGame.ballObjects[f];

checkForCollisionWithBall(firstBallObject, otherBallMC);

}

}

}

function checkForCollisionWithBall(firstBallRef:MovieClip, secondBallRef:MovieClip):void {

trace ("firstBallRef = " + firstBallRef.instanceNameValue);
trace ("secondBallRef = " + secondBallRef.instanceNameValue);

var dx = secondBallRef.tempX - firstBallRef.tempX // horizontal distance between the 2 balls
var dy = secondBallRef.tempY - firstBallRef.tempY // vertical distance between the 2 balls

var dxy = (dx * dx) + (dy * dy)

if (dxy < 0.00001) {

return

}

if (dxy < objGame.D2) {

// --------------------
// We have a collision!
// --------------------

// ------------------------------------------------------------------------------
// We now perform the square root to calculate the distance between the two balls
// ------------------------------------------------------------------------------

dxy = Math.sqrt(dxy)

var cs = dx/dxy
var sc = dy/dxy

trace ("dxy = " + dxy);

trace ("cs = " + cs);
trace ("sc = " + sc);

// -----------------------------------------------------------
// Calculate component of velocity in the direction of (dx,dy)
// -----------------------------------------------------------

var vp1 = firstBallRef.horizontalVelocity * cs + firstBallRef.verticalVelocity * sc
var vp2 = secondBallRef.horizontalVelocity * cs + secondBallRef.verticalVelocity * sc

trace ("vp1 = " + vp1);
trace ("vp2 = " + vp2);

var dt = (objGame.D + objGame.D - dxy) / (vp1 - vp2)

firstBallRef.tempX = firstBallRef.tempX - (firstBallRef.horizontalVelocity * dt)
firstBallRef.tempY = firstBallRef.tempY - (firstBallRef.verticalVelocity * dt)

secondBallRef.tempX = secondBallRef.tempX - (secondBallRef.horizontalVelocity * dt)
secondBallRef.tempY = secondBallRef.tempY - (secondBallRef.verticalVelocity * dt)

dx = secondBallRef.tempX - firstBallRef.tempX // horizontal distance between the 2 balls
dy = secondBallRef.tempY - firstBallRef.tempY // vertical distance between the 2 balls

var distance = Math.sqrt(dx * dx + dy * dy)
var ax = dx/distance
var ay = dy/distance

var va1 = (firstBallRef.horizontalVelocity * ax + firstBallRef.verticalVelocity * ay)
var vb1 = (-1 * firstBallRef.horizontalVelocity * ay + firstBallRef.verticalVelocity * ax)

var va2 = (secondBallRef.horizontalVelocity * ax + secondBallRef.verticalVelocity * ay)
var vb2 = (-1 * secondBallRef.horizontalVelocity * ay + secondBallRef.verticalVelocity * ax)

var vaP1 = va1 + (1 + 1) * (va2 - va1)/(1 + 1/1)
var vaP2 = va2 + (1 + 1) * (va1 - va2)/(1 + 1/1)

firstBallRef.horizontalVelocity = vaP1 * ax - vb1 * ay
firstBallRef.verticalVelocity = vaP1 * ay + vb1 * ax

secondBallRef.horizontalVelocity = vaP2 * ax - vb2 * ay
secondBallRef.verticalVelocity = vaP2 * ay + vb2 * ax

firstBallRef.tempX = firstBallRef.tempX + firstBallRef.horizontalVelocity * dt
firstBallRef.tempY = firstBallRef.tempY + firstBallRef.verticalVelocity * dt

secondBallRef.tempX = secondBallRef.tempX + secondBallRef.horizontalVelocity * dt
secondBallRef.tempY = secondBallRef.tempY + secondBallRef.verticalVelocity * dt

trace ("dt = " + dt);

trace ("firstBallRef.tempX = " + firstBallRef.tempX);
trace ("firstBallRef.tempY = " + firstBallRef.tempY);

trace ("secondBallRef.tempX = " + secondBallRef.tempX);
trace ("secondBallRef.tempY= " + secondBallRef.tempY);

trace ("firstBallRef.horizontalVelocity = " + firstBallRef.horizontalVelocity);
trace ("firstBallRef.verticalVelocity = " + firstBallRef.verticalVelocity);

trace ("secondBallRef.horizontalVelocity = " + secondBallRef.horizontalVelocity);
trace ("secondBallRef.verticalVelocity = " + secondBallRef.verticalVelocity);

}

}

function updateBallPositions() {

var howManyBallObjects:Number = objGame.ballObjects.length;

for (var i:Number = 0; i < howManyBallObjects; i++) {

var ballObject = objGame.ballObjects[i];

ballObject.x = ballObject.tempX;
ballObject.y = ballObject.tempY;
}

}

It is so frustrating that this works 90% of the time.

Paul
 Logged
Fu-Kwun Hwang
Hero Member

Offline

Posts: 3085

 « Embed this message Reply #165 on: October 10, 2010, 04:26:43 pm » posted from:,,Taiwan

You should have noticed that the velocity of those two balls are not small when the problem occurs.
Your time step is 1, however, dt=-17.4 so it is the problem. The time step 1 is too large.

I know that you are under a fix time step. 30FPS or whatever time step by your program.

You are doing one step of particle movement for each frame.
Here is my suggestion for your code
Code:
function actionLoop(e:Event):void {

calculateBallObjectNewPositions()
checkForCollisions()
updateBallPositions()

}

Your time step is 1 for the above 3 functions. Please change it to smaller value. e.g. change it to 0.1

You can change code like
Code:
ballObject.tempX = ballObject.tempX + ballObject.horizontalVelocity;
ballObject.tempY = ballObject.tempY + ballObject.verticalVelocity;
to
Code:
ballObject.tempX = ballObject.tempX + ballObject.horizontalVelocity*deltat;
ballObject.tempY = ballObject.tempY + ballObject.verticalVelocity*deltat;
and define deltat=0.1 (Because we change to smaller time step 0.1 so we need to calculate it 10 times)

then, change actionLoop
Code:
function actionLoop(e:Event):void {
for (var i:Number = 0; i < 10; i++) {
calculateBallObjectNewPositions()
checkForCollisions()
updateBallPositions()
}
}

Now, you are calculating it with 300FPS, even the program only update the view with 30FPS.

You can change 'deltat' to other values and change the number of outer loop (1/deltat) accordingly.
It is also possible to add code to adjust deltat according to velocity distribution (in some case, this might make it more efficient).

May be it only take you 1 hour to write the code, but you might need to spend 10 hours to debug the code (if you did not understand what your were doing or if you make a mistake without noticed).
 Logged
mediakitchen
Newbie

Offline

Posts: 9

 « Embed this message Reply #166 on: October 10, 2010, 04:54:57 pm » posted from:Wantage,Oxfordshire,United Kingdom

Thank you again. I have made the amends you suggested and it appears to work now.

http://www.mediakitchen.co.uk/physics/testFile5v2ballsDelta.html

Paul
 Logged
lunayo
Newbie

Offline

Posts: 6

 « Embed this message Reply #167 on: November 07, 2010, 07:52:47 am »

Sir, how to calculate the momentum of ball hitting the wall? (Wall with various angle and various shape)
 Logged
Fu-Kwun Hwang
Hero Member

Offline

Posts: 3085

 « Embed this message Reply #168 on: November 09, 2010, 01:46:24 pm » posted from:,,Taiwan

You can use the same equation as above, set m2>>m1

The result will be
The component parallel to the wall will be the same
but the normal component of the velocity will change direction (with the same magnitude).
 Logged
thepreditor10
Newbie

Offline

Posts: 2

 « Embed this message Reply #169 on: February 01, 2012, 08:34:26 pm » posted from:MIDDLESBROUGH,ENGLAND,UNITED KINGDOM

i am finding this all a little confusing is there a simple way to explain it in layman's terms
 Logged
Fu-Kwun Hwang
Hero Member

Offline

Posts: 3085

 « Embed this message Reply #170 on: February 01, 2012, 10:48:34 pm » posted from:LONDON,ENGLAND,UNITED KINGDOM

Please write down which part (where) you feel confusing!
 Logged
thepreditor10
Newbie

Offline

Posts: 2

 « Embed this message Reply #171 on: February 02, 2012, 08:35:55 pm » posted from:MIDDLESBROUGH,ENGLAND,UNITED KINGDOM

i find physics confusing in general i am trying to create a simulation not far off the same as shown here for my university project i have the ball moving using angle and velocity by doing

double scale_x=cos(angle);
double scale_y=sin(angle);
double v_x = (speed * scale_x);
double v_y = (speed * scale_y);

now i am looking to get the ball to bounce off the sides of the JPannel on collision also collision detection with two balls.
however i find it hard to understand how we are getting the balls to collide here and collision with the JPannel.
 Logged
nsuhaili6
Newbie

Offline

Posts: 1

 « Embed this message Reply #172 on: May 07, 2012, 07:31:52 pm » posted from:Sekudai,Johor,Malaysia

Hi prof,
your coding is for a circle 2-d collision right?
how am i going to simulate for irregular shape of object?
i want to simulate for water molecules model of this shape but in 2d..
-*-
 Water-2D-dot-cross.png (60.42 KB, 1100x933 - viewed 637 times.) Logged
Fu-Kwun Hwang
Hero Member

Offline

Posts: 3085

 « Embed this message Reply #173 on: May 08, 2012, 03:53:33 pm » posted from:Taipei,T'ai-pei,Taiwan

Do you mean three circles (as shown in the picture attached) as one object.

Then, you need to check collision between any two circles. And you need to re-derive the equation (with conservation of momentum and conservation of angular momentum and conservation of energy-- five equations for 2D case). It will be much more complicated than the above simulation.
 Logged
Some1
Newbie

Offline

Posts: 2

 « Embed this message Reply #174 on: January 08, 2013, 06:45:36 am » posted from:Bucharest,Bucuresti,Romania

Hello!

I have utilised your algorithm in a personal project and now I need to write a documentation for it. One problem I am having is explaining to someone what the actual mass of the ball is measured in... I noticed you give the default value of m1=r1*r1; So the square of the ray of the circle but technically it can be anything.

My question is how much of m1 is a gram.
So:
1 gram = m1
m1 = ?

Thank you in hopes that you can answer my question and once again. I really appreciate your work. It has helped immensely.
 Logged
Fu-Kwun Hwang
Hero Member

Offline

Posts: 3085

 « Embed this message Reply #175 on: January 08, 2013, 03:07:06 pm » posted from:Taipei,T'ai-pei,Taiwan

The mass used in the simulation can be 1g or 1kg or any other unit. It does not matter, the result will be the same (as long as all the particles used the same unit).

Because This is a two dimensional simulation, the mass is proportional to area (mass=density*area).
And the area of a circle is $A=\pi r^2$, that is why the mass is proportional to r*r in a 2D simulation.
(mass will be proportional to $r^3$ for a 3-D simulation.).
 Logged
bark46k
Newbie

Offline

Posts: 1

 « Embed this message Reply #176 on: September 26, 2013, 12:38:02 pm » posted from:,,Satellite Provider

great stuff!

 Logged
kacpero12345
Newbie

Offline

Posts: 1

 « Embed this message Reply #177 on: January 04, 2019, 11:22:20 pm » posted from:,,Satellite Provider

i have problem, if i set different masses balls clutch together
 « Last Edit: January 04, 2019, 11:25:49 pm by kacpero12345 » Logged
 Pages: 1 ... 4 5 [6]   Go Up
Establish Good support system. ...Wisdom