Today let’s have a look a program that moves a character around the screen using the W,A,S,D keyboard keys. The character moves around the screen and stays within the borders, as you would expect in a top-down style game.
Fortunately the program was short enough to fit into a single screen, because I still don’t have a storage device for my Commodore 64.
Keep in mind that this little program is something that I put together myself as part of my relearning of BASIC programming – it’s just an example of how something is done, not BASIC gospel!
1 P=1024+480:PRINT CHR$(147):POKE P,0
10 GET N$
20 IF N$="W" THEN GOSUB 100
30 IF N$="S" THEN GOSUB 200
40 IF N$="A" THEN GOSUB 300
50 IF N$="D" THEN GOSUB 400
60 GOTO 10
100 IF P<1064 THEN RETURN
110 PRINT CHR$(147)
120 P=P-40: POKE P,0: RETURN
200 IF P>1983 THEN RETURN
210 PRINT CHR$(147)
220 P=P+40: POKE P,0: RETURN
300 M=P-1024: IF M-INT(M/40)*40=0 THEN RETURN
310 PRINT CHR$(147)
320 P=P-1: POKE P,0: RETURN
400 M=P-1024: IF M-INT(M/40)*40=39 THEN RETURN
410 PRINT CHR$(147)
420 P=P+1: POKE P,0: RETURN
Line By Line Description
1 Initial screen position of @ character: clear screen: Draw @
10 Get keyboard input
20 IF Input = "W" THEN jump to line 100
30 IF Input = "S" THEN jump to line 200
40 IF Input = "A" THEN jump to line 300
50 IF Input = "D" THEN jump to line 400
60 GOTO 10 to loop through getting input approx 60 times/second
100 IF @ is already on top row, do nothing
110 clear screen
120 move @ up 1 line:Draw @: RETURN
200 IF @ is already on bottom row, do nothing
210 clear screen
220 move @ down 1 line: Draw @: RETURN
300 IF already on left edge, do nothing
310 clear screen
320 move @ up 1 line: Draw @: RETURN
400 IF already on right edge, do nothing
410 clear screen
420 move @ down 1 line: Draw @: RETURN
Due to the use of a subroutine (“function” in modern lingo) that jumps away from the GET statement using GOSUB, holding a movement key down does not repeat the movement of the character.
Lines 10 to 60 are the “game loop” that repeats roughly 60 times per second. Each time the player moves the @ character, the whole screen is erased and redrawn. This is similar to what happens in more modern game engines, just things are so fast and abstract in new game engines that redrawing the screen is taken for granted. Here with character graphics, one must manually redraw the screen, otherwise the old characters would still be there.
Lines 100, 200, 300, and 400 are used to keep the character from going off the top or bottom of the screen or from wrapping around to the next line on the screen. Lines 300 and 400 use the modulus principle (remainder after dividing) to determine the column that the character is in. In other languages it would be as simple as typing 5 % 2, which would equal 1, but BASIC 2.0 on the Commodore 64 does not have a modulus operator. I had to take the screen position and calculate it the modulus the long way, like so,
M = P-1024
M = Current Screen Memory Address – Screen Memory Start Address
M = Location in grid, a number between 0 and 999
The screen is laid out basically as a grid of 1000 sections, with 25 horizontal rows of 40 vertical columns, numbered 0 to 999. Knowing this, we can find what column the character is in using modulus like so,
Location in Grid – INT(Locaction in Grid / Length of Row)*Length of Row
Row = M – INT(M/40)*40
Where the INT() function drops any decimal places, such as 34.32 becomes just plain old 34. We know that the left most column is 0 and the right most is 39, so if the @ character is already there, then we don’t need to move it more in that direction.
This simple program can be extended by adding more functions to the game loop in a similar manner as those you see above: GOSUB to some line, do some stuff, return to line below where you GOSUB’d from. Is it perfect? No, but it’s essentially the starting point of games such as Pong and Snake.