this tutorial will partially work with borland kylix
In this tutorial we'll be covering the use of the mouse in your games. This isn't the be all and end all in mouse use, but it should provide enough information to get you on pretty well. In addition, you may want to also look at the DelphiX tutorial on using the mouse, which will show you how to make use of what you've learnt here, with DelphiX too. So, we'll start by covering each of the events open to you that use the mouse.
OnClick
You've probably used this event countless times before already, as
whenever you set up what happens when you click on a button on your form, this is the
event that's created. As far as mouse operations go, an OnClick event is only called when
the user clicks AND releases the mouse on a particular area of the form, such as a button.
It should be pointed out that an OnClick event can also be called by the keyboard if, say a button is focused on, and the return key is pushed.
The OnClick event is not likely to be used very often in your games other than for selecting options, as it does not tell your program the location of the click, ie the X and Y coordinates. For that we need the OnMouseDown event.
OnMouseDown
The OnMouseDown event differs from the OnClick event in a number of
major ways. Firstly and most importantly, it will give your program the X and Y
coordinates of a click, and so allowing you to tell exactly where on the form, a user has
clicked. This is of course, extremely useful when trying to move a character around the
screen by clicking on a location on the map. We'll come back to how to make use of this
after we've gone through the other mouse events.
The second major way in which the OnMouseDown event differs from the OnClick event is that it can check for left, middle and right clicks, as well as if the Shift, Control or Alt buttons are pressed at the time of the click. This allows for a greater range of functions which you can provide to the user of the mouse.
The final major difference is that a 'click' of the mouse is now broken up into the pushing of the mouse button down, and the release of the mouse button. As the name suggests, for this event we're only dealing with the holding down of the mouse button. We'll deal with the release of the mouse button next.
OnMouseUp
The OnMouseUp event is exactly the same as the
OnMouseDown event except for one obvious point: the event only occurs when the mouse
button is released. Everything else works the same way. You can get the X and Y
coordinates of the location where the mouse button was released (so if you were to push
the mouse button down and then release it after moving the mouse a little you can find
both the starting and ending coordinates), you can detect whether there are Shift, Control
or Alt buttons pressed, and you can detect whether it is the left, middle or right mouse
button being used. Simple.
OnMouseMove
This last event occurs at any time when the mouse is
moving while your program is running and is selected. Usually you wouldn't want to be
carrying out anything continuously while the mouse is moving, but it is often desirable to
have certain actions occurring as a mouse button is being pressed and moved across the
screen. For example, if we want to drag and select a group of player models on the screen
we may want a rectangle to appear as we drag, to see who we are currently selecting. When
used in conjunction with the OnMouseDown and OnMouseUp events, the OnMouseMove event
becomes very useful and we'll use this event in our mouse example application next.
A Practical Example...
Now that you've heard a little about each mouse
event, let's put all this knowledge together and make a few little programs. The first
thing we'll try and do is get our fly from a previous tutorial, to move to the position on
the form that we click on. After you've
added the image onto the form, enter the following code in the OnMouseDown property of the
actual form (not the TImage):
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
CurrentX := FlyImg.Left;
CurrentY := FlyImg.Top;
MouseX := X;
MouseY := Y;
while (CurrentX <> MouseX) do begin
if MouseX > CurrentX then CurrentX := CurrentX + 1
else if MouseX < CurrentX then CurrentX := CurrentX - 1;
FlyImg.Left := CurrentX;
end;
while (CurrentY <> MouseY) do begin
if MouseY > CurrentY then CurrentY := CurrentY + 1
else if MouseY < CurrentY then CurrentY:= CurrentY - 1;
FlyImg.Top := CurrentY;
end;
end;
Remember also to set up our four variables with the following code in the var section of the code:
CurrentX: integer;
CurrentY: integer;
MouseX: integer;
MouseY: integer;
Let's go through this code then. The first thing we're doing when you click on the form is setting the CurrentX and CurrentY variables to the location on the form where the fly lies at present on our form. Then we're setting our MouseX and MouseY coordinates to that of where we've just clicked.
Next we start actually carrying out the process of moving our fly to the correct location. What we're doing is first examining the location of our image and the location where we want to go and if they are not equal, we carry out the actual movement. We do this for the X coordinate and Y coordinate separately, and we check to see if the location where we've clicked is 'ahead' or 'behind' where the fly image is at that time. If we have to increase the X or Y coordinate to get closer to the clicked location, we increase our fly's coordinate by one, or if we have to decrease the coordinate, we take one off our fly's coordinate. Simple really, and these actions will repeat until the fly's location is exactly the same as the place where you've clicked.
This isn't however particularly useful on its own as we can't see the fly moving to its location. Instead we just see the fly suddenly at its new location, which we could have just as easily done by simply setting the Fly's coordinates immediately to that of the MouseDown's coordinates.
To solve this we need to make use of a delay between each movement. We can use our delay from the TTimer component tutorial for this, but we'll need to change our code a little first to allow a better movement. The way things are just now, the program will first move the fly along the X coordinate, and then after, move along the Y coordinate, causing it to move in a strange way. We can luckily sort this easily enough by getting the program to alternate between the X and Y coordinate until we reach our destination. The diagram below demonstrates this. Here the red dot represents our fly's starting position and the green dot represents the finishing position, with the orange line representing the movement of our fly.
Movement before alteration in code
Movement after alteration in code
This solution works well enough for the moment, although often you may find that one coordinate is reached before the other making the route taken a lot less perfect than that shown above.
procedure Delay(Num: longint);
var
tc: longint;
begin
tc :=GetTickCount;
repeat
Application.ProcessMessages;
until ((GetTickCount-tc) >= Num);
end;
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
CurrentX := FlyImg.Left;
CurrentY := FlyImg.Top;
MouseX := X;
MouseY := Y;
while (CurrentX <> MouseX) or (CurrentY <> MouseY)
do begin
Delay(10);
if (CurrentX <> MouseX) then begin
if MouseX > CurrentX then CurrentX := CurrentX+1
else if MouseX < CurrentX then CurrentX := CurrentX-1;
FlyImg.Left := CurrentX;
end;
if (CurrentY <> MouseY) then begin
if MouseY > CurrentY then CurrentY := CurrentY+1
else if MouseY < CurrentY then CurrentY := CurrentY-1;
FlyImg.Top := CurrentY;
end;
end;
end;
The difference here is that as well as adding the delay procedure, we've also placed our old code inside a new while..do..begin loop, as well as getting rid of our old two 'whiles' and swapping them with if..then..begin loops. This new while loop checks if either the current X-coordinate or the current Y-coordinate of the fly are not equal to the destination coordinates, and performs the relevant movement to both the X and Y coordinates at the same time. That's it.
You'll now find that the fly 'flies' all the way to its new destination. Okay, so it flickers a lot, but as a practical learning exercise for you, you should try making it flicker-free based on the techniques demonstrated in tutorial 11. If you get stuck, the downloadable code for this tutorial includes just such an example.
But that's not all...
We're not done with this tutorial though as I want to cover the
ability to select multiple characters on a screen and move them, in a
similar way as that seen in games such as 'Command & Conquer'. If you
don't know what I mean then let me explain. Basically, when there are
multiple characters on the screen and we want to select them all and
get them to walk to a given location, we might want to 'drag' a box
around the characters with one mouse button to select them, and then
click with the other button to tell them where to move to. I think
this calls for a second page, which will be available soon.
