Design Doc, GUI Refactoring, Rendering Issues

Published December 17, 2007
Advertisement
No screen shots today. Too bad.

Design Doc


My good friend, the doctor known as Brian, might help out with some art. I've know him for years and years so it's OK if I screw him over. It was at this point that I discovered that Brian could not, in fact, read my mind. For him to know what kind of art to make for the game I'd have to write down some kind of ... thorough description, "documentation", if you will, of the setting and gameplay. Madness.

So here's the current design manifesto. Read at your own peril, it's very much in progress.

Refactoring the GUI


I was iterating over all the buttons in a panel and checking if a mouseclick hit any of them in two different places. How ridiculously typical.

I've heavily revised all the workings of the GUI, Panel, and Panel Element classes. They're still a bit broken and I'm getting tired, so no screen shot of my new and improved ultra-slim GUI, but they're so beautiful and robust that I could make an interface out of a text file filled with noise. No, actually I seriously couldn't, but they're a lot better than they were.

Doing this brings up many new ideas that I should have in my GUI -- like what I'm thinking of calling a dynamicString class to put in place of regular strings in text elements or buttons that will update itself based on a call to some object somewhere else, for example a dynamicString could attach itself to a mouse position, then the mouse position would be displayed in real-time. Or something. The problem inherent in objects communicating with random other objects brings me to my next point...

Inter-object Communication


After discussing how Java's Swing handles buttons with Laura, I'm thinking of re-doing my relay class and adding a couple utility classes that can be used to set up connections between objects. Currently when a trigger is passed through the Relay it looks up the target by matching a string to a key in the Relay's dict. I thought, why does this need to be done every time? After the first successful 'connection' is made between trigger and target through the Relay, they could form a direct reference! (Of course some buttons will only ever be called once, like the 'quit' button, but for everything else I think this makes sense.)

The best part is, I don't have to intialize everything in a certain order like I think Java does. I just have to make sure that objects remove themselves from the Relay when they are deleted, which means I have to find out how the hell to add to built-in class functions -- I saw David O. do something in one of our Python/OpenGL projects where he had texture objects delete themselves from the OpenGL texture cache when they were themselves deleted; I just gotta do something like that.

Rendering


I've been having second thoughts to my rendering process.

I know that I've been hyping dirty rects for the past week and I do have my Video class set up to use them, I just have to figure out how to get everything that is rendered to pass their dirty rects back up to Video -- and how to do this only when necessary. It's a matter of planning, really.

And then I was thinking of how I render tiles: I currently render all the 'layers' in a tile from references to generic images as I iterate through, so like: blit Tile1 terrain, Tile1 terrainfringequads, Tile1 terraineffects, Tile1 isofeatures, Tile1 otherFX, shift over 128 pixels, blit Tile2 terrain, etc.

Could I not render every tiles bottom layer over the whole gamescreen, then every tiles next layer over the gamescreen, and so forth? Would this be much more costly? (A bit, probably.) Would I gain some kind of flexibility I wouldn't have otherwise? ... I recall an option in Civ where you'd tell it to show only underlying terrain. This may allow images to be drawn past the bounds of their tile without having (more) weird overlap artifacts.

And even further, I was talking to Laura about how I handle tiles, and she was saying why not render each tiles own little surface and store it in the tile (and only do this for currently visible tiles, of course), then call those on demand. This way I wouldn't have to re-render the whole stack of images every time -- I'd only have to re-render a stack of images in a tile where something changed. This would take more memory or something but may cut down on processing time -- I just have no idea if it'd be worth it.
I suppose I could implement all the different rendering methods and see empirically which has the best framerate, but that'd be a lot of work.

Does anyone know what's the best way to do this?
0 likes 4 comments

Comments

darkpegasus
- The document looks good so far; I'm interested to see some of the actual game mechanics
- Tired of GUIs yet?
- In Java you can register listeners (uh, they listen for stuff to happen) or pass an object by reference to a second object and then use the second one to call methods on the first one (and yes, it is as messy as it sounds)
- My elves are Drow, does that count?
December 17, 2007 10:22 PM
dcosborn
Is tile rendering slow right now? Since you're using PyGame and not OpenGL (right?), I like Laura's idea of caching a flattened surface for each tile. The extra memory cost would depend on the size of the map, but consider that many computers have 1+ GB of RAM. But I would only do this if you're actually finding it too slow.

There are two optimizations I can think of right now for this method. First, you might have a lot of tiles made up of same layers. If two tiles use exactly the same layers, with the same animation offset (if you have animation), they can also use the same flattened surface and you only have to render it once. This calls for a caching system that uses a key generated from the filenames of the layer graphics, perhaps a hash. I think a Python dict with a string key would be perfect, since dicts are hashed. Whether this is worth it depends on how slow it is to composite layers.

Second, you could composite your layers in a tree. Lets say your tile contains layers A, B, C, and D. Lets also say that layer C is animated, so it needs to get updated a few times per second. So composite every even layer with every odd layer: A+B=E and C+D=F. Store E and F in your flattened graphic cache. Then do the same thing again, compositing every odd layer with every even layer: E+F=G. Now whenever C gets updated to the next frame, you only have to regenerate F and G, which is only two compositing steps, compared to three for the naive implementation. The memory requirements will be much higher with this algorithm, but combined with the first optimization, it might not be so bad.
December 17, 2007 10:44 PM
Knarkles
I just have to say, I like your design even more in detailed form. I really hope your project doesn't fall flat on its face at some point and we'll see something playable, as soon as possible of course. :)
December 18, 2007 04:47 AM
dbaumgart
darkpegasus:
I know I was forgetting something -- game mechanics! I've seriously got to write about the practical stuff instead of waxing poetic about theory and setting all the time. It'd a holdover from art school, I tell you.

It's perverse, really, but I'm really enjoying making the GUI. It really isn't that difficult and it allows for some easy application of graphic design principles.
On some level I do want to be doing something "more fun", but this ... isn't that bad at all. I could get used to it. God help me.

No Drow allowed either! They're far too cool for my game, sorry. (And I wonder if the name "Drow" isn't copyrighted; everyone has "Dark Elves".) But then again IsoStrat should be very open to modding so anyone who really wants to can put in whatever they want.


dcosborn:
Tile rendering is, at the moment, quite good (I need to re-implement my FPS counter, of course) -- I found that only rendering on-demand rather than as-fast-as-possible made all the different. I expect it to be even better once I get dirty rects working.

Regarding your second optimization -- I never would have thought if that. ... that's a very interesting idea, actually.

I'll start logging framerate and see if I need to implement clever optimizations (or I could always do it way down the line when I've got nothing else to do, as if that'll ever happen).


Selkrank:
Thanks for the support! I too hope that my project doesn't fall flat and implode. I've had some rough patches in the last bit as the scale of the game boggles my mind, but I'm slogging through.
December 18, 2007 06:35 PM
You must log in to join the conversation.
Don't have a GameDev.net account? Sign up!
Advertisement