Tutorial Subroutines

By Ian Finlayson

 

Issue 29

Sep/Oct 87

Next Article >>

<< Prev Article

 

 

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.

AtariLister - requires Java

  top