What is threads good for? If you wonder, maybe this example will give you a clue. It would have been difficult to accomplish something like this without using threads. 
The example will create a balloon each time the button is pressed, and it will start to slowly descend towards ground. A random side movement is applied during descending, to give the balloon a "wacky" feeling. Each balloon will have it's own "life", within his thread. For each new balloon-position the program will check that it doesn't collide with others. In that case another position will be calculated until a free spot is found. After a while the balloon will land and the thread will be terminated. 
All thread-activity that results in changes on the form canvas, must be timed with other window activities in the main thread. The Synchronize command takes care of that part, and we don't need to bother to much about it. All we have to do is make sure that all things that goes to the window is put in separate procedures called by Synchronize. Note: You can't pass any variables to a procedure being called with Synchronize. You have to declare these as private within the thread. 
The program is using three bitmaps, one for the balloon, one "splash"-picture and one with just the background color.
If you are of the destructive type, you can aim at a balloon and shoot it down by pressing the left mouse-key. 
If you want the project files, press here: 
 
{-----------------------------------------------------------------------------
 Unit Name: Unit1
 Author: Mats Asplund
 Purpose: Threading example
 History:
-----------------------------------------------------------------------------}
unit Unit1;
interface
uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls, ExtCtrls;
type
 TBalloonThread = class(TThread)
 private
 fBalloon, fNothing, fSplash: TBitmap;
 fBalloonNo, fWidth, fHeight, x, y, xold, yold, xtmp, ytmp: Integer;
 fOK, fHit: Boolean;
 procedure Draw;
 procedure DrawSplash;
 procedure EraseOldPos;
 procedure CheckPos;
 protected
 procedure Execute; override;
 constructor Create(BalloonNo, Width, Height: Integer;
 BitmapFile1, BitmapFile2, BitMapFile3: TFileName);
 end;
 TForm1 = class(TForm)
 Button1: TButton;
 Shape1: TShape;
 procedure Button1Click(Sender: TObject);
 procedure FormCreate(Sender: TObject);
 procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
 Shift: TShiftState; X, Y: Integer);
 private
 BWidth, BHeight, BalloonNo: Integer;
 BallonPositions: array[0..99] of array[0..1] of Integer;
 Hit: array[0..99] of boolean;
 { Private declarations }
 public
 { Public declarations }
 end;
var
 Form1: TForm1;
implementation
{$R *.dfm}
{ TBallonThread }
procedure TForm1.FormCreate(Sender: TObject);
var
 Bitmap: TBitmap;
 n: Integer;
begin
 // Initialize
 BalloonNo:= 0;
 for n:= Low(Hit) to High(Hit) do
 begin
 BallonPositions[n, 0]:= 0;
 BallonPositions[n, 1]:= 0;
 Hit[n]:= false;
 end;
 // Check bitmap width and height.
 // All three bitmaps should be of same size.
 Bitmap:= TBitmap.Create;
 Bitmap.LoadFromFile('balloon.bmp');
 BWidth:= Bitmap.Width;
 BHeight:= Bitmap.Height;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
 // Create one Balloon-instance.
 TBalloonThread.Create(BalloonNo, BWidth, BHeight,
 'balloon.bmp', 'nothing.bmp', 'splash.bmp');
 Inc(BalloonNo);
end;
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
 Shift: TShiftState; X, Y: Integer);
var
 n: integer;
begin
 // Check every balloonposition to see if there's a hit.
 for n:= 0 to BalloonNo -1 do
 begin
 if (abs(BallonPositions[n, 0]- X) < BWidth + 1) and
 (abs(BallonPositions[n, 1]- Y) < BHeight + 1) and
 ((BallonPositions[n, 0]- X) <= 0) and
 ((BallonPositions[n, 1]- Y) <= 0) then
 Hit[n]:= true;
 end;
end;
constructor TBalloonThread.Create(BalloonNo, Width, Height: Integer;
 BitmapFile1, BitmapFile2, BitmapFile3: TFileName);
begin
 inherited Create(true);
 fBalloonNo:= BalloonNo;
 fWidth:= Width;
 fHeight:= Height;
 fHit:= false;
 // Create bitmaps needed
 fBalloon:= TBitmap.Create;
 fBalloon.LoadFromFile(BitmapFile1);
 fBalloon.TransParentColor:= fBalloon.Canvas.Pixels[0, 0];
 fBalloon.Transparent:= true;
 fNothing:= TBitmap.Create;
 fNothing.LoadFromFile(BitmapFile2);
 fSplash:= TBitmap.Create;
 fSplash.LoadFromFile(BitmapFile3);
 fSplash.TransParentColor:= fSplash.Canvas.Pixels[0, 0];
 fSplash.Transparent:= true;
 FreeOnTerminate:= true;
 Resume;
end;
procedure TBalloonThread.Execute;
begin
 fOK:= false;
 // First position on screen
 while not fOK do
 begin
 xtmp:= Random(600) + 50;
 ytmp:= 0;
 Synchronize(CheckPos);
 end;
 x:= xtmp;
 y:= ytmp;
 // Main loop
 while not Terminated do
 begin
 // The balloon has landed. Terminate.
 if y > 313 then
 begin
 y:= 313;
 Terminate;
 end;
 // Erase old position - draw new
 Synchronize(EraseOldPos);
 Synchronize(Draw);
 Sleep(400);
 xold:= x;
 yold:= y;
 fOK:= false;
 while not fOK do
 begin
 // Calculate new position
 if Random(2) = 0 then
 xtmp:= x + Random(3)
 else
 xtmp:= x - Random(3);
 if Random(7) < 6 then
 ytmp:= y + Random(3)
 else
 ytmp:= y - Random(3);
 Synchronize(CheckPos);
 // Balloon is hit. Draw splash, then terminate.
 if fHit then
 begin
 Synchronize(EraseOldPos);
 Synchronize(DrawSplash);
 Sleep(200);
 Synchronize(EraseOldPos);
 Terminate;
 end;
 end;
 x:= xtmp;
 y:= ytmp;
 end;
end;
procedure TBalloonThread.CheckPos;
var
 n: Integer;
begin
 // Check that new position(xtmp, ytmp) doesn't interfere with
 // any other balloons position.
 for n:= 0 to Form1.BalloonNo - 1 do
 begin
 if n <> fBalloonNo then
 begin
 if (abs(xtmp - Form1.BallonPositions[n, 0]) < fWidth) and
 (abs(ytmp - Form1.BallonPositions[n, 1]) < fHeight) then
 begin
 fOK:= false;
 Exit;
 end;
 end;
 end;
 // Check if hit
 if Form1.Hit[fBalloonNo] then
 fHit:= true;
 // ...It didn't interfere. Set new position.
 Form1.BallonPositions[fBalloonNo, 0]:= xtmp;
 Form1.BallonPositions[fBalloonNo, 1]:= ytmp;
 fOK:= true;
end;
procedure TBalloonThread.Draw;
begin
 // Draw balloon in new position
 Form1.Canvas.Draw(x, y, fBalloon);
end;
procedure TBalloonThread.EraseOldPos;
begin
 // Draw "nothing" at previous position
 Form1.Canvas.Draw(xold, yold, fNothing);
end;
procedure TBalloonThread.DrawSplash;
begin
 // Draw splashpicture. Set position outside screen.
 Form1.Canvas.Draw(x, y, fSplash);
 Form1.BallonPositions[fBalloonNo, 0]:= -fWidth;
 Form1.BallonPositions[fBalloonNo, 1]:= -fHeight;
end;
end.