Basic Joystick Programming

From Ninerpedia
Jump to navigation Jump to search

This article will demonstrate how to program in TI Basic for using a joystick to move a character, and also demonstrate how a program can take input from either a joystick or the keyboard.

Joystick input

The CALL JOYST format is not ideally written for the TI99/4A. The row and column variables are reversed compared to the graphics commands, and the subprogram seems to assume the screen origin is at bottom left (it is actually at top left).

The return variables are placed in the command as follows: CALL JOYST(NUMBER,COLRETURN,ROWRETURN)

whereas the graphics commands are in the form: CALL HCHAR(ROW,COL,CODE)

To move a character to the screen left, we need to decrease the value of the column. If the joystick is moved to the left, the column return variable is indeed negative, while movement to the right gives a positive return.

However, the top of the screen is Row 1, so to move down the screen the row must be increased : move the joystick down and the row return variable is NEGATIVE. This can cause confusion very easily! The sign has to be changed to make this work!

Sample code

If we wish to amend ROW and COL variables using the joystick, it is necessary to use:


Notice the different signs used to amend the row and column variables. We have to divide by four because the CALL JOYST will only return 4, 0, or -4.

Which joystick

To use the above in a program leaves one problem: you need to know which is joystick number one! This can be marked, but you can also scan both joysticks:

120 ROW=ROW-RR/4-RR2/4
130 COL=COL+CR/4+CR2/4  

This will take a little longer to process and you will have to see the effect in your program before you decide to use it.

Remember: the alphalock MUST be up

for the joystick to work correctly

Interference with split keyboard

Common to all forms of Extended Basic I have tried, there is interference with the status returned when using CALL KEY with a split keyboard code together with a CALL JOYST. There is no solution. Here is the troublesome code area:

Type and run this:

100 CALL KEY(3,A,B) :: PRINT B;B;B :: CALL JOYST(1,X,Y) :: GOTO 100

Now hold down a key on the RIGHT hand side continuously. What you get is a lot of +1's..

Using CALL KEY the second value returned tells you if a new key has been pressed.

A +1 means a new key has been pressed. But you have just held the key down continuously, NO new key...

Now instead hold down a key on the LEFT hand side of the keyboard. You MAY get a lot of -1 values, with the odd +1 value.

Break the program and edit it to use JOYST(2, instead of JOYST(1,. Any change when you hold down left or right keys?

These results are NOT what you might expect, and could well cause problems, especially if you use a CALL KEY to scan for the fire button AND check its status as well.

Joystick status

When using CALL KEY there is a status return we can check to see if NO key has been pressed. With joysticks there is no status return, only the return variables. A status return can however be created.

Instead of the CALL KEY "IF ST=0 THEN", using CALL JOYST(1,X,Y) it is possible to use "IF X+2*Y=0 THEN"

Why multiply the second return by 2? Check through all the possible returns from the joystick and you will see that a simple addition, subtraction or multiplication will not return a unique answer to equate with "joystick central".

Refer to sample program found below.

Explanation of sample program below

Amending the variables ROW and COL and checking to see if they are valid. To use HCHAR etc they must be from 1 to 24 or 32 respectively. Anything else will produce an error message and halt the program.

It is possible to use lots of lines of coding in TI Basic:

200 IF ROW<1 THEN 210 ELSE 220
210 ROW=1
220 IF ROW>24 THEN 230 ELSE 240
230 ROW=24.....

and so on.

It is easier however to add to the ROW incremental line a value check which will reverse the increment if it places the value outside the limits.

To do this we need to use the relational expressions.

If a relational expression is TRUE it has a value of -1

If a relational expression is FALSE it has a value of 0 (the computer sees this as "NOT -1")

Thus PRINT(2=3) will appear as 0, but PRINT(2=2) will appear as -1.

Dealing with the ROW first, if the variable ROW starts with a value of 1, and the joystick is pushed up, we must reverse the reduction of ROW.

There are two expressions which must be true : if both ROW=1 and RR=4 then after we have added 1 to ROW we must deduct it, to leave it set to 1:


Now it is impossible for ROW to become less than 1.

This has been developed further in the sample program which you will find at the bottom.

A typical use of the joystick is to move a character around the screen, and this is what the sample program will do. To give greater flexibility, this program checks both joysticks, and also checks the keyboard (keys WERSDZXC).

First the screen is cleared and the row and column variables are set to initial values. Our character is placed on screen and the joysticks and keyboard are scanned.

The next line checks to see if an input has been made: if neither joystick nor the keyboard has been used, the program will go back and look at the joysticks/keyboard again. The plus sign between the relational expressions serves as an 'OR'.

If the status of one keyboard unit is NOT zero, the program continues.

Now the program is divided into two. If the keyboard has been used, the variable ST will have a non-zero value which causes the program to branch to the keyboard section. Otherwise it continues with the joystick section.

The joystick section is a slight development of what has been discussed above. We are checking for both limits to the row variable.

The keyboard section uses similar principles,but the limit checks are a little different: If the ROW variable has a value of 1, it cannot be decreased as (RW<>1) takes a value 0 (false) and no change is made.

In the sample program a character is moved around the screen, but if you wish to leave a line of characters, just delete the line which places a blank (32) in the old position.

That was quite a complex program to develop, so check it over thoroughly. The use of relational expressions can become quite complex, but they can both speed up execution time and save memory usage.

Joystick and Keyboard control program

110 RW=12
120 CL=16
140 CALL KEY(1,K,ST)
170 IF (CR+2*RR<>0)+(CR2+2*RR2<>0)+(ST<>0)THEN 180 ELSE 140
180 IF ST THEN 240
200 RW=RW-RR/4-RR2/4+(RW=1)*((RR=4)+(RR2=4))-(RW=24)*((RR<0)+
210 CL=CL+CR/4+CR2/4+(CL=1)*((CR<0)+(CR2<2))-(CL=32)*((CR>0)+
230 GOTO 140
250 RW=RW-(RW<>1)*((K=5)+(K=4)+(K=6))+(RW<>24)*((K=15)+(K+1=1)+
260 CL=CL-(CL<>1)*((K=4)+(K=2)+(K=15))+(CL<>32)*((K=6)+(K=3)+
280 GOTO 140

The K+1=1 in line 250 needs to be written this way- see the explanation on the internal representation of zero when using TI BASIC and testing a split keyboard key value for the down arrow keys X and M. The bug is not present in Extended Basic.