farren@well.sf.ca.us (Mike Farren) (03/24/91)
NOTICE - this entire posting is Copyright (c) 1991 by Michael J. Farren. The only reproduction rights granted under this copyright are for electronic transmission between Usenet sites, and other sites connected to Usenet sites. Contact farren@well.sf.ca.us for reproduction rights other than the above. Level 2 - MASSA'S IN THE CODE, CODE GROUND The second Big Excuse game developers use, this time to justify taking over the machine, killing multitasking, or not using the Amiga ROM Kernel routines, goes something like "but if we didn't, we couldn't do real time stuff that ran smoothly". Let's take a look at that one in a little more detail, again (as always) using Lemmings as the example. Also, this will continue the memory discussion from the earlier post, since I also need to show that everything will fit into 80K of code space. First, let's plan out just what the code that runs Lemmings needs to do. Let's look at the series of actions that take place every time a screen is changed. I call the interval between screen changes a "frame". Not standard terminology, but I'm used to it. At the beginning of each frame, one of the screen buffers is being shown on the screen, and the other is sitting in the background, waiting to be redrawn. For each frame, the following things happen: - First, the appropriate image for each animated object (flames, traps, stuff like that) is drawn into the buffer which is currently non-visible. This includes the exit box - and this explains how you can get a "buried" object, or an exit box which is hidden, as the next step will overwrite this imagery. As each image is drawn (or after they've all been drawn), the counters which keep track of the current image for each object are updated. In some games, all of this happens during the vertical blanking period. This is not true for Lemmings, as I'll explain in a bit. - Next, the appropriate section of the background is copied into whichever buffer area is not visible currently. This overwrites whatever was in that buffer before. You can do some optimization here, to avoid copying over a bunch of stuff which is unchanged, but each bit of optimization carries a penalty in code size and speed, so you've got to be careful. - For every lemming, go through a loop which determines, first, if it is active or not. If it's an active lemming, actually running around on the screen or whatever, then check to see where it will end up with after it moves. This can get a bit complex, and depends a lot on just what kind of lemming you're dealing with. Blockers never move, for example, so they're easy, whereas miners are more complicated, since you have to check to ensure that they're actually going to dig something, check to see if what they're going to dig is metal, change them to walkers if they can't dig, or update their positions if they can. Like I said, it gets a bit complex. - Once the lemmings' position has been calculated, draw it into the buffer, using the appropriate image to get the animation. Have you noticed, by the way, that all of the lemmings seem to walk "in step"? It would seem that instead of a counter for each individual lemming, they may have used one or two counters for all of the lemmings. Just a theory. Anyway, when drawing the lemmings, don't bother to draw the ones that won't be visible this frame - that would be a severe waste of time. Only draw the ones whose positions place them within the buffer (which is a window onto the entire width of the background). This drawing can be done either after each individual lemming's location has been calculated, or all at once after all the locations are known. - For each action which affects the background (diggers, builders, bombers exploding, or anything else which causes the background to permanently change), make the changes in the appropriate spots in the background buffer, so they'll show up from then on. - Update the map display in the lower right corner to reflect the new position of the lemmings and state of the background. - Change the copper list to cause the buffer that you've just drawn into will become the visible buffer after the next vertical blanking period. There are some other tasks to take care of each time through, as well - you need to check the mouse position, move the cursor, update all of the displays to reflect that, update the score and "lemmings out" display, update the square cursor on the lower right-hand map, count down the time, update its display, take care of the music sequencing, and probably a few more things I've forgotten. A lot of this type of thing is best done in a vertical blanking period routine, since it doesn't take very long to do, and doing it every VBlank makes the interface look and feel a lot smoother. Whether it's in a VBlank or not, though, that's all you need to do. I'm not saying it's necessarily all _easy_ to do, but the list of tasks isn't all that long. So, let's look at this from the two criteria we started out with. First, the matter of code size. I don't actually _know_ how big the Lemmings code is, but I would be extremely surprised if all of the above routines took up more than 48K or so. That estimate comes from the fact that I designed a game about seven years ago which was of a similar level of complexity - it was a dungeon type game with 128 levels, twenty or thirty different monsters, each with its own movement patterns, sixteen different spells, each of which had different effects when activated, and a lot of other bits of magic, weaponry, armor, doors, secret doors, traps, and on and on and on. The memory price for this game, _including_ all of the graphic data and tables, was 16K total. All in 6502 assembler, of course, but then, I would expect Lemmings to have been coded in assembler anyhow, for the most part. At least, that's the way I would have done it - 80K isn't hay, but it isn't a lot of memory for your average C program, either. Add in the extra code needed to take care of the between-levels displays and the opening "one player, two player" selection screen, and I still have a hard time imagining Lemmings taking more than 80K, total, for code space.