It depends a bit on what shape you want - do you want a simple thing like a square or something more complex, like a picture with transparent areas?

First of all, a simple square is easy enough to do. You only need one of them rather than a variable amount, so you can simply dump down a TShape from the "additional" component tab.

Note that the shape has an "OnMouseDown" event. This lets you know when the user hit the shape, regardless of where that shape is on the form (i.e., you can move it about). You could write some simple logic for this event that added a score and repositioned the shape if you clicked on it.

Also, note that the form itself has similar events. You're most interested in the "onclick" event, which gets fired when the user clicks on the form. Note that if the user clicks the shape, no OnClick happens. This means that you can write code in the OnClick which assumes the user missed, deducting points and/or insulting them with nasty messages.

Next up, you have to know how to randomly position the thing. There are two functions of interest, Randomize and Random. Call Randomize *once* in your program. It ensures that the "random" values generated are different - if you don't call it, your program will generate the same "random" values each time it's run (which you may, but probably don't, want).

The main form's OnCreate is a good place to chuck that *one* call to Randomize.

The random function generates a number from [0..number-1] inclusive if passed in a value - for example, Random(10) gives a value from 0 to 9 inclusive. If you want more, you can add an offset onto it - Random(6) + 1 would result in a number from 1 to 6, since it would be [0..5] + 1.

The trick for moving/positioning your object is to notice the *left* and *top* properties for your shape. Your shape will be moved if you change these. Therefore, you want to generate a random value for the left and the top, which will move your object somewhere around the form. You might want to ensure that the values are from [0..ClientWidth - Shape1.Width] and [0..ClientHeight - Shape1.Height] to keep it on the screen.

Next up, you need to decide the difficulty - you can let the user select this somehow (e.g. a TRadioGroupBox or buttons), or you could generate it somehow (a random number again?). You have to decide how this effects the difficultly, mind you. A simple way would be to make the shape smaller depending on the value - e.g. "Shape1.Width := DEFAULT_SIZE - (10 * skill)", or something like that, with the same for its height.

It would be easy enough to time your game. Dump down a TTimer from the "system" tab and give it some code for the OnTimer event. This gets called regularly, each time a given amount of time (in milliseconds) has passed. For example, the default interval is 1000 milliseconds, equal to a second. If you set it to 2 minutes (60 * 2 * 1000 = 120000) then your timer event will fire. At that point, your game has finished! You can do any code and disable the timer (Timer1.Enabled := False). Re-enable the timer at the start of a new game.

You can move the object using another timer. TTimer sucks for quick animation (interval < 55msecs), but if you're just learning then it will be fine [you can also investigate some other component sets with good timers if you want, more on that later]. You can dump some logic in there to move the object in a speed and direction.

One easy way to store the direction is to have two integer variables for the x and the y speed - negative values = left or up, positive values = right or down (for example, speed_x = -2 would move two pixels left every timer update. If you had speed_y = -1 then that would be two units left, one unit up). You can use these simply by adding the values to the left and top positions of the shape each update.

You can make your shape bounce off of the edges by negating the speeds. Some quick pseudocode:

[pascal]procedure TForm1.MoveShape;
var
NewX, NewY: Integer;
begin
NewX := Shape1.Left + Speed_X;
NewY := Shape1.Top + Speed_Y;

if NewX < 0 then
begin
NewX := 0;
Speed_X := -Speed_X; // opposite direction
end;

if NewX > ClientWidth - Shape1.Width then
begin
NewX := ClientWidth - Shape1.Width;
Speed_x := -Speed_X;
end;

if NewY < 0 then
begin
NewY := 0;
Speed_Y := -Speed_Y;
end;

if NewY > ClientHeight - Shape1.Height then
begin
NewY := ClientHeight - Shape1.Height;
Speed_Y := -Speed_Y;
end;

Shape1.Left := NewX;
Shape1.Top := NewY;
end;[/pascal]

The above will 'bounce' your shapes. ClientWidth and ClientHeight return the available area of your form after stuff like borders, title bar are taken into account. The above code stops the shape from going off-screen. However, it will only move in lines - moving in fancy ways (circles, etc.) is a bit more difficult. You might want to consider adding a random value to the speed(s) when the shape hits the side of the form, to make things more interesting.

If you're wanting something more complicated than a square, it will take a bit more work. You can consider using a TImage (additional component tab) and giving it a bitmap using its Picture property (hit the three dots beside that property). You could then check its OnMouseDown property - it gives you access to the x and y values of where it was clicked. You could then check "if Image1.Canvas.Pixels[x,y] = transparent_colour" then missed_with_click else hit_target" (I think...)

If you want things to look better, you'd use one of the dozen component sets out there (DelphiX, PowerDraw, JDS Games' thing [gamevision? Can't remember, sorry ops: ], Bobby's Omega Project]... You could consider using a high performance timer for your main game update (see other threads in this board about game loops, etc.).

If you don't have access to a component with an onclick then you have to check manually - draw the bitmap to screen, then check in the form's onmousedown "if (x >= your_bitmap_x) and (x < your_bitmap_x + your_bitmap_height) and (y >= your_bitmap_y) and (y < your_bitmap_y + your_bitmap_height) then hit_target else missed_target;".

If you want any more detail/code, just ask.