At the start of the development of the Commodore 64 port of Vlambeer’s Super Crate Box –entitled Super Bread Box— I quickly realized that in order to keep the hectic gameplay of the original intact, the code needs to be highly optimized to prevent slowdown. These old platforms support a fixed screen-update frequency that is coupled to old CRT refresh-rates of 50/60Hz depending on which side of the Atlantic you are. This means that in order to keep everything flowing nice and smooth, screen updates should be coded at 50/60fps as well.
Contemporary games are mostly build in third party engines, which nicely separate low-level screen-update code from higher level game logic. At the same time modern platforms are also powerful enough to both update the internal game logic state and render the screen within the same clock update. This keeps everything nice and consistent. When developing games for vintage platforms you don’t have this luxury, and one has to optimize both game logic as well as render-code to keep the speed up.
Although Super Bread Box has a static background, the screen render code actually still has to do quite a lot of things. To support more than 8 sprites on screen a sprite-multiplexor was coded, which includes an optimized sorting algorithm. All the bullets and explosions are directly blitted into the background graphics, making use of a tile-based screenmode. All this means that there is only limited processing power available each frame to update the internal game logic.
The trick to keep everything (mostly) flowing at 50/60fps is to only update each frame those elements of the game logic that are really time critical. These are mostly related to updating the player state, since any lag is directly noticed in such a fast paced game. Most of the other game logic I tried to divide as evenly as possible over multiple screen refreshes. The best example of this is the collision detection between enemies and the background.
Single pixel accuracy
Normally you would do a bounding box check for each enemy each frame. However, by positioning each wall and platform at exactly 8 pixels intervals, and spawning each enemy with an individual (additional) delay, only one or two enemies need to perform their bounding box check each frame! Since the enemies still move with single pixel accuracy each frame, this doesn’t affect gameplay at all, but does reduce significantly the required processing power!
I couldn’t use the same trick for the bullet<>enemy collision detection, since bullets move much faster than enemies. A bullet could then potentially slip through if only a subset is checked each frame. However, instead of doing a bounding box check between each bullet and each enemy every frame, a two-step approach was used. First I only check if the background behind the enemy sprite contains a bullet. If true then I do a more elaborate check to also see what bullet to remove. Since the enemies are usually spread nicely around the level, this reduces the amount of checks significantly.
This shows that, although vintage platform have only a fraction of the processing power of modern platforms, one can still develop ports of high-speed action games as long as smart optimisations are performed.