Search code examples
graphics6502commodore

How do I retain proper background on a character-based graphics system?


I got feeling retro and decided to write my favorite 8-bit computer game (Williams' Defender) on my first computer (Commodore PET 4032). All the code is being done in 6502 Assembly language. For those not familiar with the PET, all the graphics are character-based and to build games you move different characters around a 40 column x 25-row screen. This is very old tech - there are no sprites, no graphics layers, no ability to AND at the screen level, etc that we would be used to today.

I want the game to have multiple "laser beams" to be fired at the same time, and those laser beams might go on top of one another as they traverse the screen. Right now, as the beams move along the screen they store in memory what was underneath themselves and then replace what was underneath themselves as they move along to restore the background to its original state. The problem comes when a second laser goes on top of the first .. the first moves along and replaces the original background rather than leaving the second laser on top, then that second laser moves along and leaves artifacts of the first behind.

Is there a classic "light" algorithm or rule-set that allows multiple objects to move across one another such that the original proper things underneath are retained? I've tried different approaches (swapping backgrounds as things traverse, etc) but nothing seems to give me the correct result that I want.


Solution

  • It's certain an option to have each sprite keep a copy of whatever it overwrote, and have them erase themselves in the opposite order to that in which you drew them. That can't fail, but it assumes you have time for a full sprite draw and erase each frame.

    You can also use a screen-sized buffer of 'is background' and 'is sprite' flags. Each time a sprite is drawn, mark its character locations as 'is sprite'. To erase all sprites iterate through the screen-sized buffer repainting the background anywhere that isn't marked 'is background'. You can keep upper and lower bounds of updated positions if iterating the whole 2000 potential slots is too great a cost.

    You can also compare the differences between two such buffers to reduce flicker substantially supposing you have only one video buffer: paint the new sprites first, wherever they should go, noting them in the new buffer. Once all sprites are drawn, fill in background anywhere that the new buffer isn't marked 'is sprite' but the old is.