Bullfrog Part 1
Be a real programmer
Sim City has a bugged traffic algorithm, Powerdrift is too slow and Cadaver needs more levels. Stop whingeing when a game doesn't live up to expectations and sit down and write your own. Game-makers Bullfrog show you how easy it is.
Every now and again, the odd group of school children is ferried down to gloomy Guildford to see how real programmers work. Bullfrog don't just demonstrate how far they've got with Populous 2 though. They actually sit people down and take them through a crash course in programming in assembly language. “We can have people writing their own routines to move things about the screen in an hour," boasts Peter Molyneux, head honcho at Bullfrog. Not bad — especially when most children can't tell the difference between assembly language and Swahili.
As testament to Bullfrog's training abilities, two of their programmers started off knowing nothing about assembly. Six weeks later they were helping out on a couple of games. Sean Cooper even went on to write Flood — the Bullfrogs' contribution to the array of cutesy platform games.
Now Bullfrog are committing that tutorial to paper exclusively for ST FORMAT. In the next six issues they guide you through the complexities of assembly programming from a game-maker's perspective. Learn how to move sprites across the screen, how to read information from the joystick ports and how to manipulate the ST's screen memory.
Accompanying the series is a selection of files written in Devpac 1. For this first part we're giving away the complete Devpac 1 on the Cover Disk to enable you to load and edit the Bullfrogs' own assembly routines or go ahead and write your own.
Assembly language is very close to the ST's own internal language, so the programs it produces tend to be extremely fast — ideal for writing games. Unfortunately, because it's so close to the ST's language the code looks vastly complex and daunting enough to put you off programming for life.
However, if you can write programs in BASIC you already know something of the principles of programming. BASIC uses an interpreter which translates near-English instructions into machine code your ST can understand. You need many lines of machine code to perform the equivalent of a single BASIC instruction, but in assembly language every instruction has an exact machine code equivalent so you don't need an Interpreter. The biggest problem confronting any newcomer to assembly is actually the dispiriting mass of technical information required.
"You need to learn all about initialising your ST, screen addressing and different resolutions before you can get anywhere close to putting a single pixel on the screen. This means months of hard work, poring over badly written technical manuals and crashing your ST over and over again with instructions you don't understand. By including routines on our Cover Disk we can help you overcome this first hurdle and get straight to the fun bit. Before we start, though, here are a couple of helpful pointers:
- You must want to program. This sounds obvious but the most important factor that makes a good games programmer is enthusiasm. You can teach people to program but you can't teach them enthusiasm.
- Find out all you can about 68000 machine code. To make the most of it, invest in a book which explains the instructions to you. While you're waiting for the next issue of ST FORMAT to hit the shelves, you can play around with different assembly commands and take your programming a stage further. You might cause your ST to crash a few times but it can't do any harm.
The file called SPRITES.S on this month's Cover Disk contains all the sprite and set-up routines we used in Flood. Consequently, all you have to worry about is learning how to animate your sprites and the principles of game logic.
The program on the disk sets up the screen and then draws a sprite. At this point it's best to ignore these two functions and just accept that they work correctly — we're going into these at a later stage. For now we want to consider the actual animation and movement of a sprite.
Look through the program and locate the area where the sprite is put onto the screen (at line 69). This is the area of the program where all the real business goes on. Your first step is to create some variables for the position of the sprite and its state of animation.
You can call these anything, but use a name which you recognise: sprite_x, sprite_y and sprite_anim. The variables sprite_x and sprite_y are the coordinates of the sprite. Sprite_anim is the frame number we want to display.
To add these to your program change the three instructions at line 71 from
move.w #32,d0 move.w #32,d1 move.w #0,d2
move.w sprite_x,d0 move.w sprite_y,d1 move.w sprite_anim,d2
This means that when the sprite is drawn, its position and animation frame are drawn according to the values in the new variables. You can now change them at any time and the sprite moves accordingly. We also need to allocate the memory for these variables by adding the following lines near the very end of the file, just before the line of asterisks (line 528):
sprite_x dc.w 32 sprite_y dc.w 32 sprite_anim dc.w 0
These lines declare the variable name and define memory space for word sized variables. They set the initial value for the variables to 32, 32 and 0 respectively.
At this point it should be possible to assemble the file and run it. There shouldn't be any difference in the execution of the program — this is because the variables have the same value now as they had in the original program. Even so, we can add lines of programming code (or source) to make the sprite move on screen very easily.
To make the sprite move from left to right we can simply add an amount to the value of sprite_x. The larger the amount, the faster the sprite moves. At a later date we can change the program so that the sprite moves according to an input received from the joystick but for now we need to add one to sprite_x and move it slowly across the screen.
At line 80 (in the area marked in comments for the sprite movement) add the following lines:
move.w sprite_x,d0 ;move the value in sprite_x into d0 add.w #l,d0 ;add 1 to it cmp.w #280,d0 ;see if the value in d0 is less than 280 ble.s less_than move.w #32,d0 ;if it isn't then change it to 32 less_than move.w d0,sprite_x ;put it back into sprite_x
These instructions increase the value of the sprite's x coordinate by one each time the screen is redrawn. Then the value is compared with 280, and if its greater the position is reset to 32. Otherwise the value must be less than or equal to 280 and the program jumps to a point in the code immediately after the instruction to reset the sprite_x. The value currently in d0 is then stored back in sprite_x ready for the next draw.
Assemble the file at this point and you can then watch the sprite move slowly across the screen from left to right. This continues until it gets near to the right side of the screen, at which point it jumps back to the left and then continues moving to the right again. Now we can animate the sprite. Set the sprite_x increment to 0 by removing the line add.w #l,d0 from the above code. This has the effect of making the sprite immobile. You can remedy this by adding this line of code:
add.w #l,d0 cmp.w #7,d0 ble.s less move.w #0,d0 less move.w d0,sprite_anim
This displays eight frames of animation from 0-7 and then repeats this continuously at a ridiculously fast rate — far too fast to use in a game. To slow the rate down simply change the line:
And after the line which you typed into the draw sprites area
add the following:
asr #4,d2 ;this divides by 16
This code does exactly the same as the previous section except it's slower. Don't worry about the asr #4,d2 command just yet. All you need to know right now is that it divides a number by 16. The reason we use this instruction is to display each frame 16 times before moving onto the next. Now if you put the sprite_x increment back in, our cuddly sprite moves across the screen while melting!
These routines aren't as fast or as efficient as they could be — that comes later. What we've tried to do is to make them as simple to understand as possible. Next month we'll look more closely at what you can do with your sprite. In the meantime play around and see how the values of the variables affect the movement of the sprite. You might crash your ST a few times but you can't do any serious damage.
If you have any idea what should go in this box, please let me know! :)