Simple screen graphics with MSX Basic. David H. Ahl.
Would you like to be able to draw borders easily, plot a projectile, or make fancy geometric patterns? With the rich library of graphics commands buitlt into MSX Basic, it is easy, but it is a bit different from some other computers.
MSX Basic has three screen modes, appropriately called SCREEN 0, SCREEN 1, and SCREEN 2. SCREEN 0 is the text mode and permits only limited graphics using the LOCATE command. Using LOCATE, you can move the cursor to any point on the screen ranging from 0 to 36 in the horizontal direction, and 0 to 23 in the vertical direction. Remember, vertical locations are numbered from the top of the screen to the bottom.
The LOCATE command is always used with the PRINT command to put something on the screen. As a result, the character printed is actually placed on the screen one location to the right of the position defined in the LOCATE command. Thus, if you type the commands:
LOCATE 10,15: PRINT "X" the X will be located at screen location 11,15. Since LOCATE permits only very low resolution graphics, we will concentrate on SCREEN 1 AND 2.
The horizontal (x) and vertical (y) coordinates used with SCREEN 1 and 2 are the same. X ranges from 0 to 255, and y ranges from 0 to 191. However, the main graphics command, PSET, illuminates a single pixel on SCREEN 1 and a 4 x 4 block of pixels on SCREEN 2. Thus, the effective resolution of SCREEN 1 is 256 x 192, and of SCREEN 2 is 64 x 48. Draw A Border
You can draw a point anywhere on the screen using the PSET command.
Try illuminating the center pixel on the screen using both screen modes. Here is a program to do this for mode 1. Change line 10 to SCREEN 2 and see what happens.
10 SCREEN 1
20 PSET (128,96) 30 GOTO 30
Now, how would you draw a line? One way would be to use a series of PSET statements, for example:
10 SCREEN 1
20 PSET (1,23) 610 PSET (60,23)
30 PSET (2,23) 620 PSET (61,I3)
40 PSET (3,23) 630 PSET (62,23)
50 PSET (4,23) 640 PSET (63,23)
60 PSET (5,23) 650 GOTO 650
Obviously, this is very inefficient and cumbersome. Consider this alternative:
10 SCREEN 1
20 FOR X=0 TO 255
30 PSET (X,23)
40 NEXT X
50 GOTO 50
Now, let us say you want to draw a border. As long as we are letting x vary from the left to right of the screen, why not draw two horizontal lines at once, one at the top and one at the bottom? Here is a modification of our previous program to do this:
10 SCREEN 1
20 FOR X=0 TO 255
30 PSET (X,0)
35 PSET (X,191)
40 NEXT X
50 GOTO 50
But we would also like to draw vertical borders, too. We can add two statements to do so. Run this program and see what happens.
10 SCREEN 1
20 FOR X=0 TO 255
30 PSET (X,0)
35 PSET (X,191)
36 PSET (0,X)
37 PSET N255,X)
40 NEXT X
50 GOTO 50
It works, but the vertical lines finish before the horizontal ones do. Why? Because, the vertical height of the screen is only 192 pixels, and the width is 256. Thus, we should put a line in our program to test for values out of range. Renumber your program using renum 10 and line 45 to test for vertical values over 191:
45 IF X>191 THEN 70
The final program is one of the shortest ways to draw a border. Remember it and use it when you need a border.
10 SCREEN 1
20 FOR X=0 TO 255
30 PSET (X,0)
40 PSET (X,191)
45 IF X>191 THEN 70
50 PSET (0,X)
60 PSET (255,X)
70 NEXT X
80 GOTO 80
Now, let's try this program with SCREEN 2. It works, but we can make it run much faster. Remember, each PSET lights up a 4 x 4 pixel block. Hence, we can change our FOR loop in line 20 to use a step size of four.
On screen mode 2, you can also add color. The third variable in the PSET statement is color. Most MSX Basic computers give you a choice of 15 colors. Color 0, transparent, is not really a color, so realistically your pallette consists of 14 colors. Here is a program to draw a border in color 2 (medium green).
10 SCREEN 2
15 C=2
20 FOR X=0 TO 255 STEP 4
30 PSET (X,0),C
40 PSET (X,191),C
45 IF X>191 THEN 70
50 PSET (0,X),C
60 PSET (255,X),C
70 NEXT X
80 GOTO 80 Multiple Borders
In the previous program, instead of having the border print at the edges of the screen, it is possible to let the non-X value vary. We will let the distance or increment from the edge of the screen be I. The value I can be used as the coordinate for the
top and left side, however, the right side must be defined as
255-I and the bottom as 192-I.
Here is a program that uses these relationships to draw a series of borders which start at random points in the upper left quarter of the screen. Note that the test to see if the maximum y value has been exceeded has changed somewhat. Can you explain why?
10 SCREEN 2
20 C=INT(15*RND(1))
30 I=INT(92*RND(1))
40X2=255-I
50 Y2=191-I
60 FOR X=I TO X2 STEP 4
70 PSET (X,I),C
80 PSE (X,Y2),C
90 IF X2-X<=64 THEN 120
100 PSET (I,X),C
110 PSET (X2,X),C
120 NEXT X
130 GOTO 20
As you run this program, you will notice that many of the borders do not join correctly in the lower right corner. Why
not? It is because the border may start at any location as defined by the random number function in line 30, but 4 x 4 blocks are being illuminated and the last one may be left off. There are several ways to correct this. Try to devise at least two ways.
One way to correct the above problem is to make sure the random number is a multiple of four. Simply substitute this line 30 for the one in the program, and all will be fine.
30 I=4*INT(23*RND(1)) Bouncing Ball
Let us start with just four statements, one to give us a starting point for the plot of a bouncing ball, one to plot the ball, and one to repeat the plot.
10 X=8:Y=8
50 SCREEN 2
160 PSET (X,Y)
190 GOTO 160
Well, that is certainly a long way from bouncing. We can get the ball moving with these lines:
20 I=4:J=4
90 X=X+I
100 Y=Y+J
190 GOTO 90
We are off to a good start, but unfortunately the ball rolls right off the bottom of the screen. Hence, we must add four IF statements to test for the screen edges. Depending upon the values in these statements and the starting point of the ball, several things can happen. Most common is for the plot at some point to start retracing a previous line. We used trial and error to choose these values: they are not the only ones that will work to eliminate line retracing. Try other starting points in line 10 and screen edge points in line 110 to 140 and see what happens.
110 IF X>=254 THEN I=-I
120 IF X<=1 THEN I=-I
130 IF Y>=192 THEN J=-J
140 IF Y<=1 THEN J=-J
Would you like a ball that changes color? If so, you can add the following line 150:
150 C=INT(15*RND(1))
160 PSET (X,Y),C
You will find that this line slows the program down a good deal. Another interesting way to get color is to relate it to the x or y value. Here is a line that works nicely:
150 C=Y/13
While this program produces pretty patterns, it is hardly a bouncing ball. The problem is that it does not erase the previous ball position when it draws a new one.
On your computer, these lines will do that. Our computer (a Spectra Video 328) uses medium blue (color 4) as a background color, so plotting a point in this color is the same as erasing a point in another color. The PRESET command can also be used to erase an illuminated pixel or block.
70 C=4
80 PSET (X,Y),C
190 GOTO 70
Now the program works as it ought to. You may find that the ball moves too fast to be seen. If so, you can put in some sort of delay after line 160. We have added a few lines to let the user select a bouncing ball or a continuous line (which produces the pattern we saw earlier). If you want a sound when the ball hits the edge of the screen, you can add a BEEP in lines 110 through 140. Here is our final program.
5 DEFINT C,I,J,X,Y
10 X=2:Y=2
20 I=4:J=4
30 INPUT "Leave trail (Y or N)";A$
40 COLOR 15,15
50 SCREEN 2
70 C=4
80 PSET (X,Y),C
90 X=X+I
110 IF X>=254 THEN I=-I :BEEP
120 IF X<=1 THEN I=-I :BEEP
130 IF Y>=192 THEN J=-J :BEEP
140 IF Y<=1 THEN J=-J :BEEP
150 C=Y/13
160 PSET (X,Y),C
180 IF A$="Y" OR A$="Y" THEN 90
190 GOTO 70
When a trail is left, the plot eventually fills in every other screen location. How could you modify it to fill in every location? There are several ways to accomplish this, some of which produce more interesting effects than others. Hint: try doing it with a random variable. Plot a Projectile
Let's say we want to plot the motion of projectile from a gun on the left of the screen to a target on the right. Let's start by setting the screen mode and plotting a point.
40 SCREEN 1
130 PSET (X,Y)
What point do we plot? From physics, do you remember the equations for the horizontal and vertical positions of an object (projectile, ball, arrow, etc.) in the absence of air resistance? they are:
X = V.sup.*cos(a).sup.*t
Y = V.sup.*sin(a).sup.*t-1/2.sup.*.g.sup.*t.sup.2
For a complete discussion, turn to any physis book or the section on projectile in Computer in Science and Social Studies.
The maximum range of a gun is obtained with a firing angle of 45 degrees. Let's say that the gun has a muzzle velocity (V) of 1000 feet per second. The acceleration due to gravity (on Earth) is 32 ft/sec/sec. Then, the time until the projectile returns to Earth is given by the formula: T = 2.sup.*.V.sup.*sin(a) / g = 2.sup.*1000.sup.*.707 / 32 = 44.2
And the maximum range is: R = V.sup.2 / g = 1000.sup.2 / 32 = 31250
Since this will not fit on the screen, we must divide the horizontal distance (31250) by a constant (125). This gives a maximum horizontal distance of 250 pixels, which fits nicely on the screen.
On most computers, the distance between horizontal and vertical pixels is not the same. In other words, if you plotted a square 100 pixels on a side, it would not actually be square. To make it square, you have to multiply the vertical distance by 1.2.
We have combined all of the information above and put it into our program. Try this on your computer.
10 A=45
20 V=1000 :G=32
30 D=180/3.1415926#
40 SCREEN 1
50 CX=V*COS(A/D)
60 CY=V*SIN(A/D)
80 FOR T=0 TO 44.2 STEP .2
90 X=CX*T
100 Y=CY*T-16*T*T
110 X=X/125
120 Y=Y/125*1.2
130 PSET (X,Y)
140 NEXT T
150 GOTO 150
In the program, the variable D is a factor that converts degrees into radians, which is what Basic requires, CX and CY are constants for each firing angle.
What happened when you ran the program? It should work except the plot is upside down. But of course: vertical distances on the computer are measured from the top down so we must make a simple correction:
120 Y=192-(Y/125*1.2)
Now, let us modify the program to accept any firing angle for our gun. You need add only a few lines.
10 INPUT "ANSLE OF SUN";A
70 T1=2*CY/G
Experiment with this program. Try different firing angles. Try to tigthen up the code and make it faster. Here is one approach.
10 INPT "ANSLE OF SUN";A
20 V=1000 :G=32
30 D=180/3.1415926#
40 SCREEN 1
50 CX=V*COS(A/D)/125
60 CY=V*SIN(A/D)
70 T1=2*CY/G
80 FOR T=0 TO T1 STEP .2
90 X=CX*T
100 Y=192-9.6E-03*(T*CY-16*T))
110 PSET (X,Y)
120 NEXT T
130 GOTO 130
See if you can make this program into a game in which the player on the left must hit a target on the right.
Expl Explosions
Here is a short little routine to produce marvelous multi-colored explosions. You can easily figure out how it works, but can you add interesting sounds?
200 CLS
210 A=INT(15*RND(1))
220 B=INT(15*RND(1))
230 COLOR A,B
240 FOR Z=1 TO 10*B:NEXT
250 GOTO 210
Do you really need line 210? Of course not! In facT, the routine works much better if you simply put in:
210 A=0 Circles and Targets
MSX Basic has a generalized CIRCLE command built in. By generalized, we mean that it actually can draw a circle, ellipse, or arc with any center and any aspect ratio. For now, we will stick to circles. Let us draw a concentric ring of circles and fill in each one with a different color.
We will put the center of each circle at the center of the screen (128,96) and will make each one of the circles 7 pixels smaller in radius (I) than the preceding one. We will step through the 14 colors painting each one with a different color. The program to do this takes only nine lines.
10 SCREEN 1
20 COLOR 1,1,1
3 C=2
40 FOR I=98 TO 1 STEP -7
50 CRICLE(128,96),I,C
60 PAINT(128,95),C
70 C=C+1
80 NEXT
90 GOTO 90
The next article in this series will discuss plotting various functions, the Sierpinskey curve, polygons, and spirals.