2. JOYSTICK LOGIC
Did you know that you can read the joystick without a dozen IF
... THEN statements? In the second of our Tutorial Subroutines, Ian
Finlayson presents a very compact subroutine to handle joystick
input.
As I start the second in this series of tutorial
subroutines I had better explain how all the subroutines will be
laid out. In the last issue the disk contents subroutine started at
line number 31000 (with a REM statement preceding it in line 30999);
this time the subroutine starts at 31100 and from now on I will
increment by 100 each time. This will allow you to store all the
subroutines in one file rather than having to store each separately.
The REM identifier statements will all be put ahead of the main line
number at which the subroutine starts.
LOGICAL OPERATORS
My subroutine this time is based on the use of
logical operators, and as some people have difficulty with the
underlying concept I will try to explain first and then develop the
subroutines. The logical operators are fast and they can be used to
generate compact code.
The fundamental concept is this – The value of a
logical statement is 1 if the statement is true and zero if the
statement is false.
That is all very well, but what does it mean? An
example would be the expression (A> B); this has a value of 1 if A
is greater than B, and zero if A is less than or equal to B. It is
quite easy to experiment with this technique by typing into your
computer in direct mode. Try the following (each line must be
completed with RETURN):
A=1 :B=1 : ? "(A>B)="; (A>B)
A =1 : B =0 : C=1 : IF A =B OR A=C THEN ? "TRUE"
The relational operators are < (less than), >
(more than), = (equal to), < = (less than or equal to), > = (more
than or equal to), < > (not equal to). They can be used with the
Unary Operator NOT and the Logical Operators AND and OR. NOT
reverses the value of an expression so, for example, NOT(A = B) and
A < > B are effectively the same.
READING THE JOYSTICK
Joystick position is obtained in Basic from
STICK(0) for joystick port 1, STICK(1) for port 2. Alternatively
PEEK(632) gives the same value as STICK(0)and PEEK(633) the same as
STICK(1). The value returned depends on the direction in which the
joystick is pressed. Eight different directions are detectable
resulting in nine possible values including stick centred. Relating
joystick direction to the points of the compass the values are as
follows:
Position |
Decimal |
Binary |
|
|
|
Centered |
15 |
1111 |
N (Up) |
14 |
1110 |
NE |
6 |
0110 |
E (Right) |
7 |
0111 |
SE |
5 |
0101 |
S (Down) |
13 |
1101 |
SW |
9 |
1001 |
W (Left) |
11 |
1011 |
NW |
10 |
1010 |
The decimal numbers appear to be a rather random
set but if you look at the binary equivalent in the third column a
logical pattern appears showing that each cardinal point has a
switch which controls one bit of a 4 bit number.
The fire button or trigger on the joysticks is
detected in STRIG(0), STRIG(1) or by PEEK(644), PEEK(645). These
return a value of 0 if the trigger is pressed and 1 if it is not.
THE FIRST JOYSTICK SUBROUTINE
The first subroutine gives only up/down and
left/right movement.
Line 31100 - TT3 is the variable for
position across the screen (or column position). This could be the
position of the cursor or the position of a player. TT3 must be
changed to the variable name used in the main programme. TT3MAX is
the variable which defines the highest value to which the horizontal
position can go, normally the value of the right hand column on the
screen (which depends on the graphics mode in use). It is defined in
the main program to stop the cursor going off the screen causing an
ERROR 141 – cursor out of range.
The first (+) bracket of this line has a value of
1 if the joystick is to the right and the right hand limit has not
been reached while the second (1) bracket will have a value of 1 if
the stick is to the left and the cursor is not on column 0 (the
leftmost column on the screen). Thus the cursor will move right one
place if the first condition is satisfied, left if the second
condition is satisfied and stay in the same horizontal position if
neither is true. If you do not want the left hand edge of the screen
to be your limit you can define a variable TT3MIN in place of the
zero.
Line 31110 - This line is the same but for
vertical movement. TT4 is the vertical position (or row number) and
TT4MAX is the bottom of screen. Again if you wish to reduce the
height of travel use TT4MIN in place of the zero in the second
bracket.
This two line subroutine does nothing on its own
so I have included the programme Joydraw as a simple demonstration.
Combine Joydraw with the subroutine and when it is run you can move
around the screen with a joystick in position 1 drawing when the
trigger is pressed and erasing when the trigger is released.
The only line which may need clarifying is line
40. 'IF STRIG(0)' is the same as 'IF STRIG(0)=1' that is 'if the
trigger is not pressed.
THE SECOND JOYSTICK SUBROUTINE
The second subroutine takes account of the
diagonal positions of the joystick.
Line 31150 - For compactness TT5 has been
put equal to STICK(0). In the brackets TT5 <8 is when the joystick
is to the right while (TT5 > 8 AND TT5 < 12) is when the joystick is
to the left.
Line 31160 - Vertical position. The first
(+) bracket has the operator ((TT5-1)/4 = INT((TT5-1)/4)) which is
only true for values of TT5 of 5,9 and 13. You could use (TT5 =5 OR
TT5 =9 OR TT5 =13) instead and there must be other alternative
expressions. The second (-) bracket uses (TT5/2 = INT(TT5/2)) which
tests for an even number i.e. 6,10 and 14 for upward movement.
This subroutine can be tested with Joydraw by
changing line 50 to :
50 GOSUB 33150:GOTO 20
Familiarity with the logical operators is worth
while as they are invaluable for programming multiple condition
statements.
I hope that you can use these routines in your own
programs and you should be able to find other applications for this
type of programming.
|
|
|