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.

[pascal]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;[/pascal]

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.

Code:
  // 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;