The balls are repelled from the walls and each other
Need help with a program where several balls push off the walls and hit each other. Here is the code where one ball flies around the shape and is pushed off the walls.
var
Form1: TForm1;
PosX, Posy, VelX, Vely: single;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
Posx:=3;
PosY:=5;
VelX:=2;
VelY:=2;
end;
procedure TForm1.shar;
begin
PosX:= PosX+VelX;
PosY:= PosY+VelY;
if PosX > ClientWidth - Shp1.Width then
begin
PosX:= ClientWidth - Shp1.Width;
VelX:= - VelX;
end
else
if PosX < 0 then
begin
PosX:= 0;
VelX:= -VelX;
end;
if PosY > ClientHeight - Shp1.Width then
begin
POsY:= ClientHeight - Shp1.Width;
VelY:= - VelY;
end
else
if PosY < 0 then
begin
POsY:= 0;
VelY:= - VelY;
end;
Shp1.Left:= Round(PosX);
Shp1.Top:= Round(PosY);
end;
procedure TForm1.tmr1Timer(Sender: TObject);
begin
shar;
end;
end.
I can't figure out how to add more balls and make them repel each other. I will be grateful for any help!
2 answers
You need to take advantage of OOP and design your classes correctly.
I don't know exactly what the pattern is called (well, maybe someone from the fans of Kant Beck knows the name).
First, you need a class that controls the balls.TSharManager
it must have the properties of initializing objects (InitObjects
) and changing them in space when they collide, and drawing them accordingly (DrawObjects
).
And also in this class, you need to set the characteristics of the walls.
The TShar
class itself must contain information about the balloon.
Storing everything in separate variables is a direct path to total confusion and the most difficult debugging.
The TShar
class must have properties Radius
, LeftCentrPos
, TopCentrPos
, Color
(well, maybe for this task it is not necessary, but it is easy to add), Plotnost
(you can neglect physics, but if necessary, it is also easy to add) and most importantly the vector and speed of movement. (You can use the speed of movement in X and Y)
I must say at once that I do not remember the physical formula for the addition of forces at the moment of collision.
But in her as a result, these properties should change. That is, there will be a method in which the coordinates of two colliding objects are recalculated. You can understand that they will collide by the fact that the sum of the radii will be equal to the distance between the centers. Unlike a square / rectangle, here the collision does not occur at the moment when the borders touch. Based on the characteristics of the balls, we calculate a new trajectory (vector and velocity). Theoretically, several balls can collide at the same time.But this is already next step. Let's simplify that only two balls collide. You need to go through all the balls and find out if the radii touch. And also find out if the ball will touch the wall. In both cases, the direction of movement and its vector change.
I don't know how much it helped, but I think the algorithm should be like this.. There's more math and physics involved. The task is large enough to write code here and create a model.
The balls, their velocities, and coordinates are entered in arrays. The sizes of all the balls are the same.
procedure bumpWalls; //столкновение со стенами
var
i: Cardinal;
begin
with Form1 do
begin
for i := 0 to BallCount - 1 do
begin
masPosX[i] := masPosX[i] + masVelX[i];
masPosY[i] := masPosY[i] + masVelY[i];
if masPosX[i] > ClientWidth - Shp1.Width then
begin
masPosX[i] := ClientWidth - Shp1.Width;
masVelX[i] := -masVelX[i];
end
else if masPosX[i] < 0 then
begin
masPosX[i] := 0;
masVelX[i] := -masVelX[i];
end;
if masPosY[i] > ClientHeight - Shp1.Width then
begin
masPosY[i] := ClientHeight - Shp1.Width;
masVelY[i] := -masVelY[i];
end
else if masPosY[i] < 0 then
begin
masPosY[i] := 0;
masVelY[i] := -masVelY[i];
end;
end;
end;
end;
procedure bumpEachOther; //столкновение друг с другом
var
h0, h1, i, j: Cardinal;
a, b, dist, bet, x1, x2, y1, y2: extended;
n: integer;
xx0, yy0, xx1, yy1: single;
begin
for i := 1 to 10 do
begin
for h0 := 0 to ballcount - 1 do
begin
for h1 := 0 to ballcount - 1 do
if h0 <> h1 then
begin
a := MasPosX[h0] + MasVelX[h0] * 0.001 - MasPosX[h1] - MasVelX[h1] * 0.001;
b := MasPosY[h0] + MasVelY[h0] * 0.001 - MasPosY[h1] - MasVelY[h1] * 0.001;
dist := sqrt(sqr(a) + sqr(b));
if dist <= 241 then
begin
bet := arctan2(MasPosY[h1] - MasPosY[h0], MasPosX[h1] - MasPosX[h0]);
x1 := masvelx[h0] * cos(-bet) - MasVelY[h0] * sin(-bet);
y1 := MasVelX[h0] * sin(-bet) + MasVelY[h0] * cos(-bet);
x2 := MasVelX[h1] * cos(-bet) - MasVelY[h1] * sin(-bet);
y2 := MasVelX[h1] * sin(-bet) + MasVelY[h1] * cos(-bet);
MasVelX[h0] := x2 * cos(bet) - y1 * sin(bet);
MasVelY[h0] := x2 * sin(bet) + y1 * cos(bet);
masVelX[h1] := x1 * cos(bet) - y2 * sin(bet);
MasVelY[h1] := x1 * sin(bet) + y2 * cos(bet);
n := 0;
xx0 := masvelx[h0];
yy0 := masvely[h0];
xx1 := masvelx[h1];
yy1 := masvely[h1];
repeat
MasPosX[h0] := MasPosX[h0] + xx0 * 0.0011;
MasPosY[h0] := MasPosY[h0] + yy0 * 0.0011;
MasPosX[h1] := MasPosX[h1] + xx1 * 0.0011;
MasPosY[h1] := MasPosY[h1] + yy1 * 0.0011;
a := MasPosX[h0] - MasPosX[h1];
b := MasPosY[h0] - MasPosY[h1];
dist := sqrt(sqr(a) + sqr(b));
inc(n);
until (dist > 241) or (n > 50000);
end;
end;
MasPosX[h0] := MasPosX[h0] + MasVelX[h0] * 0.001;
MasPosY[h0] := MasPosY[h0] + MasVelY[h0] * 0.001;
end;
end;
end;