Advertisement

Object persistency in a limited-resource situation

Started by February 04, 2013 09:20 PM
4 comments, last by AgentC 11 years, 11 months ago

Hi,

I'm working on a Commodore64 side-scrolling action adventure, in which there's a continuous big world to explore, divided in several maps, let's say about 20 of 50 screens each. There are two categories of objects (enemies, items) found in the world:

1) Placed in the level editor. For example a turret on a wall or a pistol in a weapon closet. For each of these, 1 bit tells whether it still exists, or has been destroyed or collected by the player. I estimate there'll be about 2000 of these in the game total, so it's 2000 bits of storage in the save state.

2) Created during gameplay. For example randomly spawning enemies, and weapons/ammunition dropped by defeated enemies. These can be persisted only until as long as the player is in the same map, as the full position and type information needs to be stored, and are not part of the save state. Dying and restarting from the latest save also counts as a map change, therefore losing these kinds of objects.

To avoid unnecessary disk IO and allow for the player to quickly restart the latest save is always in memory, so the whole persistent game state is stored twice in the C64's limited memory. Using more memory for the save state (to allow persisting the "created-during-gameplay" objects fully from the whole world) is not really feasible.

Now, the question: do you feel it would actually be better and more consistent to never even attempt to persist the created objects for the duration of being in the same map, but rather teach the player that whenever something dropped by an enemy scrolls off the screen, it's gone? I estimate that this will not present a resource problem to the player, as there will always be spawning enemies from which more resources can be collected.

Some context is required here. smile.png

Do you mean you're doing a game "after the fashion of" C64 games? Or do you literally mean you are developing a game for an emulator or even real, still functional hardware? You might find a hobbyist board where people still enjoy throwing together software for those (very) old systems. Personally I've written veeeeerrry rudimentary programs for C64 in their platform's built in BASIC interpreter (when I was a 'spring chicken') but my memories of specifics are nigh useless.

What "level editor" are you using?

You are asking for ways to mitigate the technical limitations of the Commodore 64 which are significant. The first bit of advice you'll see from probably everybody is this: don't make games for the Commodore 64. Unless you really enjoy wrestling with those technical limitations, which can be it's own kind of fun.

What you might do is this: instead of using two copies of the entire map (doubling the amount of memory you require for a map) you could instead limit the number of items that can be on the screen to some small number and keep each in an array, which in C64-ville you may have to manually manage yourself, but the code to do that will still be less than 2 kb. If you're picky and careful, anyway. You can see some methods by looking into how to manually manage arrays in C. The mechanics are similar, assuming my memories are correct and you can address memory on the C64; you don't have "Protected" memory but your game has nigh exclusive control so you just need to watch out for yourself.

Anyway, restrict it to maybe 10-20 items on the map in a FILO manually managed queue where each entry keeps track of coordinates and item code and maybe item code 0 is "I am not a valid item" for a safety net. ("Manually managed" means your code manages it, of course.)

I hope this is helpful.

Advertisement
I mean actual Commodore64 game development in 6510 assembly language. And yes, I use both emulators and real hardware to test. And I have completed several large-ish games for it already :) The level editor is selfwritten, slightly customized for each project, but resembles the editors in the classic "Shoot'Em Up Construction Kit" in general functionality.

Anyway, thanks for the input. Yes, one idea that occurred to me soon after writing the post would be to allow a small number of the latest "created objects" to be stored, irrespective of on what map they are (storing the map number naturally requires one extra byte per object) That would make it so that if the player was to backtrack a bit, or even cross map boundaries, he'd still see the latest objects remain, but those further away would be "overwritten" by the newer.

...he'd still see the latest objects remain, but those further away would be "overwritten" by the newer.

I've seen this very thing happen in so many early games (more recent items endure, old ones expire) that I think it's a very good way to go. Another (even more frequent) idea is to have dropped items expire after a really short cool down (either actual time or whatever). They land, they blink for five to ten seconds, they vanish.

Play Ninja Gaiden I and II, it has enemies which always spawn when screen enters certain area, and despawn when it leaves the screen. You can see how such behavior actually affects gameplay.

Yeah, the NES is much more brutal than Commodore 64, as it has 2 KB RAM (if the cartridge has no extra) into which you have to store everything dynamic, therefore necessitating fetching almost everything directly from the ROM. It's a whole play mechanic of its own trying to get some flying enemy spawned at a convenient time by scrolling the screen just right smile.png

Anyway, I implemented the system roughly like in my post before, seems to work fine, it now has three levels of storage:

- Objects currently on screen. This is a small amount, currently 6 enemies + 5 items, can be tuned as necessary. The limiting factor here is not actually memory, but CPU time consumption (C64 has 1MHz clock speed.)
- Pool of fully stored (position/type/other data) offscreen objects. Currently max.96, which is also fairly arbitrary and can be changed. Both the pre-placed and runtime-created objects are stored here, but runtime-created ones may be overwritten if necessary.
- The bit storage for the pre-placed objects in the whole gameworld. On map change time, relevant objects are created into the offscreen pool from here, using static data from disk for their positions & types. This static data needs to exist only during the map loading and can be overwritten with other runtime data immediately afterward.

The last two are now part of the save state. This means the memory use of the save state grew, which is somewhat uncomfortable, but the benefit in the gameworld making more sense to the player, as objects don't arbitrarily disappear, should outweight it.

This topic is closed to new replies.

Advertisement