Wednesday, January 28, 2009

Silver Plated Engine

Nope, the computer is still down. But I have figured out a new engine component that will make the game that much better (see the transitional animation hack post below). The new background artist asked about putting animated bits into the background of the levels, and I told him, "Sure, pretty much if it's animated, I can put it in." The thinking at the time was that I would end up scripting all of that. I've found I have a staggering distaste for that now. I mean, it should be an engine side feature with ThiefEd support.
The main issue was creating a dynamic system that would keep up with all of the things that I may or may not want to to throw at it. I mean, I could create 5 discreet "candle" objects (for example) but what happens if I need 7? Or I only ever use 3? So a dynamically created table would be the way to go.
Since I've already tried streaming the enemies, I've found I don't much care for that. It slows stuff down quite a bit when the pages change. To combat that and have different assets for different stages I think that loading a stage's "objects" at the beginning of the stage into memory is the way to start, then I can just reference the objects as I need them. So each stage will have a directory of objects. This is the static part that I need so I can build the dynamically generated part of the system (instead of all dynamic all the time - which is crazy hard to debug and test).
So, in the ThiefEd Editor the objects will have a number and an x and y position. So Stage 2's object #1 may be a tomb or bats or something like that, but Stage 3's may be flags or seagulls or whatnot. So these will be the bits that need to be saved into level information file.
First though, before the object information is saved, ThiefEd will keep a count of the number of objects in a particular screen. This number (let's call it the Key) will be saved first so as to remain at a constant, identifiable, space in the save information. The rest of the objects can be saved in whatever order they happen to be in. With objects placed later being in the "Front."

Right then, when the engine loads a level it will load all of the level stuff that it does now (the collision detection boxes) and then load the Key. Using this Key it will create an array that has a number of rows equal to the Key. So if the Key is 7 (meaning that there are 7 objects in the level) an array with 7 rows will be made. This array will then have 4 columns. The first column will have the object type (a candle, torch, crow's nest), the second the X and the third the Y. The last column will be used for animation and offsets.
When the screen is drawn, the Engine will use a loop to run through this array. It will draw item #(information in column #1) and x position (column #2) and y position (column #3) and frame (column #4). Then it will update column #4 to the next animation frame so it plays a different animation the next time, or in the case of parralax effects it will offset them more or reset them.

It will do this every time the screen is drawn and it should go fast. When the level changes, the array will be deleted and a new array created. So memory leaks shouldn't be an issue. This all seems quite doable, but it will need a lot of building before anything works. At least, if I'm correct, this shouldn't invalidate all of my current level information. I'll just need to keep ThiefEd from looking at the Key information, but save it anyway. So when levels without it are loaded, it won't crash because they don't have it, but it will save a Key in them. Then I can require the Key in the Engine. Shouldn't take more than a few minutes to update that. So I'm happy with that. Of course, designing it in my head and getting the code to dance like a monkey on LSD to its particular beat are different matters entirely. Swearing incoming.

- Level? Stage? What am I talking about? When I started Thief I thought the individual screens would be the entire level. So I referred to them that way in the code and I refer to them that way now. I know that it is confusing and I know that it's incorrect, but that's just how I call it now. So when I refer to a level (especially in terms of system or engine stuff) I really mean a single screen. When you run off the edge of the screen, it takes you to the next level.
So what do I mean by Stage? A "Stage" is a collection of Levels. Stages are saved in the system as 144 discreet levels and in game terms (will) have their own set of objects. The Super Mario naming conventions would call my Stages "Worlds."

- Chapter? Stages are generally broken up into Chapters too. These are just switches in the gameplay style and backgrounds within a Stage. They really have no impact on anything other than being story based and having a music change. They are not in the engine proper. Of course, while playing the game people will probably consider the Chapters to be the base unit of gamplay (as opposed to Levels or Stages). For example, Stage 1 has 2 Chapters. The first takes place in the Prison section and the second in the Warehouse. These Chapters are numbered too, so when somebody says, "I'm in the second level," they'll probably be saying that they are in the Warehouse section, not the second screen. So, yeah, that's a little confusing, but that's how it works.

- Yep, super technical post. But I find if I write it down it helps me build it later and organize my thoughts.

No comments: