Sunday, September 26, 2004

Sunday 26th

Started doing some tidying up today, mainly because I know I've been somewhat sloppy and slapdash in some respects. The first job was to bring the toolbar up to date; first I added proper Tooltips for each item, then I tied in each button to it's particular function (and inserted "blank" code where this is yet to be done). I also jotted a few notes regarding other tools I could add to the Toolbar - this is all dependant on space, however, and as I'm rapidly running out of room for extra buttons, any obscure features will have to make do with just a menu entry.

Speaking of menus, I also started jotting down a few notes on the Menu structure, what menus I'll need, which functions will be included, and precisely what will go where. There are a few unofficial conventions when it comes to menu layout, and most of the map editors I've looked at seem to conform to these (which makes it easier to find what you need). I'll probably leave the actual implementation towards the end, however, as I can envisage me spending a lot of time moving things around unnecessarily as features are finished and tweaked.

Next I set about finishing and tidying up the routine to choose the current Layer by using the Tabber rather than pressing a key (though both will be possible), as well as the checkbox functionality. Thanks to a combination of tired eyes and temporary code from the last session, an intermittent crash bug crept in, as did a strange quirk associated with the checkboxes. I must be thinking more methodically, as these bugs only took a couple of minutes to track down and fix. Ok, so maybe a little luck helped, too. I'm not complaining :)

* * *

I've decided that the Editor will support one Map (or Project) at a time, each Map consisting of six different Layers corresponding to FX, Foreground, Foreground Collision, Background, Background Collision, and a Static backdrop. Thus, each level from the game will have its own associated Map/Project file.

Tilesets are created and then "linked" to a Map/Layer by specifying the tileset path in the Map properties; this allows multiple Map/Projects to share tilesets, if necessary, and also has the advantage that tilesets can be tweaked externally without having to re-export the data (this wouldn't be possible if the tileset data was embedded.

Within the Editor, Map/Project files can be loaded and saved, individual Layers saved/loaded/exported, and Brushes saved/loaded at will. This gives the user maximum flexibility to shunt Maps, Layers, and Brushes around as required. Of course, I have yet to write these routines, but you get the idea :)

There are a couple of reasons for this single Map/Project approach, the primary one being time; I could waste months putting together an editor which (I hope) would be completely flexible for any type of project - but therein lies the problem, that of providing support, maintenance, and updates, something which I simply don't have time for.

With this in mind, the Editor will be crafted to suit Citadel's requirements, but remain flexible enough for me to adapt it to other projects in the future. Another reason for keeping the Editor under wraps is, to put it bluntly, the sheer number of awkward quirks and bugs that are present, through no fault of my own (Blitz only permits a certain amount of interaction with Windows - and I don't have time to write DLLs to combat this often limited functionality).

Just before winding down, I took the liberty of expanding the Editor's window size; I want the editor to be able to support tiles which are 32, 64, or 128 pixels square (after all, I've yet to decide on the optimum tile size for Citadel), so the Editor window was tweaked so that tiles of these sizes fit comfortably within the window. And of course, since all my variables are self-calculating, everything works perfectly after changing just a single value.

Tuesday, September 21, 2004

Tuesday 21st

Tonight's session saw the start of the "cleaning up" process associated with multiple maps; up until now, I've been dealing with one map and thus, one set of variables. The addition of more maps means the creation of arrays to house what were once single variables (such as map width and height, current tileset, etc.). To compliment these changes, I also need to include small initialisation routines to change certain variables whenever maps are swapped. Not exactly the most riveting task in the world, but a pretty essential one.

After a little more tinkering, I had most of the basic arrays and initialisation routines done; this then led on to a little playing around with check boxes to control a layer's visibility (if you remember, each map will be made up of several layers). This involved changing the map drawing routine to display all layers overlaid, which works quite nicely.

Once I link the tabber controls into the map selection routine, the user will be able to click the tabber to select a layer (and thus, all editing takes place on that layer), while the check boxes will control which layers they can actually see. Of course, it's perfectly possible to turn off the current layer but still make changes (potentially hazardous, but then, PhotoShop has been getting away with that for years, so why can't I?).

Sunday, September 19, 2004

Sunday 19th

Kicked off the session by tackling the Flood Fill routine; I'd started converting this routine on Friday (to work with the Data Bank instead of the old array), but a few ugly bugs reared their heads. After stepping through everything methodically, it all boiled down to just a couple of mis-typed characters. Grrr!

After this came the less than enviable task of applying similar changes to the rest of the drawing routines (exchange tiles, grab Brush, plot Brush, and insert/delete Column/Row). The Brush routines in particular were a nightmare to write, let alone change and debug, so there was plenty of head-scratching and more than a little cursing before everything was working properly.

In addition, there were a number of behind-the-scenes routines (such as the tile occurrence counter, saving routines, and map initialisation) that also needed to be tweaked. So after several hours work, everything looks exactly the same as it did before! Ho-hum.

Once that arduous task was out of the way, I decided to test my luck, dive in, and implement multiple maps. Thankfully, all of the hard work and preparation had paid off, and after adding a couple of lines of code and doing a quick search & replace, the Editor can now handle multiple maps. Happy Bunny mode engaged. :)

Friday, September 17, 2004

Friday 17th

A welcome return to the land of code saw the start of a major overhaul to the way the Editor stores and manipulates maps. I'd been giving this a lot of thought recently (even when I'm not updating the Blog or programming, I'm still musing over ideas!), and concluded that using Data Banks is the easiest way of storing and manipulating the data.

Why? Well, as previously discussed, it's very difficult to store an array of arrays - every array has to be the same size, and if you redefine one array (for instance, if the user resized the map), you'd lose ALL of the data. However, arrays are useful because they allow you to refer to something - be it a map or list of data - using an offset, making it extremely easy to code routines which work with data chunks of variable size.

However, the system is a nightmare to rewrite for a few reasons; you have a routine which defines the map, one that prints it to the screen, and then the tool routines which allow you to draw to the map. An error in any one of those routines would spell trouble - but how would you know if your line drawing code was at fault, or the routine that displayed the data?

After diving in at the deep end and tweaking several routines, I decided to step through methodically and try them one at a time. Firstly, I adapted the Load routine so I could import an existing map; this allowed me to tweak the map display routine to get it working (after all, I knew what the loaded map was supposed to look like - any errors would therefore be down to the display routine).

Once this was working, I tweaked the control and map initialisation routines, as there was a nasty bug associated with Bank sizes (in fact, precisely the same problem I had on Friday 3rd September - perhaps I should start reading my own Blog!). After about an hour's intense coding, I finally had everything working properly, and set about tweaking the various drawing tools.

Pen Mode was straightforward enough, but Line Mode caused a couple of panic attacks; the numbers used by the routine are floating point, whereas the Data Bank deals with integers - and plotting Floats into an Integer bank causes somewhat unexpected results. After delving into the docs, I found a command that converts Float to Int which worked beautifully.

Although the session started with more than a little dread, I was quite pleased with how things progressed. I also developed my knowledge of Data Banks a little more, and in the process devised a neat way of implementing an Undo feature. Splendid.

Saturday, September 4, 2004

Saturday 4th

Got off to a good start this afternoon, and managed to get the Brush store/get functions working properly (as opposed to using test buffers and variables). You can now hold Shift and tap a number key to store the current Brush in that buffer, and then press the number at any point to recall the Brush. An appropriate message is also displayed in the Status Bar at the bottom of the screen.

I also added in some extra code to check if a defined Brush is actually stored in a buffer, to prevent the user from recalling erroneous data (error handling is an important aspect of coding, and is often overlooked). The final task remaining is to save the Brush data to disk with the current project - I'll tackle this with the rest of the I/O functionality, so for the moment I made some notes as to which variables and data require storage and intialisation.

Next, thoughts turned to the Maps and ostensibly, how I'm going to implement multiple maps. I looked through a lot of example code, and many people seem to favour the use of Types (a type is essentially an "object" which can contain a chunk of variable data - for instance, an alien name, its X and Y position, etc. - and these objects can be tweaked, modified, and manipulated in batches using some pretty simple yet powerful commands).

I'm content at the moment to keep my maps stored as arrays, as the actual data, even for a big map, is still relatively small. The problem remains, however, how do I organise the data so that I can access any map using just the one routine? Hmmm.

Friday, September 3, 2004

Friday 3rd

No work tonight (grin), so I tucked straight into Mask mode once again; started off by tidying up the Tabbers which display the Tiles and the Mask - tiles are displayed as normal in the Tile tabber, and you now click on the Mask tabber to display the Tiles with Mask information overlaid. This was also combined with a key to turn the Mask on and off, which makes it much easier to use.

Next I set to work on integrating the Mask into the various drawing tools (Pen, Line, Box, Box Fill, Box Continuous, and Brush mode). Again this was relatively straightforward, and I finished up by adding a small function which will invert the current mask on the press of a key.

The next task was something of a biggie, a task I'd been pushing to the back for quite some time; I could have tackled another small job, but my brain was itching to get started on the dreaded Brush library. As mentioned in previous instalments, once you've grabbed a brush from the current map, you can "store" this in a Brush library and bring it back with the prod of a key (this library is saved as part of the current project). Well, that's the plan anyway.

As each Brush is an array, and I need an array of Brushes, the situation calls for an array of arrays; this is possible in Blitz only if the arrays are all the same size, and has the downside that when one array is resized, all the arrays are wiped. The solution, therefore, is to use a DataBank, which is more or less a "home made" array, is dynamic, and slightly more flexible.

After delving in at the deep end, I wrote a routine to firstly save the current brush to a DataBank, and then retrieve it. The save code seemed to work, but the load code continually crashed the program. After over an hour of trying different combinations and permutations, I tracked the problem down to a single variable that needed to be declared as "Global". Frustrating, but I'm glad I had the perseverance to, well, persevere. :)

Once the basics were working, I added the code to dynamically store brush dimensions in the DataBank too (until now I'd been using Brushes of a fixed size), but this kept resulting in an intermittent crash. "A memory leak!" I hear you cry.

In actual fact, the DataBank wasn't big enough - usually, you can define a properly-sized array by multiplying two variables together; with DataBanks, you have to add 1 to the variables, otherwise you're DataBank is too small. Not particularly consistent (excuse me while I have another grumble about the Blitz documentation!), but it was good not to end the day with more bugs on my list.

Thursday, September 2, 2004

Thursday 2nd

Again, limited time to get anything done tonight, but I decided to plough ahead anyway and tackle the Mask mode (if you recall, the Mask mode is similar to Deluxe Paint stencils, allowing you to "lock" tiles to prevent them being drawn over).

I'd already created the necessary cursor graphics a couple of days ago, so I started off by displaying the current tileset, overlaid with the mask information (essentially, you left-click a tile you want to add to the mask, and right-click to remove it - tiles affected by the mask are highlighted by a special "X" shaped cursor).

This was fairly painless to implement, and so I delved into the Pen mode function and added the code to make the Mask actually take effect. Despite the code only taking a matter of 10 minutes to add, the tool is both amazingly powerful and immensely useful. Time was my enemy (I hate having to cut my code time short, particularly when I'm on a roll), so tomorrow's first task is to apply the mask to all of the other drawing tools.

Wednesday, September 1, 2004

Wednesday 1st

A new month, so my first task of the day was to archive the old diary and tweak the website (you can access August's entries by following the Archive link over there on the left). Hard to think that a few short weeks ago I was sitting around glumly looking for a programming language - and now, here I am elbow-deep in a Map Editor. :)

Again, limited time to do anything today, so I took the liberty of investigating a few bugs that had cropped up. One of these centred around the Mini-Map which, if you recall, was playing up when map sizes were changed. Tracked this down to a miscalculated value, and now the Mini-Map happily works with any size of map.