This section clarifies all aspects of controlling a program by hardware. So we are exploiting the joystick and the keyboard in your programs.
A joystick can be used to control movement around the screen by pushing its handle in the desired direction, and to trigger all sorts of actions by pressing one or more buttons built in to its mechanism. Either of the two (or four) joystick sockets at the back or side of your computer will happily accept a joystick plug. If two/four users want to control one joystick each for specially written programs, all ports can be used. To make a joystick interact with your programs, the computer must be able to read its movements and actions. ugBASIC offers a number of useful functions to do just that.
The JOY
command inspects what is happening with the joystick and makes a report. The maximum number of joysticks installed in the system can be retrieved using the JOY COUNT
constant. If the joystick you are interested in is plugged into any joystick port, the computer must be told to look at that port number. For example:
DO j=JOY(1) PRINT BIN$(j,5),j LOOP
By running that routine, reports are given about the movements of the joystick and the status of the fire-button in the form of binary numbers. The pattern of ones and zeros in the report can then be inspected. Binary bits shown as zero indicate that nothing is happening, whereas if any of the bits in the report is shown as a one, it means that the joystick has been moved in the direction that relates to that bit.
Here is a list of those bits along with their meanings:
UP
(0) - joystick has been moved up;DOWN
(1) - joystick has been moved down;LEFT
(2) - joystick has been moved left;RIGHT
(3) - joystick has been moved right;FIRE
(4) - fire-button has been pressed.In ugBASIC bits can be checked in various way:
REM functional style left = BIT( JOY(1), LEFT ) PRINT "LEFT IS: ";left REM declarative style up = BIT UP OF JOY(1) PRINT "UP IS: ";up REM conditional style IF JOY(1) HAS BIT UP THEN : PRINT "UP" : ENDIF IF JOY(1) IS UP THEN : PRINT "UP" : ENDIF REM (negative) conditional style IF JOY(1) HAS NOT BIT UP THEN : PRINT "NOT UP" : ENDIF IF JOY(1) IS NOT UP THEN : PRINT "NOT UP" : ENDIF
Each of those aspects of the joystick status can be accessed individually, using the following functions:
JLEFT
- test for joystick movement towards the left;JRIGHT
- test for joystick movement towards the right;JUP
- test for joystick movement upwards;JDOWN
- test for joystick movement downwards;JFIRE
(or FIRE()
) - test for joystick fire button pressed.Every function will returns a value of -1 (meaning true) if the joystick connected to the given port number has been pushed to the directiong requested (or the button has been pressed), otherwise a value of 0 is returned (meaning false).
These functions can be demonstrated by the following example:
DO IF JLEFT(1) THEN PRINT "WEST" IF JRIGHT(1) THEN PRINT "EAST" IF JUP(1) THEN PRINT "NORTH" IF JDOWN(1) THEN PRINT "SOUTH" IF JFIRE(1) THEN CENTRE "BANG!" LOOP
The keyboard can be used to interact with your routines once they are running. This is vital for any sort of arcade game, adventure gaming or for more practical items such as word processing.
The INKEY$
function checks to see if a key has been pressed, and reports back its value in a string. For example:
DO k = INKEY$ IF k<>"" THEN : PRINT "YOU PRESSED A KEY!" : ENDIF LOOP
The INKEY$
function does not wait for you to input anything from the keyboard, so if a character is not entered an empty string is returned. INKEY$
can only register a key-press from one of the keys that carries its own ASCII code, and the ASCII code numbers that represent the characters which can be printed on the screen.
It has also been explained that special keys and the function keys do not carry as ASCII code at all, and if INKEY$
detects that this type of key has been pressed, a character with a value of zero will be returned. When this happens, the internal “scan codes” of these keys can be found.
The function SCANCODE
returns the internal scan code of a key that has already been entered using the INKEY$
function. The next example may be tested by pressing the function keys, F1 and F2.
DO WHILE k == "" k = INKEY$ WEND IF ASC(k)==0 THEN PRINT "NO ASCII CODE" PRINT "THE SCAN CODE IS ";SCANCODE k = "" LOOP
To determine if keys are pressed at the same time as either or both of the SHIFT keys, the SCANSHIFT
function returns the following values:
0
) - if no SHIFT key pressed;1
) - if the left SHIFT pressed;2
) - if the right SHIFT pressed;3
) - if both keys pressed.
LEFT SHIFT
and RIGHT SHIFT
are bitmask, you can use the previus syntax:
REM functional style left = BIT( SCANSHIFT, LEFT SHIFT ) PRINT "LEFT IS: ";left REM declarative style left = BIT LEFT SHIFT OF SCANSHIFT PRINT "LEFT IS: ";up REM conditional style IF SCANSHIFT HAS BIT LEFT SHIFT THEN : PRINT "LEFT" : ENDIF IF SCANSHIFT IS LEFT SHIFT THEN : PRINT "LEFT" : ENDIF REM (negative) conditional style IF SCANSHIFT HAS NOT BIT LEFT SHIFT THEN : PRINT "NOT LEFT" : ENDIF IF SCANSHIFT IS NOT LEFT SHIFT THEN : PRINT "NOT LEFT" : ENDIF
Try out the following example by pressing various keys, in combination with the SHIFT keys:
DO a = INKEY s = SCANSHIFT IF s <> 0 THEN PRINT s END IF LOOP
Use the KEY STATE
function to check whether or not a specific key has been pressed. The relevant scan code should be enclosed in brackets, and when the associated key is being pressed KEY STATE
will return a value of TRUE
(-1
), otherwise the result will be given as FALSE
(0
). For example:
DO IF KEY STATE(KEY F1) == TRUE THEN : PRINT "F1!" : ENDIF IF KEY STATE(KEY RUNSTOP) == TRUE THEN : PRINT "RUN STOP!" : ENDIF LOOP
On the same way, KEY SHIFT
is used to report the current status of those keys which cannot be detected by either INKEY$
or SCANCODE
because they do not carry the relevant codes. These control keys cannot be tested individually, or a test can be set up for any combination of such keys pressed together. A single call to the KEY SHIFT function can test for all eventualities, by examining a bit map in the following format:
0
) - if the left SHIFT is pressed;1
) - if the right SHIFT is pressed;2
) - if it is on or off3
) - if the CTRL is pressed;4
) - if the left ALT is pressed;5
) - if the right ALT is pressed; If the report reveals that a bit is set to 1, then the associated key has been held down by the user, otherwise a 0 is given. Here is a practical example:
CENTRE "PLEASE PRESS SOME CONTROL KEYS" CURS OFF DO LOCATE 14,4: PRINT BIN$(KEY SHIFT, 8) LOOP
When an appropriate character is entered from the keyboard, its ASCII CODE is placed in an area of memory called the keyboard buffer. This buffer is then examined by the INKEY$
function in order to report on key presses. CLEAR KEY
completely erases this buffer and re-sets the keyboard, making it a very useful command at the beginning of a program when the keyboard buffer may be filled with unwanted information. CLEAR KEY
can also be called immediately before a WAIT KEY
command, to make sure that the program waits for a fresh key-press
before proceeding.
The WAIT KEY
command waits for a single key-press before acting on the next instruction. For example:
PRINT "PLEASE PRESS A KEY" : WAIT KEY : PRINT "THANK YOU!"
The INPUT$
function loads a given number of characters into a string variable, waiting for the user to enter each character in turn. Although characters will not appear on the screen, similar to INKEY$
, the two instructions are totally different.
Here is an example:
CLEAR KEY : PRINT "PLEASE TYPE IN TEN CHARACTERS" v=INPUT$(10) : PRINT "YOU TYPED: ";v
The INPUT
command is used to enter information into one or more variables. Any variable may be used, as well as any set of variables, providing they are separated by commas. A question mark will automatically appear at the current cursor position as a prompt for your input.
REM ASK FOR A NUMBER AND A STRING INPUT A, K$
If your own “prompt string” is included, it will be printed out before your information is entered. Please note that a semi-colon must be used between your prompt text and the variable list, a comma is not allowed for this purpose. You may also use an optional semi-colon at the end of your variable list, to specify that the text cursor is not to be affected by the INPUT command, and will retain its original position after your data has been entered. When INPUT is executed, the program will wait for the required information to be entered via the keyboard, and each variable in the list must be matched by a single value entered by the user. These values must be of exactly the same type as the original variables, and should be separated by commas.
For example:
PRINT "TYPE IN A NUMBER" INPUT a PRINT "YOUR NUMBER WAS ";a INPUT "WHAT'S YOUR NAME?";name$ LOCATE 23, : PRINT "HELLO ";name$
LINE INPUT
is identical in usage to INPUT
, except that is uses a press of the RETURN key to separate each value you enter via the keyboard instead of a comma. Try this:
LINE INPUT "TYPE IN THREE NUMBER";a,b,c PRINT a,b,c
The PUT KEY
command loads a string of characters directly into the keyboard buffer, and it is most commonly used to set up defaults for your INPUT routines. Note that end of line returns can be included using a CHR$(13)
character. In the next example, NO
is assigned to the default INPUT
string.
DO PUT KEY "NO" INPUT "DO YOU WANT TO CONTINUE, YES OR NO: ";a$ b$ = UPPER$(a$) IF b$ == "NO" THEN BOOM : WAIT 50 : EXIT LOOP