It has been a while since I last visited this tutorial. "Delphi 2" sounds a bit dated, and I wasn't sure whether this tutorial worked with USB joysticks.
Good news! The .exe in the archive works fine on a Windows XP, Home Edition, SP3 machine with a USB joystick, specifically a "RaiderPro Digital" from InterAct, aka interactaccessories.com
One little "gotcha": Plug the joystick in, let the system "find" it before you run my Delphi application. If you'd already run my application, before seeing this advice, don't worry... just close it and re-start it.
One thing that works, but not, maybe, as you would expect it to...
When the application starts, there are two messages in the display...
Press "Fire" to make green square. Press "Fire" to make red circle.
... but, at the start, there is no square or circle of any description. Press the "Fire 1" button and a green square will appear and remain. (I'm not sure why I didn't write the program to remove the green square when "Fire 1" was released.)
Press the "Fire 2" button and red circle will replace the green square, which will remain on the screen unless you press "Fire 1" again, at which time the red circle will be replaced by a green square.
Maybe it was an "exercise for the student" to make the square and circle appear and disappear in the manner you might expect! Joking aside... the point of the tutorial was to show you how to detect the pressing of a button. And it does. The overheads of making things disappear when buttons are released might have been distracting.
That's the good news. The bad news is that I haven't done much more to the tutorial at 3/11... but it didn't seem to need much.
This tutorial needs some editing. Sorry! But I thought you'd rather have the information in it, however badly presented, than wait (probably forever) for the cosmetic surgery it needs? What happened is this: I wrote a first attempt at explaining the material in this. I then forgot I'd done that, and wrote a second "using joysticks" tutorial! You can read the first attempt just by reading the rest of this page. The second attempt is better, and covers everything that appears below and more. (It shows you a way to respond to a Windows message from a separate application, and it creates a joystick driven stopwatch!) The one you are reading now may be more concise, may stray less far from the core concepts.
This tutorial is based on a newsgroups post from Mark Wilkinson... thank you, Mark! This tutorial will be short on explanation and not much longer on program... because Delphi makes things so easy!
I have a switch that goes off-on-off-on... in response to rainfall, as it happens. (It can come to rest in either state.) The more rain, the more cycles. I wanted to monitor that switch, and the "fire button" input of a joystick seemed the obvious, easy way. Don't worry, I have another computer for important things like Interactive Magic's Apache and Novalogic's F-16, so losing the joystick port was acceptable.
Though I couldn't find it in the Delphi 2 help file, Delphi 2 has built in joystick support.
Thanks to a newsgroups post from Mark Wilkinson (homepage: Mark Wilkinson), I discovered enough to write my program for my rainfall monitor.
The essential bits of reading the joystick port are all in DD18. A zip archive of it's source files source can be downloaded by clicking here. The finished .exe file is included, so that you can see if your system, in particular your joystick, is compatible with the software. It has worked under Windows XP with a Logitech USB joystick. I've also had reports that it also works with a BlackWidow USB joystick. It should work with any "old fashioned", "standard" (i.e. 15 way D plug) joystick, but they are, of course, more rare now.
It puts up a window showing you the current x and y positions of the joystick, and responds to Fire buttons 1 and 2.
Something you shouldn't overlook:
Add MMSYSTEM to the "USES" clause. The unit is a standard, Borland unit, don't worry. But be sure to add the reference.
A few things you don't need to worry about:
The variable MyJoy is declared to be of type TJoyInfo. This class is set up by Borland; you don't need to worry about the internal details.
The call of JoyGetPos passes a parameter by means of a pointer... I think!! the "@" sign isn't a mistake, it is to do with pointers, I should probably go learn something about why Borland did JoyGetPos the way they did... but in the meantime, I'm just going to use it and be happy.
The information that follows about procedure ReadJoystick is NOT needed if you want to look at the DD18 version of "how to read a joystick". It may be relevant to the TM17 version.
The following procedure declaration header involves "var", which I don't often use, so I'll say a bit about it here if you haven't come across it. Note it appears before li1 AND before bo1. (If it isn't repeated, the boolean parameters bo1 and bo2 will not behave the way li1 and li2 behave.)
procedure ReadJoystick(var li1,li2:longint;var bo1,bo2:boolean);
The following is messy, and I wouldn't do things like this... but it illustrates what var is doing...
Imagine I have a global variable called Answer, and a procedure as follows:
procedure DoubleAndAdd(b1,b2:byte); begin b1:=b1+b1; b2:=b2+b2; Answer:=b1+b2; end;
If, in my program, I said
...then Answer would be filled with 14. Okay so far... simple stuff, so far.
b1:=3; b2:=4; DoubleAndAdd(b1,b2);
.... Same result, I hope you agree. Answer is still filled with 14. Also, I were to check what was in b1 and b2 after the above, they would still hold 3 and 4. The b1 and b2 of the main program are separate from the b1 and b2 of the procedure. The fact that they have the same names is mere coincidence. This is all about scope... an important concept, one of the things Pascal Got Right, thus making it easy to write robust programs.
Now we start the tricky stuff....
If the procedure said:
procedure DoubleAndAdd(var b1,b2:byte); begin b1:=b1+b1; b2:=b2+b2; Answer:=b1+b2; end;
(same as before, except for the "var")
and the main part of the program said the same as before....
b1:=3; b2:=4; DoubleAndAdd(b1,b2);
.... Answer would still be filled with 14... BUT!....now if I were to check what was in b1 and b2 after the above, they would hold 6 and 8. Even more "magic": if I did.....
FirstVariable:=3; SecondVariable:=4; DoubleAndAdd(FirstVariable,SecondVariable);
... Answer would hold 14, FirstVariable would hold 6, and SecondVariable would hold 8. 3 went into FirstVariable, in that it went into the procedure. In the procedure, it was moved to b1. As the procedure was finishing up, it passed back to FirstVariable whatever was in b1 at the end of executing the procedure.
There are other solutions. (user defined types.) Using var in the procedure declaration might be seen as a clumsy solution... but it works! Be sure to put var in front of each group of variables you want to pass that way.
That's the simple approach to joysticks.... remember there is another tutorial about working with joysticks in these pages, especially the downloadable zip archive with the version of this material that includes a timer.
You are welcome to use the material here free of charge. But if you wish to show your appreciation, you easily can make a gift to me or contribute to a charity I would like to help... I've listed several to choose from. (The link will open in a new tab or window.)
If you visit 1&1's site from here, it helps me. They host my website, and I wouldn't put this link up for them if I wasn't happy with their service. They offer things for the beginner and the corporation.
Page tested for compliance with INDUSTRY (not MS-only) standards, using the free, publicly accessible validator at validator.w3.org
....... P a g e . . . E n d s .....