Game Development: Playing to Strength
Posted by Rampant Coyote on March 7, 2013
When I first started programming the Commodore 64, I was coming to grasp with a more complete version of the BASIC language. And, slowly, coming to grips with the limitations of the C-64. While in comparison to my previous computer (a Sinclair ZX80) it was overwhelmingly powerful, writing action games in BASIC would bring you very quickly to some of those limitations.
For those who don’t know, BASIC (at least as traditionally implemented) is an interpreted language. This means that there’s a language interpreter parsing your code while it runs. This means that every step of the way, there’s a complex program trying to understand what your code wants it to do, and then executing. By comparison, most applications you run today are compiled languages, which means that you run a compiler on your code in advance which does all the interpretation into the machines’ own native language. So at run-time there’s not as much overhead.
So anyway – BASIC was slow. And I wasn’t quite to the point of teaching myself machine code (or Assembly, the much easier-to-use Next Best Thing). So I found myself writing games that took advantage of the strengths of the language (and the computer) rather than the weaknesses.
Probably the best example of this was printing and scrolling. On the C-64, moving a bunch of character-sized things around on the screen could get very slow. Putting a three-character block that looked something like this [=] on the screen involved six interpreted lines of code telling the machine what memory location to use and what value to put there (three for the shapes, three for the colors). If you were to move it, you’d have to include at least three more lines of interpreted code to erase the three pieces at their previous location.
Obviously, you didn’t want to move too many objects around on the screen like that. Even in machine code, there were limits. Now, for larger objects, there were some built-in hardware-controlled sprites – a total of eight that could be on-screen at a time – which could be combined with more static backgrounds to make a pretty decent game.
But when I hadn’t quite mastered sprites, there was another trick of the hardware and BASIC interpreter I took advantage of . I wrote a particular game multiple times (a little better each time) taking advantage of the strengths of the interpreter. For one thing, while moving an entire screen’s worth of character objects was a massive hit, there was (IIRC) some hardware performance shortcuts that made scrolling pretty fast. And while having the BASIC interpreter draw objects one at a time was really slow, the “PRINT” statement – designed to render lines of text – was pretty dang fast, with rapid machine-code handling of a chunk of data. Likewise, string manipulation – while not fast – was still faster doing it with built-in BASIC commands than trying to do it “by hand.”
So I wrote a car game. In the game, you controlled a car at the top of the screen. The road was actually created by a series of print statements which would print the road using a subset of a string (a line of text) like this:
" [=] [=]"
I’d use a keyword to eliminate some of the spaces at the front of the string, and just print it out. So I’d get a track like this:
[=] [=]
[=] [=]
[=] [=]
[=] [=]
[=] [=]
[=] [=]
[=] [=]
[=] [=]
[=] [=]
[=] [=]
[=] [=]
[=] [=]
[=] [=]
To make the entire screen scroll, I’d just print a new line at the bottom.
It made for pretty jerky movement, but it worked. Then the car could be moved by using the left or right arrows (or the joystick). As difficulties increased, I could use a different string that narrowed the road, or throw in the occasional variant string that had an obstacle in the middle of the road.
For collision detection, I just kept a couple of arrays of values that I’d rotate through to keep track of which road piece had been used, which would tell me what the left and right boundaries were (or if there was an obstacle). Since it was all blocky with integer-based movement, it was fast and easy.
It wasn’t a great game. And an arcade gamer would be really put off because it played “upside down”. But it worked pretty well, and was easy to write. Easy enough to write in a single afternoon, and to write multiple times (with various enhancements).
Why do I share this?
I think there are a few game development lessons to be derived from this example from now-ancient technology:
#1 – Start simple.
Especially when you are first learning a platform or just learning to write games, it’s a lot easier to learn with simple examples than being bogged down with industrial-strength crap. For one thing, it’s easier to figure out if the problem is in your (limited) code, or if it’s an issue with the platform. And you can get the basic stuff done quickly to move on to the more advanced topics. Like – in this example – with the basic “prototype” game so easy to code, I was able to focus on learning how to do sound effects or joystick control.
#2 – Play to the engine’s strengths, and take advantage of what you are given.
Here’s the thing: There’s no such thing as a “perfect” game engine or API. All of them come with limitations and trade-offs. While it’s easy to go off and scream, “design is law” and feel all heroic bending the engine to your will, it’s often far, far better to take advantage of the power of the engine and simply avoid playing to its weaknesses. With a few exceptions, those battles you choose to fight because they will definitely raise the awesome factor by a good three notches. Use the advantages of the game engine to your own advantage, even if it means modifying your game design to match.
#3 – There are many ways to skin a cat.
Pardon the expression, cat-lovers. But there are usually several different ways of accomplishing your goal in making a game, particularly if you can be flexible on details. If a particular approach or implementation seems pretty cumbersome given your tools, try to think outside the box and see if there’s any other way to accomplish something close enough. You may even find your “Plan B” approach is far better than your original!
And my favorite:
#4 – You don’t need to be an expert to start making games!
This was one of my very first (if not THE first) action-games I ever wrote. I didn’t know much about programming. But it was something really fun and motivating I could work on as I was learning, and I know of some indies out there who have done okay with commercial releases of their products that they learned-while-making. The bottom line is that you don’t need to complete any kind of degree or even a six-week course to get started.
I think these principles are just as applicable today on modern game systems as they were in 1983 on the C-64.
Filed Under: Game Development - Comments: 12 Comments to Read
OttoMoBiehl said,
I remember making a game like your car game on my TRS-80 CoCo back in 1984. It used the built in character graphics. I felt really impressed I could do that. I remember showing my mom and being a bit disappointed when she didn’t “get” the game and the work it took to make it.
I agree that you don’t need to be an expert and I would like to add that the sense of accomplishment of figuring out how to do something is actually very nice. For Example:
Another strength of the CoCo was the graphic commands and the ability to draw graphics to a “page” and then flip that page to the screen. Basically it was a back buffer. I wrote a simple game in the vein of the old vector based Star Wars game that was popular at the arcades back then. I used the
LINE
command to draw the graphics representing the four guns in each corner. Something like:10 LINE(0, 5)-(3, 10)
20 LINE -(5, 0): REM AUTOMATICALLY DRAWS FROM LAST POSITION.
I had a cross hair that moved around with the joystick that was also drawn via the
LINE
command. And when I hit the button lasers were drawn from each gun to the cross hair. My “Tie Fighters” were drawn with theLINE
command and theCIRCLE
command for the body. A simple collision detection done by seeing if the joystick button was pressed and if the cross hair was in the same X, Y position as the fighter told me if I had a hit or not. It wasn’t perfect but it was a fun little game to make and play. My brothers had fun playing it after I made it and that was pretty cool for me.The best part was it took me about three or four weeks to make and I had to save it to cassette because I didn’t have any floppy drives. Loading and saving to cassette tape makes one very nervous about your recovering your work.
Xenovore said,
Cassette tape! Ugh, that brings back memories, not good. I was so stoked to finally get a floppy drive! =)
Rampant Coyote said,
Oh, man, yeah. I don’t think I ever got a tape I made myself to load on the Sinclair. On the C-64 my success was a little higher (with their custom tape drive), but it was still always a pain.
The 1541 disk drive was far more reliable, but sadly wasn’t nearly the speed improvement that it should have been.
Xenovore said,
Yeah, the Commodore floppy drives were crap. Glad I didn’t have to deal with those. =)
McTeddy said,
Woohoo! I never had to worry about Tapes or floppys, one of the advantages of being young.
I actually consider my time programming in basic to be some of the most valuable experiences because of your above example. It’s limitations made me think out of the box for finding solutions rather than relying on brute force.
To this day, I find the problem solving skills equally important to my code. Sure… between my own experience and the internet I don’t need to be creative very often… but it’s still a useful skill.
OttoMoBiehl said,
Yeah, the tape was rough…especially trying to sync up where you needed to load the program from.
When I did eventually move up to a C64 the 1541 was soon to follow and the Epyx FastLoad cartridge soon after that. The 1541 was slow but I do look back at it’s familiar disk read/write sounds with a sense of nostalgia.
I was always sad that C64 BASIC v2 didn’t come with a robust set of draw commands like Apple and TRS80 BASIC did. I do remember figuring out how to clear the screen and draw a line in BASIC. It was slooooooooooow. I think I focused on learning ASM after that.
Now if I remember right the Sinclair ZX80 had about 1k of RAM. Don’t know what kind of CPU it had. I would think that moving up from 1k to the luxurious 64k of the C64 would have seemed like heaven. Kind of curious to what every body elses 8-bit computers where too. (if they had one.)
Rampant Coyote said,
Heh – you can probably figure out what the ZX80 had for a CPU… it had…. (wait for it) – the Z80 Microprocessor! Which can be had now for about $4. And yeah, 1K of RAM. Not enough room to store the screen picture, so it could only process what was supposed to be in the screen during idle cycles (which means when you pressed a button or did any calculations, the screen would blank out).
Anyway – yeah. Having something like 48K of *usable* RAM (the rest was storing BASIC, operating system stuff, screen memory map, etc.) was HUGE. And it was much faster. And in color. And the screen didn’t blank out when you pressed a button. But no, no built in graphics commands – it was all PEEKS and POKES for BASIC programmers. 🙂
By the time I finally got a decent assembler and taught myself how to really program in assembly, I was just about to the point of moving on, anyway. But I did write some pretty cool little assembly-language subroutines to speed up some operations, like rendering.
In some ways I miss those days, but not to the point of wanting to go back. I’m really, REALLY happier working with Unity now. 🙂 But it was kind of a wild-feeling era.
Xenovore said,
Amen! I’ve got fond memories from back then, but there’s no way I’d go back to it. =)
Adamantyr said,
Hah, I got you all beat… the TI-99/4a had one of the slowest worst BASICS ever made.
There were two reasons it was so slow:
1. It was DOUBLE-interpreted, first into a proprietary byte-code language called GPL, which was then ran through another interpreter to turn it into assembly code.
2. The only memory on the base console was the 16k of video memory and a 256 byte 16-bit RAM area called the scratchpad used by registers and system globals. The video memory was accessed through an 8-bit memory-mapped port, which effectively bottle-necked speed to a crawl.
For writing games, TI BASIC lacked sprites as well as routines to write text anywhere on screen. And absolutely no machine language available; TI engineers decided to block all that off from users to make it an “easy” BASIC.
On the Atari Age forums a few years ago, we had a “BASIC writing contest” to create the best game you could with just the original console. I actually won the contest with my entry “Aperture” a side-scrolling (with no scrolling) version of Portal.
http://tigameshelf.net/tibasic.htm
The real challenge I found was with logic statements. I had a long IF/THEN chain for detecting different characters, and I found that processing that single line slowed the game visibly. So I broke it down into individual IF/THEN statements with the most frequent being checked first. When your player is falling, I also routed to a separate routine to handle controls during that period. With optimizations like this, I was able to make the game work.
For storing the 16 different levels, I wrote up an run-length encoding system to store them in data statements. This let me store them as efficiently as possible and still not require off-loading to disk. (Which on a real TI consumes about 2k of RAM for the I/O)
In the end, I managed to cram it all into 16k of RAM, I only ended up having to cut an animated title screen. I did have to make a disk version, though, as nobody was interested in loading only from cassette, even in emulation.
OttoMoBiehl said,
@Jay
I did a quick Wikipedia lookup on the ol’ ZX80 and it did have the Z80. Wow! I was surprised to see it clocked at around 4MHz though. To bad they never gave you any RAM to play with as it would have been interesting to see what could have been done on that machine with, even, 16kBs of RAM. I read that the Z80 could be a spiritual cousin to the 8086 so I always wondered if assembly language programming on one would be the same too? (minus the awful memory offset scheme the 80286 and beyond have)
@Adamantyr
I had a friend who had a TI-99/4a. I only got to play with it a couple of times and it was in the beginning of my hobby of using 8-bit machines so I never had much to compare it against at the time. If I remember it correctly it had a space invader clone game built into the system ROM. I still have fond memories of playing around with that machine, a neighbors Apple IIc and my TRS-80 CoCo and it made me appreciate the diversity in machines back then. I would also be the first to admit that those old 8-bit machines all had personality…even the slow, low on memory ones.
I do remember that BASIC contest on Atari Age back then too. I didn’t realize it was you who wrote aperture. I was absolutely blown away when I first saw what you had done to implement the Portal clone. The way you stored the levels is brilliant. Congratulations! 🙂 I love when people do stuff like that on these old 8-bit machines, especially when they use BASIC.
Shawn Delahunty over at Armchair Arcade wrote a space invader clone in BASIC on his TRS80. That was pretty interesting to follow too!
http://www.armchairarcade.com/neo/node/4612
I don’t know why but it fascinating to watch people do stuff like that with these old machines.
Speaking of CPUs I think my favorite CPU from back in that era was the Motorola 6809. It was a lot like the 6502/6510 but it had the ability to do proper math among other things. To bad Commodore/Apple/Atari didn’t use that processor in their 8-bit machines.
OttoMoBiehl said,
@McTeddy
Out of curiosity what machine did you program BASIC on and what version of BASIC. I had some classes back in the college days on some old DOS machines and we used GWBASIC if I remember correctly. In high school we used Apple IIs to program in BASIC.
CdrJameson said,
Wow! I’m impressed that you had a Sinclair machine in the US.
I was ZX81 (Like the ZX80, but it goes up to 81!) which could be expanded to 16K and could optionally NOT blank the screen when you pressed a button. The old, screen blanking mode was still there, but in an early piece of marketing it was renamed ‘FAST’ mode.
Then onto the C64, with its somewhat restricted BASIC drawing functions. I remember passing around secret POKE addresses in the playground because they didn’t seem to be documented anywhere. Plenty kudos for knowing the value that changed the border colour.
Tapes all round for us, because you had to be made of gold with a gold wallet containing gold to afford one in the UK in the 1980s.
BTW, Commodore loading was so slow because they saved everything twice, and then checked that the copies matched. This system was clearly designed by someone with no idea what they’re doing, because this is both slower and LESS reliable than saving it once (if they’re different, which one is correct?)