Chapter 16: Colours

BASin

Chapter 16: Colours

Summary

INK, PAPER, FLASH, BRIGHT, INVERSE, OVER, BORDER

Run this program:

 10 FOR m=4 TO 1: 
    BRIGHT m
 20 FOR n=1 TO 14
 30 FOR c=4 TO 7
 40 PAPER c: 
    PRINT "    ";: 
    REM 4 coloured spaces
 50 NEXT c: 
    NEXT n: 
    NEXT m
 60 FOR m=0 TO 1: 
    BRIGHT m: 
    PAPER 7
 70 FOR c=0 TO 3
 80 INK c: 
    PRINT c;"    ";
 90 NEXT c: 
    PAPER 0
100 FOR c=4 TO 7
110 INK c: 
    PRINT c;"    ";
120 NEXT c: 
    NEXT m
130 PAPER 7: 
    INK 0: 
    BRIGHT 0

This shows the eight colours (including white and black) and the two levels of brightness that BASin can produce. Here is a list of them for reference.

0

- black

1

- blue

2

- red

3

- purple, or magenta

4

- green

5

- pale blue, technically called cyan

6

- yellow

7

- white

On a black and white television, these numbers are in order of brightness.

To use these colours properly, you need to understand a bit about how the picture is arranged.

The picture is divided up into 768 (24 lines of 32) positions where characters can be printed, and each character is printed as an 8×8 square of dots like that below for a. This should remind you of the user-defined graphics in Chapter 14, where we had 0s for the white dots and 1s for the black dots.

The character position also has associated with it two colours: the ink, or foreground colour, which is the colour for the black dots in our square, and the paper, or background colour, which is used for the white dots. To start off with, every position has black ink and white paper so writing appears as black on white.

The character position also has a brightness (normal or extra bright) and something to say whether it flashes or not - flashing is done by swapping the ink and paper colours. This can all be coded into numbers, so a character position then has

  1. an 8×8 square of 0s and 1 s to define the shape of the character, with 0 for paper and 1 for ink,
  2. ink and paper colours, each coded into a number between 0 and 7,
  3. a brightness - 0 for normal, 1 for extra bright and
  4. a flash number - 0 for steady, 1 for flashing.

Note that since the ink and paper colours cover a whole character position, you cannot possibly have more than two colours in a given block of 64 dots. The same goes for the brightness and flash number: they refer to the whole character position, not individual dots. The colours, brightness and flash number at a given position are called attributes.

When you print something on the screen, you change the dot pattern at that position; it is less obvious, but still true, that you also change the attributes at that position. To start off with you do not notice this because everything is printed with black ink on white paper (and normal brightness and no flashing), but you can vary this with the INK, PAPER, BRIGHT and FLASH statements. Try

PAPER 5

and then print a few things: they will all appear on cyan paper, because as they are printed the paper colours at the positions they occupy are set to cyan (which has code 5).

The others work the same way, so after

PAPER number between 0 and 7
INK number between 0 and 7
BRIGHT 0 or 1 (Think of 0 as off and 1 as on)
or
FLASH 0 or 1

any printing will set the corresponding attribute at all the character positions it uses. Try some of these out. You should now be able to see how the program at the beginning worked (remember that a space is a character that has INK and PAPER the same colour).

There are some more numbers you can use in these statements that have less direct effects.

8 can be used in all four statements, and means 'transparent' in the sense that the old attribute shows through. Suppose, for instance, that you do

PAPER 8

No character position will ever have its paper colour set to 8 because there is no such colour; what happens is that when a position is printed on, its paper colour is left the same as it was before. INK 8, BRIGHT 8 and FLASH 8 work the same way for the other attributes.

9 can be used only with PAPER and INK, and means 'contrast'. The colour (ink or paper) that you use it with is made to contrast with the other by being made white if the other is a dark colour (black, blue, red or magenta), and black if the other is a light colour (green, cyan, yellow or white).

Try this by doing

INK 9: 
FOR c=0 TO 7: 
PAPER c: 
PRINT c: 
NEXT c

A more impressive display of its power is to run the program at the beginning to make coloured stripes, and then doing

INK 9: 
PAPER 8: 
PRINT AT 0,8;: 
FOR n=1 TO 1080: 
PRINT n;: 
NEXT n

The ink colour here is always made to contrast with the old paper colour at each position.

Colour television relies on the rather curious fact that the human eye can only really see three colours - the primary colours, blue, red and green. The other colours are mixtures of these. For instance, magenta is made by mixing blue with red - which is why its code, 3, is the sum of the codes for blue and red.

To see how all eight colours fit together, imagine three rectangular spotlights, coloured blue, red and green, shining at not quite the same place on a piece of white paper in the dark. Where they overlap you will see mixtures of colours, as shown by this program (note that ink spaces are obtained by using either Shift with 8 when in graphics mode):

  10 BORDER 0: 
     PAPER 0: 
     INK 7: 
     CLS
  20 FOR a=1 TO 6
  30 PRINT TAB 6; INK 1; "nnnnnnnnnnnnnnnnnn": 
     REM 18 ink squares
  40 NEXT a
  50 LET dataline=20
  60 GO SUB 1000
  70 LET dataline=210
  80 GO SUB 1000
  90 STOP
 200 DATA 2,3,7,5,4
 210 DATA 2,2,6,4,4
1000 FOR a=1 TO 6
1010 RESTORE dataline
1020 FOR b=1 TO 5
1030 READ c: 
     PRINT INK c;"nnnnnn";: 
     REM 6 ink squares
1040 NEXT b: 
     PRINT: 
     NEXT a
1050 RETURN

There is a function called ATTR that finds out what the attributes are at a given position on the screen. It is a fairly complicated function, so it has been relegated to the end of this chapter.

There are two more statements, INVERSE and OVER, which control not the attributes, but the dot pattern that is printed on the screen. They use the numbers 0 for off and 1 for on in the same way as FLASH and BRIGHT do, but those are the only possibilities. If you do INVERSE 1, then the dot patterns printed will be the inverse of their usual form: paper dots will be replaced by ink dots and vice versa. Thus a would be printed as

If (as at switch-on) we have black ink and white paper, then this a will appear as white on black - but we still have black ink and white paper at that character position. It is the dots that have changed.

The statement

OVER 1

sets into action a particular sort of overprinting. Normally when something is written into a character position it completely obliterates what was there before; but now the new character will simply be added in on top of the old one (but see Exercise 1). This can be particularly useful for writing composite characters, like letters with accents on them, as in this program to print out German letters - an 'o' with an umlaut above it. (Do NEW first.)

10 OVER 1
20 FOR n=1 TO 32
30 PRINT "o"; CHR$ 8;"""";
40 NEXT n

(notice the control character CHR$ 8 which backs up one space.)

There is another way of using INK, PAPER and so on which you will probably find more useful than having them as statements. You can put them as items in a PRINT statement (followed by ;), and they then do exactly the same as they would have done if they had been used as statements on their own, except that their effect is only temporary: it lasts as far as the end of the PRINT statement that contains them. Thus if you type

PRINT PAPER 6;"x";: 
PRINT "y"

then only the x will be on yellow.

INK and the rest when used as statements do not affect the colours of the lower part of the screen, where commands and INPUT data are typed in. The lower part of the screen uses the colour of the border for its paper colour and code 9 for contrast for its INK colour, has flashing off, and everything at normal brightness. You can change the border colour to any of the eight normal colours (not 8 or 9) using the statement

BORDER colour

When you type in INPUT data, it follows this rule of using contrasting ink on border coloured paper; but you can change the colour of the captions written by the computer by using INK and PAPER (and so on) items in the INPUT statement, just as you would in a PRINT statement. Their effect lasts either to the end of the statement, or until some INPUT data is typed in, whichever comes first. Try

INPUT FLASH 1; INK 1;"What is your number?";n

There is one more way of changing the colours by using control characters - rather like the control characters for AT and TAB in Chapter 15.

CHR$ 16 corresponds to INK
CHR$ 17 corresponds to PAPER
CHR$ 18 corresponds to FLASH
CHR$ 19 corresponds to BRIGHT
CHR$ 20 corresponds to INVERSE
CHR$ 21 corresponds to OVER

These are each followed by one character that shows a colour by its code: so (for instance)

PRINT CHR$ 16+CHR$ 9; . . .

has the same effect as

PRINT INK 9; . . .

On the whole, you would not bother to use these control characters because you might just as well use the colour items. However, one very useful thing you can do with them is put them in programs: this results in different parts being listed in different colours, to set them apart from each other or even just to look pretty. You must put them in after the line number, or they will just get lost.

To get these into the program, you have to enter them from the keyboard. Note that control characters tend to be less useful in BASin than on a real Spectrum, because BASin already uses colour for syntax highlighting.

The ATTR function has the form

ATTR (line, column)

Its two arguments are the line and column numbers that you would use in an AT item, and its result is a number that shows the colours and so on at the corresponding character position on the television screen. You can use this as freely in expressions as you can any other function.

The number that is the result is the sum of four other numbers as follows:

128 if the character position is flashing, 0 if it is steady
64 if the character position is bright, 0 if it is normal
8 * the code for the paper colour
the code for the ink colour

For instance, if the character position is flashing and normal with yellow paper and blue ink then the four numbers that we have to add together are 128, 0, 8*6=48 and 1, making 177 altogether. Test this with

PRINT AT 0,0; FLASH 1; PAPER 6; INK 1;" "; ATTR (0,0)

Exercises

  1. Try
    PRINT "B"; CHR$ 8; OVER 1;"/";

    Where the / has cut through the B, it has left a white dot. This is the way overprinting works: two papers or two inks give a paper, one of each gives an ink. This has the interesting property that if you overprint with the same thing twice you get back what you started off with. If you now type

    PRINT CHR$ 8; OVER 1;"/"

    why do you recover an unblemished B?
     

  2. Type
    BORDER 0: 
    PAPER 0: 
    INK 0: 
    CLS
    

    and notice that the '0 OK' report is printed in a contrasting colour to make it readable. Isn't it just as well that INK and PAPER don't affect the lower part of the screen?
     

  3. Run this program:
    10 POKE 22527+RND*704, RND*127
    20 GO TO 10
    

    Never mind how this works; it is changing the colours of squares on the television screen and the RNDs should ensure that this happens randomly. The diagonal stripes that you eventually see are a manifestation of the hidden pattern in RND - the pattern that makes it pseudorandom instead of truly random.

  4. Type or LOAD in the chess piece characters in Chapter 14, and then type in this program which draws a diagram of a chess position using them.

      5 REM draw blank board
     10 LET bb=1: 
        LET bw=2: 
        REM red and blue for board
     15 PAPER bw: 
        INK bb: 
        CLS
     20 PLOT 79,128: 
        REM border
     30 DRAW 65,0: 
        DRAW 0,-65
     40 DRAW -65,0: 
        DRAW 0,65
     50 PAPER bb
     60 REM board
     70 FOR n=0 TO 3: 
        FOR m=0 TO 3
     80 PRINT AT 6+2*n, 11+2*m;" "
     90 PRINT AT 7+2*n, 10+2*m;" "
    100 NEXT m: 
        NEXT n
    110 PAPER 8
    120 LET pw=6: 
        LET pb=5: 
        REM colours of white and black pieces
    200 DIM b$ (8,8): 
        REM positions of pieces
    205 REM set up initial positions
    210 LET b$(1)="rnbqkbnr"
    220 LET b$(2)="pppppppp"
    230 LET b$(7)="PPPPPPPP"
    240 LET b$(8)="RNBQKBNR"
    300 REM display board
    310 FOR n=1 TO 8: 
        FOR m=1 TO 8
    320 LET bc=CODE b$(n,m): 
        INK pw
    325 IF bc=CODE " " THEN 
        GO TO 350: 
        REM space
    330 IF bc>CODE "Z" THEN 
        INK pb: 
        LET bc=bc-32: 
        REM lower case for black
    340 LET bc=bc+79: 
        REM convert to graphics
    350 PRINT AT 5+n, 9+m; CHR$ bc
    360 NEXT m: 
        NEXT n
    400 PAPER 7: 
        INK 0
    

Chapter 17

Chapter 15