PDA

View Full Version : Physics and Math (not advanced)



arthurprs
16-07-2007, 06:39 AM
I simply can't make this thing work!!!!!

http://pastebin.com/f29c5c3f8
( code is more than 100 lines and i don't like to be warned by admins and mods =P )

Compiled project + source
http://www.thehardwaresxtreme.com/nye/arthurprs/test.zip

savage
16-07-2007, 08:34 AM
Hi arthur,
Could you please mention exactly what is not working. Otherwise it's like a treasure hunt.

WILL
16-07-2007, 02:09 PM
I think that we have all been in this state with a project before. I know I have many many times. Still patience and expressing the problem clearly and in detail to others is always the best solution rather than a rushed panic.


( code is more than 100 lines and i don't like to be warned by admins and mods =P )

Do I really need to say it? :roll:

AthenaOfDelphi
16-07-2007, 06:40 PM
I've just had a quick look and unless my eyes deceived me, in the example exe, the balls collide and the one on the left starts going back (to the left), but the one on the right continues on its path instead of rebounding (something to do with... it going faster? momentum being retained that probably shouldn't be?)

The net result is that on the next collision calculation cycle, they are still in collision and thus, they are accelerated... in the same direction they are already traveling (to the left)... so instead of parting and going in opposite directions, they accelerate together and result in the whirl of pixels you're getting.

Thats what appears to be happening to me. I could be wrong but I don't have the time to brush off my physics and mechanical maths to go into it any further.

Hope it helps.

arthurprs
16-07-2007, 09:55 PM
I've just had a quick look and unless my eyes deceived me, in the example exe, the balls collide and the one on the left starts going back (to the left), but the one on the right continues on its path instead of rebounding (something to do with... it going faster? momentum being retained that probably shouldn't be?)

The net result is that on the next collision calculation cycle, they are still in collision and thus, they are accelerated... in the same direction they are already traveling (to the left)... so instead of parting and going in opposite directions, they accelerate together and result in the whirl of pixels you're getting.

Thats what appears to be happening to me. I could be wrong but I don't have the time to brush off my physics and mechanical maths to go into it any further.

Hope it helps.

Yeah the balls don't collide right, they go to same direction =/ and the code appers to be right

arthurprs
16-07-2007, 10:26 PM
I think that we have all been in this state with a project before. I know I have many many times. Still patience and expressing the problem clearly and in detail to others is always the best solution rather than a rushed panic.


( code is more than 100 lines and i don't like to be warned by admins and mods =P )

Do I really need to say it? :roll:

Im on this for more than 3 months :cry:


Sorry,
but it's nothing wrong.. to say that

sorry my bad english =(

arthurprs
17-07-2007, 07:53 AM
Remade but don't finded the solution and don't find the problem on the source

arthurprs
18-07-2007, 11:29 PM
I've just had a quick look and unless my eyes deceived me, in the example exe, the balls collide and the one on the left starts going back (to the left), but the one on the right continues on its path instead of rebounding (something to do with... it going faster? momentum being retained that probably shouldn't be?)

The net result is that on the next collision calculation cycle, they are still in collision and thus, they are accelerated... in the same direction they are already traveling (to the left)... so instead of parting and going in opposite directions, they accelerate together and result in the whirl of pixels you're getting.

Thats what appears to be happening to me. I could be wrong but I don't have the time to brush off my physics and mechanical maths to go into it any further.

Hope it helps.

ohhh now that i read that u saw the problem :shock:

and i think that's the problem too,
but don't know how solve the problem :(

Robert Kosek
19-07-2007, 12:55 PM
Hello,

Your problem is in procedure Tform1.colision; because you loop through the balls twice. You might have more than one problem, but this is the one I really see.

You only have two balls, and you know this, so why do you check the collision of the balls twice in nested for-loops? If ball 1 collided with ball 2, obviously ball 2 collided with 1! Yet, you loop through and check again. This is where the strange behavior comes in. To use a for loop with this sort of thing, you'll have to "register" collisions to avoid, uh, collision collisions.... How to make that less wacky and more understandable? Ah, prevent duplicate collisions. Sorry, for a second there I got stuck between cars in my train of thought.

procedure Tform1.colision;
var
n, i: Integer;
dist: single;
colided: Boolean;
begin
colided := False;

for n := 0 to 1 do
begin // n = currentball

ball[n].v2x := 0;
ball[n].v2y := 0;

// wall hit
//x
if (ball[n].x <0>= Form1.ClientWidth) then
begin
ball[n].vx := -ball[n].vx;
// todo: atrito 10%
end;
//y
if (ball[n].y <0>= Form1.ClientHeight) then
begin
ball[n].vy := -ball[n].vy;
// todo: atrito 10%
end;

// other balls hit
for i := 0 to 1 do // i = other ball
if i <> n then
begin
dist := distance(ball[i].cx, ball[i].cy, ball[n].cx, ball[n].cy);
if dist < (ball[i].raio + ball[n].raio) then
begin
colided := True;
form1.Caption := 'colidiu bola : ' + IntToStr(n) + ' , ' + IntToStr(i) + ' na distancia de ' + FloatToStr(dist) + ' ' + FloatToStr(ball[n].vx) + ' ' + FloatToStr(ball[n].vy) + ' ' + FloatToStr(ball[i].vx) + ' ' + FloatToStr(ball[i].vy);
ball[n].v2x := ball[n].v2x + ball[i].vx;
ball[n].v2y := ball[n].v2y + ball[i].vy;
end;
end;
end;

for n := 0 to 1 do
begin
if colided then
buffer.Canvas.TextOut(30,100,('ball n¬? ' + IntToStr(n) + ' ,v2x:' + FloatToStr(ball[n].v2x) + ' ,v2y:' + FloatToStr(ball[n].v2y)));
ball[n].vx := ball[n].vx + ball[n].v2x;
ball[n].vy := ball[n].vy + ball[n].v2y;
ball[n].Refresh;
end;
end;

I won't tell you how to write your code because I think you are trying to learn by doing so. But, you have two choices: the first is to hardcode this system into only two collisions; the second is to make a basic physics system that avoids duplicate collisions. I recommend the first in your case, but it is your choice.

If you follow my recommendation you should remove all for loops except the ending ball update code. Just check if ball 1 and 2 collided (once) and then calculate the reflection vectors.

Edit: Oh fine, I thought of the exact line away from the computer for two seconds, and I know how it is to stumble around for something like that. Here's your problem, and solution; check the first if statement.


// other balls hit
for i &#58;= 0 to 1 do // i = other ball
if &#40;i <> n&#41; and &#40;not colided&#41; then // But don't colide twice.
begin
dist &#58;= distance&#40;ball&#91;i&#93;.cx, ball&#91;i&#93;.cy, ball&#91;n&#93;.cx, ball&#91;n&#93;.cy&#41;;
if dist < &#40;ball&#91;i&#93;.raio + ball&#91;n&#93;.raio&#41; then
begin
colided &#58;= True;
form1.Caption &#58;= 'colidiu bola &#58; ' + IntToStr&#40;n&#41; + ' , ' + IntToStr&#40;i&#41; + ' na distancia de ' + FloatToStr&#40;dist&#41; + ' ' + FloatToStr&#40;ball&#91;n&#93;.vx&#41; + ' ' + FloatToStr&#40;ball&#91;n&#93;.vy&#41; + ' ' + FloatToStr&#40;ball&#91;i&#93;.vx&#41; + ' ' + FloatToStr&#40;ball&#91;i&#93;.vy&#41;;
ball&#91;n&#93;.v2x &#58;= ball&#91;n&#93;.v2x + ball&#91;i&#93;.vx;
ball&#91;n&#93;.v2y &#58;= ball&#91;n&#93;.v2y + ball&#91;i&#93;.vy;
end;
end;

arthurprs
19-07-2007, 06:33 PM
Hello,

Your problem is in procedure Tform1.colision; because you loop through the balls twice. You might have more than one problem, but this is the one I really see.

You only have two balls, and you know this, so why do you check the collision of the balls twice in nested for-loops? If ball 1 collided with ball 2, obviously ball 2 collided with 1! Yet, you loop through and check again. This is where the strange behavior comes in. To use a for loop with this sort of thing, you'll have to "register" collisions to avoid, uh, collision collisions.... How to make that less wacky and more understandable? Ah, prevent duplicate collisions. Sorry, for a second there I got stuck between cars in my train of thought.
...



Thx for the help! ;]

i will try what u say, but just one thing, i think the loop is necessary because the original source have 4 balls (you can see the dynamic array), isn't it ?


*from brazil so sorry my english

arthurprs
20-07-2007, 03:28 AM
Hello,

Your problem is in procedure Tform1.colision; because you loop through the balls twice. You might have more than one problem, but this is the one I really see.

You only have two balls, and you know this, so why do you check the collision of the balls twice in nested for-loops? If ball 1 collided with ball 2, obviously ball 2 collided with 1! Yet, you loop through and check again. This is where the strange behavior comes in. To use a for loop with this sort of thing, you'll have to "register" collisions to avoid, uh, collision collisions.... How to make that less wacky and more understandable? Ah, prevent duplicate collisions. Sorry, for a second there I got stuck between cars in my train of thought.
...



Thx for the help! ;]

i will try what u say, but just one thing, i think the loop is necessary because the original source have 4 balls (you can see the dynamic array), isn't it ?


*from brazil so sorry my english
i have finnaly find the problem but don't know how solve it

the balls get same V after the colision, so with same V balls continues coliding and getting more and more V

A -> with 0.5v
B <- with -0.9v

result in

A <- with -0.4v
B <- with -0.4v

=/


procedure Tform1.colision;
var
n, i: Integer;
dist: double;
begin

for n := 0 to Length(ball) - 1 do
begin // n = currentball

ball[n].v2x := 0;
ball[n].v2y := 0;
ball[n].colided := False;

// wall hit
//x
if (ball[n].x <= 0)
or (ball[n].x2 >= Form1.ClientWidth) then
begin
ball[n].vx := -ball[n].vx;
// todo: atrito 10%
end;
//y
if (ball[n].y <= 0)
or (ball[n].y2 >= Form1.ClientHeight) then
begin
ball[n].vy := -ball[n].vy;
// todo: atrito 10%
end;

// other balls hit
for i := 0 to Length(ball) - 1 do // i = other ball
if (i <> n) then
begin
dist := distance(ball[i].cx, ball[i].cy, ball[n].cx, ball[n].cy);
if dist < (ball[i].raio + ball[n].raio) then
begin
ball[n].colided := True;
form1.Caption := 'colidiu bola : ' + IntToStr(n) + ' , ' + IntToStr(i) + ' na distancia de ' + FloatToStr(dist) + ' ' + FloatToStr(ball[n].vx) + ' ' + FloatToStr(ball[n].vy) + ' ' + FloatToStr(ball[i].vx) + ' ' + FloatToStr(ball[i].vy);
ball[n].v2x := ball[n].v2x + ball[i].vx;
ball[n].v2y := ball[n].v2y + ball[i].vy;
end;
end;
end;

for n := 0 to Length(ball) - 1 do
begin
if ball[n].colided then
begin
ball[n].vx := ball[n].vx + ball[n].v2x;
ball[n].vy := ball[n].vy + ball[n].v2y;
end;
ball[n].Refresh;
end;
end;


EDITED

jdarling
20-07-2007, 12:38 PM
arthurprs, the board mangled your code. Please uncheck the HTML option in the post and clean it back up so we can read it :).

arthurprs
20-07-2007, 06:00 PM
arthurprs, the board mangled your code. Please uncheck the HTML option in the post and clean it back up so we can read it :).

edited

Robert Kosek
20-07-2007, 07:49 PM
Gah! No pastebin, please! It is horrid for cut and paste so I can't excerpt and point out things in your code here. There's a checkbox over the "submit" button that says "Disable HTML in this post"; check that and leave the code in there please. :)

It looks like the collision math itself is flawed. To me it seems you're just adding together the velocities of the collision balls withough any further computation. Are you using a specific formula?

arthurprs
20-07-2007, 08:22 PM
Gah! No pastebin, please! It is horrid for cut and paste so I can't excerpt and point out things in your code here. There's a checkbox over the "submit" button that says "Disable HTML in this post"; check that and leave the code in there please. :)

It looks like the collision math itself is flawed. To me it seems you're just adding together the velocities of the collision balls withough any further computation. Are you using a specific formula?

no formula just ading the other ball V =/

what is the correct way ?

Robert Kosek
20-07-2007, 08:26 PM
Ah! Therein lies the problem.

If two balls collide in direct impact (head on) they don't come to a complete stop like your math would indicate. They bounce off each other in opposite directions. With your code two balls doing this will bounce in such a way that one stops and the other goes crazy.

This page might help: http://www.physicsforums.com/archive/index.php/t-8650.html

arthurprs
20-07-2007, 09:56 PM
Ah! Therein lies the problem.

If two balls collide in direct impact (head on) they don't come to a complete stop like your math would indicate. They bounce off each other in opposite directions. With your code two balls doing this will bounce in such a way that one stops and the other goes crazy.

This page might help: http://www.physicsforums.com/archive/index.php/t-8650.html

:!: Vryyyy Complicated,

when the code ready i'll post results

arthurprs
21-07-2007, 12:14 AM
Real code, real problem comes

http://www.mediafire.com/?fdwtze33wwt
Source + Demo exe



procedure Tform1.colision;
var
n, i: Integer;
dist, dt: Double;
dx, dy: Double;
ax, ay: Double;
vp_n, vp_i: Double;
begin

for n := 0 to Length(ball) - 1 do
begin // n = currentball

// wall hit
//x
if (ball[n].x <= 0)
or (ball[n].x2 >= Form1.ClientWidth) then
begin
ball[n].vx := -ball[n].vx {* 0.9};
end;
//y
if (ball[n].y <= 0)
or (ball[n].y2 >= Form1.ClientHeight) then
begin
ball[n].vy := -ball[n].vy {* 0.9};
end;

// other balls hit
for i := 0 to Length(ball) - 1 do // i = other ball
if (i <> n) and not (ball[i].colided) and not (ball[n].colided) then
begin
*dx := ball[n].cx - ball[i].cx;
*dy := ball[n].cy - ball[i].cy;
*dist := Sqrt(Power(dx, 2) + Power(dy, 2));
if dist <= (ball[i].raio + ball[n].raio) then
begin
*ax := dx / dist;
*ay := dy / dist;
*vp_n := ball[n].vx * ax + ball[n].vy * ay;
*vp_i := ball[i].vx * ax + ball[i].vy * ay;
*dt := (ball[n].raio + ball[i].raio - dist) / (vp_n + vp_i);
*ball[n].x := ball[n].x - (ball[n].vx * dt);
*ball[n].y := ball[n].y - (ball[n].vy * dt);
*ball[i].x := ball[i].x - (ball[i].vx * dt);
*ball[i].y := ball[i].y - (ball[i].vy * dt);
ball[n].colided := True;
ball[i].colided := True;
form1.Caption := 'colidiu bola : ' + IntToStr(n) + ' , ' + IntToStr(i) + ' na distancia de ' + FloatToStr(dist) + ' ' + FloatToStr(ball[n].vx) + ' ' + FloatToStr(ball[n].vy) + ' ' + FloatToStr(ball[i].vx) + ' ' + FloatToStr(ball[i].vy);
ball[n].v2x := ball[n].v2x + ball[i].vx; // this will change, but need solve the oter problem first
ball[n].v2y := ball[n].v2y + ball[i].vy;
ball[i].v2x := ball[i].v2x + ball[n].vx;
ball[i].v2y := ball[i].v2y + ball[n].vy;
end;
end;
end;

for n := 0 to Length(ball) - 1 do
begin
if ball[n].colided then
begin
ball[n].vx := ball[n].vx + ball[n].v2x;
ball[n].vy := ball[n].vy + ball[n].v2y;
ball[n].v2x := 0;
ball[n].v2y := 0;
ball[n].colided := False;
end;
ball[n].Refresh;
end;
end;


Based on http://www.phy.ntnu.edu.tw/ntnujava/index.php?topic=4.0 i write some code to make distance of balls be ball1Ray + ball2Ray
i marked the lines in the code with a *

i think i writed it correctly, but it don't work, the code moves the ball to a wrong place =/ and not when the dist = ball1Ray + ball2Ray

:?

WILL
21-07-2007, 12:38 AM
Ok... it would really help if you explained in plain english, instead of trying to explain it in code. For all we know, you are new to programming in general and your problem could range anywhere from physics, implementation or standard coding practices.

We understand that your english is weak (thats ok a LARGE amount of visitors here don't have English as their first language too) but the best way is to get the problem across in people language first. We also can spot your mistakes quicker.

Like this I'm afraid I can't tell if you whole code is 'out to lunch' (English expression for totally wrong) or not.


What I can offer from what I see; Make sure that you are not moving everything before you know where it all is going to go first. In other words, If you have 2 balls that are to bump into each other and react on their own then try this:

1) move ALL balls

2) detect ALL collisions

3) change velocity on ALL balls with a collision

4) go back and start at 1...

Now you can combine 2 and 3, but do NOT combine 1 and 3 or 1 and 2. Imagine a whole table full of pool balls bouncing around and moving... try to determine where they are all going... confusing huh? Sort of the same deal here.

Hope this little bit of theory helps.

arthurprs
21-07-2007, 01:44 AM
Ok... it would really help if you explained in plain english, instead of trying to explain it in code. For all we know, you are new to programming in general and your problem could range anywhere from physics, implementation or standard coding practices.

We understand that your english is weak (thats ok a LARGE amount of visitors here don't have English as their first language too) but the best way is to get the problem across in people language first. We also can spot your mistakes quicker.

Like this I'm afraid I can't tell if you whole code is 'out to lunch' (English expression for totally wrong) or not.


What I can offer from what I see; Make sure that you are not moving everything before you know where it all is going to go first. In other words, If you have 2 balls that are to bump into each other and react on their own then try this:

1) move ALL balls

2) detect ALL collisions

3) change velocity on ALL balls with a collision

4) go back and start at 1...

Now you can combine 2 and 3, but do NOT combine 1 and 3 or 1 and 2. Imagine a whole table full of pool balls bouncing around and moving... try to determine where they are all going... confusing huh? Sort of the same deal here.

Hope this little bit of theory helps.

edited the post, and 99% sure that the error are in the new code :oops:
cuz i tried only to "-V" and it worked perfecly