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.
The ugBASIC language 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:
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
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.TRUE
(meaning-1) 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).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
FIRE
button
to be pressed on the joystick, you can use the WAIT FIRE
command.
The ugBASIC language generally provides two ways to read the joystick
position.
The first, which is the most precise and timely, is the so-called synchronous
readings. In this case, the value of the joystick position is read at the exact moment
in which it is requested. The advantage of this technique is that you get the
instantaneous position of the joystick, and it is less demanding on the computer.
The disadvantage is that, if you are not regular in the readings, you can get irregular
movements.
On the contrary, the asynchronous readings uses the so-called "interrupts" to perform
the reading. In other words, at regular intervals the execution is interrupted and
the position of the joystick at that moment is read. The program, when it requests
the joystick position, actually gets the last known position. The major disadvantage
of this technique is that it can be demanding on the computer, depending on the
target. However, it has the undoubted advantage of ensuring regularity in the readings
over time, and so you can get regular movements.
Both modes can be selected with a specific pragma:
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:
NO SHIFT
(0) - if no SHIFT key pressed;LEFT SHIFT
(1) - if the left SHIFT pressed;RIGHT SHIFT
(2) - if the right SHIFT pressed;BOTH SHIFTS
(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
SHIFT
keys:DO
a = INKEY
s = SCANSHIFT
IF s <> 0 THEN
PRINT s
END IF
LOOP
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
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:LEFT SHIFT
(0) - if the left SHIFT is pressed;RIGHT SHIFT
(1) - if the right SHIFT is pressed;CAPS LOCK
(2) - if it is on or offCTRL
(3) - if the CTRL is pressed;LEFT ALT
(4) - if the left ALT is pressed;RIGHT ALT
(5) - if the right ALT is pressed;CENTRE "PLEASE PRESS SOME CONTROL KEYS"
CURS OFF
DO
LOCATE 14,4: PRINT BIN$(KEY SHIFT, 8)
LOOP
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.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!"
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.CLEAR KEY : PRINT "PLEASE TYPE IN TEN CHARACTERS"
v=INPUT$(10) : PRINT "YOU TYPED: ";
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$
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.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
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
The ugBASIC language provides also for keyboard two ways to read the keys.
The first, which is the most precise and timely, is the so-called synchronous
readings. In this case, the value of keyboard is read at the exact moment
in which it is requested. The advantage of this technique is that you get the
instantaneous key pressed, and it is less demanding on the computer.
The disadvantage is that, if you are not regular in the readings, you can miss
keystrokes.
On the contrary, the asynchronous readings uses the so-called "interrupts" to perform
the reading. In other words, at regular intervals the execution is interrupted and
the key pressed on keyboard at that moment is read. The program, when it requests
any key, actually gets the last pressed. The major disadvantage
of this technique is that it can be demanding on the computer, depending on the
target. However, it has the undoubted advantage of ensuring regularity in the readings
over time, and so you can avoid to lose keystrokes.
Both modes can be selected with a specific pragma:
If you have found a problem, if you think there is a bug or, more
simply, you would like something to be improved, write a topic on the official forum, or open an issue on GitHub.
Thank you!