Fu-Kwun Hwang
|
 |
«
Embed this message
Reply #150 on: October 08, 2010, 06:06:57 pm » |
|
 You have the following code dt = (r1+r2-d)/(vp1-vp2);
What if vp1==vp2??? You also have the following 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 » |
|
 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 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 » |
|
 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 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 dt = (r1+r2-d)/(vp1-vp2);
What if vp1==vp2??? You also have the following 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
|
 |
«
Embed this message
Reply #153 on: October 09, 2010, 10:31:14 am » |
|
 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 » |
|
 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 » |
|
 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 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? 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
|
 |
«
Embed this message
Reply #156 on: October 09, 2010, 02:54:03 pm » |
|
 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 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 » |
|
 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 for (var j = 0; i < howManyBalls; j++) {
Should have been for (var j = 0; j < howManyBalls; j++) {
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: 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 » |
|
 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
|
 |
«
Embed this message
Reply #159 on: October 09, 2010, 05:34:28 pm » |
|
 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! 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 » |
|
 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 » |
|
 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.htmlhttp://www.mediakitchen.co.uk/physics/testFile5balls.htmlSimply 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 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 » |
|
 Further to my last post, I have printed some variable values to the screen when the problem occurs as follows: 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
|
 |
«
Embed this message
Reply #163 on: October 10, 2010, 09:04:32 am » |
|
 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 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 » |
|
 Thanks you for your patience. I assure you I am reading your replies and attempting to act on your advice. 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: 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: Another issue is you are processing collision before all the particles are moving to the next time step. 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. 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: 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. Many thanks for your help Paul
|
|
|
Logged
|
|
|
|
Fu-Kwun Hwang
|
 |
«
Embed this message
Reply #165 on: October 10, 2010, 04:26:43 pm » |
|
 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 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 ballObject.tempX = ballObject.tempX + ballObject.horizontalVelocity; ballObject.tempY = ballObject.tempY + ballObject.verticalVelocity;
to 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 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
|
|
|
|
|
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
|
 |
«
Embed this message
Reply #168 on: November 09, 2010, 01:46:24 pm » |
|
 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 » |
|
 i am finding this all a little confusing is there a simple way to explain it in layman's terms 
|
|
|
Logged
|
|
|
|
Fu-Kwun Hwang
|
 |
«
Embed this message
Reply #170 on: February 01, 2012, 10:48:34 pm » |
|
 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 » |
|
 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 » |
|
 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.. -*-
|
|
|
Logged
|
|
|
|
Fu-Kwun Hwang
|
 |
«
Embed this message
Reply #173 on: May 08, 2012, 03:53:33 pm » |
|
 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 » |
|
 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
|
 |
«
Embed this message
Reply #175 on: January 08, 2013, 03:07:06 pm » |
|
 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  , that is why the mass is proportional to r*r in a 2D simulation. (mass will be proportional to  for a 3-D simulation.).
|
|
|
Logged
|
|
|
|
bark46k
Newbie
Offline
Posts: 1
|
 |
«
Embed this message
Reply #176 on: September 26, 2013, 12:38:02 pm » |
|
 great stuff!
|
|
|
Logged
|
|
|
|
kacpero12345
Newbie
Offline
Posts: 1
|
 |
«
Embed this message
Reply #177 on: January 04, 2019, 11:22:20 pm » |
|
 i have problem, if i set different masses balls clutch together
|
|
« Last Edit: January 04, 2019, 11:25:49 pm by kacpero12345 »
|
Logged
|
|
|
|
|