Started refining the control system a little, in order to emulate the C64 version of Citadel. The first task in hand was to adjust the control so that Monitor moves a set distance (i.e. one tile) when a direction is pushed. The tricky part is, what happens when Monitor is moving and another direction is pushed?
With this in mind, I booted up the emulator and started tinkering; a couple of problems were easy enough to fix (prioritising lateral movement over vertical movement, for instance), but then arose the question: what happens when the player holds the Left and Right or Up and Down keys at the same time?
You would expect, in such a situation, a simple answer - until you consider that the C64 version was joystick only; there was never the issue of two opposing directions being activated simultaneously. Fortunately, the emulator seems to have a rather nice way of prioritising its keypress logic, so all I have to do was emulate it in my code.
Friday, October 15, 2004
Sunday, October 10, 2004
Sunday 10th
Blimey! An update! Progress has been moderately slow this last week, mainly because of other commitments. Nevertheless, I've still been giving the game considerable thought at every opportunity.
Last weekend I visited the Binary Zone HQ, and spent a few enjoyable days with Kenz and his wife Natz. A bit of time was given over to the discussion of Citadel, and Kenz showed me a rather nice Paradroid remake called Freedroid (see links column).
I'd seen this when I was scouring the internet for Paradroid links, but hadn't actually downloaded or played it. However, it's a very nice remake with some nice touches and additions (particularly the ability to play the game in Classic mode). This highlighted what I consider to be the difference between Citadel and other remakes; what I'm basically trying to achieve is the 'next generation' of Citadel, rather than a strict port with extra effects. Though the game will retain some of the key elements that made the C64 version so good, there will be a myriad new features.
One of the most interesting aspects of Freedroid is its control system; the main character is controlled using the keyboard, while the mouse controls a cursor which is used to aim and fire bullets. What is interesting is that I was planning an identical system for Citadel (of course, the game will support joypad control too).
As is typical in the world of game creation, Freedroid stuck in my head for a number of days, and so - as a break from the Editor - I decided to tinker with the basic player controls. I'd normally shy away from game-specific code until the Editor was finished and the basic scrolling routines were in place, but the beauty of the control system is that it's modular, and thus, easy to rip out and insert into the game at a later date.
I already had a test-bed created, so I added the sprites for the player's ship Monitor, and included basic keyboard controls. Then I set about adding some basic bullet code, so the player could fire left and right depending on the lateral placement of the mouse pointer (all fairly basic routines just to get the variables set up and working properly).
And thus began the tricky part - how exactly does the player shoot a bullet in the precise direction of the mouse pointer? I knew there'd be some tricky maths involved (NOT my forte at all), so I took the liberty of popping on to IRC picking the brain of veteran coder Snakey. It turns out that, as suspected, I'll need to use the Sin and Cos functions (these allow you to calculate how far an object needs to move in the X and Y directions in order to travel along a given angle).
However, the issue remains, how do you calculate the angle between ship and mouse pointer? As it turns out, Blitz has a specific function for that very task; its name is ATAN2, and it does its job very nicely indeed. With this in mind, I expanded the basic bullet data structure to allow each bullet to have its own Angle and X/Y direction.
After a fair amount of research, head scratching, and examination of other people's code, I had the bullets working properly (all 80 of the blighters!), and Monitor can now move freely around the screen firing recklessly. As an extra touch, I added extra variables so that every bullet can have its own animation type.
So, after adding just a couple of routines - and learning a fair bit about maths in the process - the control system is already beginning to take shape; as a testament to how good the control already feels, I added a punchy sound effect when bullets are fired - before I knew it, I'd spent nigh-on 20 minutes racing around the screen flinging bullets everywhere! Excellent stuff!
Last weekend I visited the Binary Zone HQ, and spent a few enjoyable days with Kenz and his wife Natz. A bit of time was given over to the discussion of Citadel, and Kenz showed me a rather nice Paradroid remake called Freedroid (see links column).
I'd seen this when I was scouring the internet for Paradroid links, but hadn't actually downloaded or played it. However, it's a very nice remake with some nice touches and additions (particularly the ability to play the game in Classic mode). This highlighted what I consider to be the difference between Citadel and other remakes; what I'm basically trying to achieve is the 'next generation' of Citadel, rather than a strict port with extra effects. Though the game will retain some of the key elements that made the C64 version so good, there will be a myriad new features.
One of the most interesting aspects of Freedroid is its control system; the main character is controlled using the keyboard, while the mouse controls a cursor which is used to aim and fire bullets. What is interesting is that I was planning an identical system for Citadel (of course, the game will support joypad control too).
* * *
As is typical in the world of game creation, Freedroid stuck in my head for a number of days, and so - as a break from the Editor - I decided to tinker with the basic player controls. I'd normally shy away from game-specific code until the Editor was finished and the basic scrolling routines were in place, but the beauty of the control system is that it's modular, and thus, easy to rip out and insert into the game at a later date.
I already had a test-bed created, so I added the sprites for the player's ship Monitor, and included basic keyboard controls. Then I set about adding some basic bullet code, so the player could fire left and right depending on the lateral placement of the mouse pointer (all fairly basic routines just to get the variables set up and working properly).
And thus began the tricky part - how exactly does the player shoot a bullet in the precise direction of the mouse pointer? I knew there'd be some tricky maths involved (NOT my forte at all), so I took the liberty of popping on to IRC picking the brain of veteran coder Snakey. It turns out that, as suspected, I'll need to use the Sin and Cos functions (these allow you to calculate how far an object needs to move in the X and Y directions in order to travel along a given angle).
However, the issue remains, how do you calculate the angle between ship and mouse pointer? As it turns out, Blitz has a specific function for that very task; its name is ATAN2, and it does its job very nicely indeed. With this in mind, I expanded the basic bullet data structure to allow each bullet to have its own Angle and X/Y direction.
After a fair amount of research, head scratching, and examination of other people's code, I had the bullets working properly (all 80 of the blighters!), and Monitor can now move freely around the screen firing recklessly. As an extra touch, I added extra variables so that every bullet can have its own animation type.
So, after adding just a couple of routines - and learning a fair bit about maths in the process - the control system is already beginning to take shape; as a testament to how good the control already feels, I added a punchy sound effect when bullets are fired - before I knew it, I'd spent nigh-on 20 minutes racing around the screen flinging bullets everywhere! Excellent stuff!
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.
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?).
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. :)
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.
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.
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.
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.
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.
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.
Tuesday, August 31, 2004
Tuesday 31st
Back to work today, so there was limited time to get anything done. Kicked off by coding the Exchange routine - the user can now press a key to swap the currently selected Left and Right tiles; for instance, if you want to swap all occurrences of Tile 3 on the map with Tile 5, you left-click Tile 3, tight-click Tile 5, then hit "E". As with many of the functions I've added recently, it's a relatively simple routine but adds so much to the flexibility of the Editor.
Monday, August 30, 2004
Monday 30th
Not much coding activity for the better part of the day, mainly because my brain just wasn't in the mood. I weaned myself into things by tweaking the toolbar yet again, as well as grabbing a few more maps from the C64 version of Citadel (there's always stuff to be done - if I don't fancy coding, I can still tackle other things until I feel like crunching some bytes again). It's a funny old business, this programming lark.
Set to work later on, and finally got my tile cursors working properly (these appear in the Tiles window and highlight the tiles currently assigned to the Left and Right mouse buttons). I've no idea why this routine took so long - my brain simply refused to work. However, after tapping my head on my knee for a few moments - the programming equivalent of banging the TV to stop the picture rolling - I added a couple of lines of code and got the thing working. What was most puzzling, I couldn't understand why it worked!!! It took a further 10 minutes before things clicked into place. Biz-arre.
Undeterred, I cracked on and implemented Move mode, which, like the hand in PhotoShop, allows the user to scroll the map using just the mouse and left button. It actually works extremely well in practise (mainly because I prefer using the Hand to dreadful, satanic Scroll Bars), and it's now much easier to move around the map.
My main bugbear at the moment is swapping between canvases (these are the "graphic" areas of the screen onto which I print the Map, Mini-Map, and Tile window). Currently I use an event-based system to work out which canvas is being used when the user moves the mouse or presses a button, a system which also controls the gadget operations (Tabbers and Toolbars), and menu functions. Currently, however, all is not as it should be; there are noticeable delays when trying to close the Window, and occasionally the Tabbers refuse to work. Investigating the problem and finding a solution will be no small task - I think I'll reserve that for a day when my brain isn't so frazzled. :)
Set to work later on, and finally got my tile cursors working properly (these appear in the Tiles window and highlight the tiles currently assigned to the Left and Right mouse buttons). I've no idea why this routine took so long - my brain simply refused to work. However, after tapping my head on my knee for a few moments - the programming equivalent of banging the TV to stop the picture rolling - I added a couple of lines of code and got the thing working. What was most puzzling, I couldn't understand why it worked!!! It took a further 10 minutes before things clicked into place. Biz-arre.
Undeterred, I cracked on and implemented Move mode, which, like the hand in PhotoShop, allows the user to scroll the map using just the mouse and left button. It actually works extremely well in practise (mainly because I prefer using the Hand to dreadful, satanic Scroll Bars), and it's now much easier to move around the map.
My main bugbear at the moment is swapping between canvases (these are the "graphic" areas of the screen onto which I print the Map, Mini-Map, and Tile window). Currently I use an event-based system to work out which canvas is being used when the user moves the mouse or presses a button, a system which also controls the gadget operations (Tabbers and Toolbars), and menu functions. Currently, however, all is not as it should be; there are noticeable delays when trying to close the Window, and occasionally the Tabbers refuse to work. Investigating the problem and finding a solution will be no small task - I think I'll reserve that for a day when my brain isn't so frazzled. :)
Sunday, August 29, 2004
Sunday 29th
More research was the first thing on today's agenda, specifically, how to create arrays of arrays. After a little forum-based malarkey, I discovered that Blitz has a rather nifty "Bank" feature, which allows you to create small chunks of reserved data - much the same as an Array, but more flexible and accessible. I'm still undecided as to whether or not I should be using an Array of Types or Banks, though.
Toiled for a while trying to get the Brush rotate commands to work; after 10 minutes I realised there were a couple of parameters the wrong way round. Fired it up and it worked beautifully, except that I kept getting an error on exit (which usually points to memory being overwritten by a leaky array).
After a bit of subtle investigation I realised a temporary buffer I was using wasn't big enough (this ties into the fact that arrays are created using whole numbers starting at 1, while variables start at 0). A couple of key presses (and several sweary words) later, everything was working, and means that all the Brush-related tools are finished. All I have to include now is the facility to "save" a brush to one of 8 buffers, and load the brush back again.
Work continued slowly but consistently this evening; I added the controls to scroll the Tile window (and widened the window slightly in the process), ready for the cleanup of my Main Loop. I also Took the liberty of tweaking my test tileset to include numbers in all the blank / unused tiles (this helps with debugging, allowing me to see a little more clearly when things go wrong).
I then tweaked the Toolbar, removing the Insert / Delete Column / Row buttons (it's more intuitive to do this using keypresses as you need to keep the cursor in the correct spot on-screen - selecting the option from the Toolbar meant the cursor was never in the right position), as well as adding icons for the Brush rotation functions. I then coded a small routine which checks the map and reports the occurrences of each tile - this will be used in the Info panel at some point.
While tinkering with some of the drawing functions, I realised that it's annoying when certain tiles are accidentally drawn over (particularly as I've yet to code an Undo function). I thus hit upon the idea of having "masked" tiles - akin to the Stencil mode from Deluxe Paint - where the user can "lock" certain tiles to prevent them being drawn over. This mask is exclusive to a particular tileset, can be tweaked as required, and turned on and off at will. In theory. :)
The next big task was to tweak my Main Loop, something which I've been dreading, and something which could have a knock-on effect to many areas of the code. Thankfully, things went pretty smoothly, and I now have a slightly more organised program. Further tweaks are required, such as the calling of key functions, but these will be handled as I finish things off.
Whenever you create a program, such as an Editor, the abundance of extra features often tends to swamp the little "what ifs" that may not readily become apparent. I'd jotted down on my notepad something to do with variable map sizes - specifically, what happens if a map is smaller than the screen? Surely the drawing tools have to be tweaked? Thankfully, all it required was a small initialisation routine which changes a couple of universal values.
However, one thing became readily apparent: I now needed clipping routines for the Brush (which, if you recall, I removed from the code yesterday!). The actual Brush clipping was easy enough, but the outline which surrounds the brush was a little trickier, if only because I'd mis-labelled my code. There also remains the issue of fixing the Mini-Map, which doesn't seem to like maps smaller than the screen and throws a small wobbly, but as the system needs finishing anyway I can do this as I go along.
Toiled for a while trying to get the Brush rotate commands to work; after 10 minutes I realised there were a couple of parameters the wrong way round. Fired it up and it worked beautifully, except that I kept getting an error on exit (which usually points to memory being overwritten by a leaky array).
After a bit of subtle investigation I realised a temporary buffer I was using wasn't big enough (this ties into the fact that arrays are created using whole numbers starting at 1, while variables start at 0). A couple of key presses (and several sweary words) later, everything was working, and means that all the Brush-related tools are finished. All I have to include now is the facility to "save" a brush to one of 8 buffers, and load the brush back again.
* * *
Work continued slowly but consistently this evening; I added the controls to scroll the Tile window (and widened the window slightly in the process), ready for the cleanup of my Main Loop. I also Took the liberty of tweaking my test tileset to include numbers in all the blank / unused tiles (this helps with debugging, allowing me to see a little more clearly when things go wrong).
I then tweaked the Toolbar, removing the Insert / Delete Column / Row buttons (it's more intuitive to do this using keypresses as you need to keep the cursor in the correct spot on-screen - selecting the option from the Toolbar meant the cursor was never in the right position), as well as adding icons for the Brush rotation functions. I then coded a small routine which checks the map and reports the occurrences of each tile - this will be used in the Info panel at some point.
While tinkering with some of the drawing functions, I realised that it's annoying when certain tiles are accidentally drawn over (particularly as I've yet to code an Undo function). I thus hit upon the idea of having "masked" tiles - akin to the Stencil mode from Deluxe Paint - where the user can "lock" certain tiles to prevent them being drawn over. This mask is exclusive to a particular tileset, can be tweaked as required, and turned on and off at will. In theory. :)
The next big task was to tweak my Main Loop, something which I've been dreading, and something which could have a knock-on effect to many areas of the code. Thankfully, things went pretty smoothly, and I now have a slightly more organised program. Further tweaks are required, such as the calling of key functions, but these will be handled as I finish things off.
* * *
Whenever you create a program, such as an Editor, the abundance of extra features often tends to swamp the little "what ifs" that may not readily become apparent. I'd jotted down on my notepad something to do with variable map sizes - specifically, what happens if a map is smaller than the screen? Surely the drawing tools have to be tweaked? Thankfully, all it required was a small initialisation routine which changes a couple of universal values.
However, one thing became readily apparent: I now needed clipping routines for the Brush (which, if you recall, I removed from the code yesterday!). The actual Brush clipping was easy enough, but the outline which surrounds the brush was a little trickier, if only because I'd mis-labelled my code. There also remains the issue of fixing the Mini-Map, which doesn't seem to like maps smaller than the screen and throws a small wobbly, but as the system needs finishing anyway I can do this as I go along.
Saturday, August 28, 2004
Saturday 28th
A welcome return to the land of code today saw a few major changes (albeit behind the scenes). My first task was to get the Grid display functions finally sorted out. The user can basically display one of two different grids: the first grid is a basic affair, which can be changed to any size; the second grid is a Brush grid, and changes size according to the currently active Brush.
After a bit of head-scratching, I managed to merge the two grid display routines (modular programming is much cleaner and efficient), so the user can now view either grid, and choose whether or not the grid scrolls with the map or stays "locked" to the screen. I also added a Menu function which allows the user to change the grid size via a pop-up window, though this needs further tweaking.
I was all set to work on my snap-to-grid routines, before I had a flash of inspiration. Currently, the Brush is handled from the top-left, which is all well and good but limits where the user can actually place the Brush. The only graceful solution is to allow the user to change the Brush's handle point (if I recall, Deluxe Paint had a similar facility).
With this in mind, a further chunk of time was spent implementing a toggle so that the user can choose between top-left or bottom-right - I also had to tweak the display, plot, and clipping routines accordingly, but the end result was worth it (I just wish I'd thought of it at the beginning while the routine was still fresh in my mind!).
I also took the liberty of removing a couple of checks from the brush clipping routines; I discovered that Blitz automatically clips any images or geometry drawn to the screen, so my checks were basically redundant and unnecessary (the processing time is negligible but if the code is redundant, it shouldn't be there). The only checks I now perform are to ensure that the plotted Brush doesn't spill over the array boundaries and corrupt other areas of memory.
I did quite a bit of research into Types and Arrays, as I'm pretty sure some of the functionality I want to include will rely on Types of some form, particularly if I want to include multiple Brushes (I'm not quite sure if it's possible to have arrays of arrays).
In preparation for this, I changed my brush variables to array pointers, which entailed tweaking a couple of routines. It's always a bit scary making big "search & replace" changes to code, but after a couple of compile errors the thing fired up without a hitch. Phew!
I rounded off the night's session by implementing the Brush flipping - the user can now hit X or Y to flip the Brush along the respective axes, and I also threw in an extra line of code to flip the Brush through 180 degrees. I did attempt the Rotate Brush function, but with the time approaching 7am my brain wasn't up to much. Maybe tomorrow, as the Littlest Hobo once sang.
After a bit of head-scratching, I managed to merge the two grid display routines (modular programming is much cleaner and efficient), so the user can now view either grid, and choose whether or not the grid scrolls with the map or stays "locked" to the screen. I also added a Menu function which allows the user to change the grid size via a pop-up window, though this needs further tweaking.
I was all set to work on my snap-to-grid routines, before I had a flash of inspiration. Currently, the Brush is handled from the top-left, which is all well and good but limits where the user can actually place the Brush. The only graceful solution is to allow the user to change the Brush's handle point (if I recall, Deluxe Paint had a similar facility).
With this in mind, a further chunk of time was spent implementing a toggle so that the user can choose between top-left or bottom-right - I also had to tweak the display, plot, and clipping routines accordingly, but the end result was worth it (I just wish I'd thought of it at the beginning while the routine was still fresh in my mind!).
I also took the liberty of removing a couple of checks from the brush clipping routines; I discovered that Blitz automatically clips any images or geometry drawn to the screen, so my checks were basically redundant and unnecessary (the processing time is negligible but if the code is redundant, it shouldn't be there). The only checks I now perform are to ensure that the plotted Brush doesn't spill over the array boundaries and corrupt other areas of memory.
I did quite a bit of research into Types and Arrays, as I'm pretty sure some of the functionality I want to include will rely on Types of some form, particularly if I want to include multiple Brushes (I'm not quite sure if it's possible to have arrays of arrays).
In preparation for this, I changed my brush variables to array pointers, which entailed tweaking a couple of routines. It's always a bit scary making big "search & replace" changes to code, but after a couple of compile errors the thing fired up without a hitch. Phew!
I rounded off the night's session by implementing the Brush flipping - the user can now hit X or Y to flip the Brush along the respective axes, and I also threw in an extra line of code to flip the Brush through 180 degrees. I did attempt the Rotate Brush function, but with the time approaching 7am my brain wasn't up to much. Maybe tomorrow, as the Littlest Hobo once sang.
Wednesday, August 25, 2004
Wednesday 25th
No update yesterday, partly because - well, mostly because - I never did anything on the Editor (some days I'm itching to get at the keyboard, others I'm not. Ho-hum). I did take the time to do a little research on Pathfinding algorithms and Line of Sight calculations, both of which will play an important part in the actual game. It seems that the AI community really know how to research, and after visiting just a couple of sites I found I had all the links and articles I need.
Today was marginally more productive; I did a little tinkering around other people's code to find out the best way to flip or rotate arrays (presently I'm still trying to refine and polish my coding techniques). Not only did I find what I was after, I was also inspired to include a Mini-Map, which shows a teeny representation of the finished map. This allowed a few things to "click" in my head, least of all how I'm going to organise the information that appears at the bottom-right of the Editor (see the screenshot from last Saturday).
So inspired was I, the rest of my pre-work time was spent creating a new Tabber for this area, plus setting up the canvases and panels to display the information. After 30 minutes coding I had all the Tabs working - the user can now select Info (which will display co-ordinates and other relevant blurb), Mini-Map (which still needs some work but will operate like the Navigator panel in PhotoShop), and a Tools section (which will display information relevant to the current tool).
Today was marginally more productive; I did a little tinkering around other people's code to find out the best way to flip or rotate arrays (presently I'm still trying to refine and polish my coding techniques). Not only did I find what I was after, I was also inspired to include a Mini-Map, which shows a teeny representation of the finished map. This allowed a few things to "click" in my head, least of all how I'm going to organise the information that appears at the bottom-right of the Editor (see the screenshot from last Saturday).
So inspired was I, the rest of my pre-work time was spent creating a new Tabber for this area, plus setting up the canvases and panels to display the information. After 30 minutes coding I had all the Tabs working - the user can now select Info (which will display co-ordinates and other relevant blurb), Mini-Map (which still needs some work but will operate like the Navigator panel in PhotoShop), and a Tools section (which will display information relevant to the current tool).
Monday, August 23, 2004
Monday 23rd
Not much to report for today, as I was back at work (all of my Mondays seem a little thin on progress - must be the transition from relaxing weekend to the daily grind). Spent a bit of time looking at some code that was posted on the Blitz forum; I definitely need to restructure my Main loop and tweak a few routines (the editor started out as a hybrid of two other editors, and as a result some of the code isn't as clean as it could be).
I also organised my To-Do list a little better, with big and/or important stuff on the left, and smaller tasks on the right; this way, if I know I have limited time, I can code and debug one of the smaller ones rather than tackle a biggy and leave it half-finished. Just a small psychological trick so that I can always feel like I'm making progress. :)
I also organised my To-Do list a little better, with big and/or important stuff on the left, and smaller tasks on the right; this way, if I know I have limited time, I can code and debug one of the smaller ones rather than tackle a biggy and leave it half-finished. Just a small psychological trick so that I can always feel like I'm making progress. :)
Sunday, August 22, 2004
Sunday 22nd
Suffering from eye strain today (possibly the result of four days staring at code), so I wasn't really in the mood for programming problems. Inevitably, a niggly bug - the multiple canvas problem I mentioned yesterday - decided to eat away at the back of my brain for the best part of a day (and because my eyes were hurting, I couldn't tackle the problem head-on). Grrr.
Thankfully, after posting a few messages to the Blitz forums, and jiggling some code around, I finally managed to get the problem sorted out, and the Editor now happily refuses to process certain functions if the mouse isn't in the right place. This initial bout of joy was tempered with an intermittent bug (my favourite!), but a few extra checks soon sorted it out. Haha! Take that, puny bug. Ahem.
Flushed with this small morsel of success, I took to tidying up a few bits and pieces; the first task was to sort out the keyboard shortcuts for various functions. I then tweaked my Grid routine to adjust automatically to the current tile size, and also allowed the user to adjust the grid size (in multiples of the current tile size, of course). This will come in handy when combined with the Snap facility, which I spent a bit of time tinkering with to no avail (needs a little more thought).
I also added a Shift modifier to Brush Mode; currently, the entire Brush is pasted to the map, even if half of it is off-screen - after a couple of simple tweaks, holding Shift now clips the brush to the screen.
I'm always amazed by the way these projects grow, the inclusion of seemingly basic features inspiring further embellishments and modifications that in turn make the toolset more and more powerful; one minute I have a very simple Map Editor, the next I have a full-blown Windows application with dozens of tools. Blimey. :)
Though the transition to Windows hasn't been too painful, and despite my grumbles concerning the documentation and lack of tutorials, do owe a debt of gratitude to the Forum communities who have helped out along the way (the documentation might be lacking, but their willingness to help isn't). Plus, considering how far I've progressed in just a couple of weeks, I really shouldn't bewail my lot.
However, the fact remains that I'm itching to get started on the game, so once my current To-Do list has been completed and the Editor Load/Save/Export functions are sorted, and barring any tweaks that need to be made in light of game features that may present themselves, I shall be putting the Editor project to bed. I had hoped initially to produce an open-source editor which anyone could use or modify, but there remains the issue of support (which I'd have precious little time to do), and the fact that Blitz is fairly limited in some areas (so I'd never be able to produce precisely the tool I envisaged, merely one that gets the job done).
What's important here, I suppose, is that writing the Editor has taken me on a very steep learning curve but has introduced me to the vast majority of working practises, techniques, and language commands that I'll need to get the game up and running. Therefore, my advice to anyone wanting to write games in Blitz would be, write your Editor first. ;)
Thankfully, after posting a few messages to the Blitz forums, and jiggling some code around, I finally managed to get the problem sorted out, and the Editor now happily refuses to process certain functions if the mouse isn't in the right place. This initial bout of joy was tempered with an intermittent bug (my favourite!), but a few extra checks soon sorted it out. Haha! Take that, puny bug. Ahem.
Flushed with this small morsel of success, I took to tidying up a few bits and pieces; the first task was to sort out the keyboard shortcuts for various functions. I then tweaked my Grid routine to adjust automatically to the current tile size, and also allowed the user to adjust the grid size (in multiples of the current tile size, of course). This will come in handy when combined with the Snap facility, which I spent a bit of time tinkering with to no avail (needs a little more thought).
I also added a Shift modifier to Brush Mode; currently, the entire Brush is pasted to the map, even if half of it is off-screen - after a couple of simple tweaks, holding Shift now clips the brush to the screen.
* * *
I'm always amazed by the way these projects grow, the inclusion of seemingly basic features inspiring further embellishments and modifications that in turn make the toolset more and more powerful; one minute I have a very simple Map Editor, the next I have a full-blown Windows application with dozens of tools. Blimey. :)
Though the transition to Windows hasn't been too painful, and despite my grumbles concerning the documentation and lack of tutorials, do owe a debt of gratitude to the Forum communities who have helped out along the way (the documentation might be lacking, but their willingness to help isn't). Plus, considering how far I've progressed in just a couple of weeks, I really shouldn't bewail my lot.
However, the fact remains that I'm itching to get started on the game, so once my current To-Do list has been completed and the Editor Load/Save/Export functions are sorted, and barring any tweaks that need to be made in light of game features that may present themselves, I shall be putting the Editor project to bed. I had hoped initially to produce an open-source editor which anyone could use or modify, but there remains the issue of support (which I'd have precious little time to do), and the fact that Blitz is fairly limited in some areas (so I'd never be able to produce precisely the tool I envisaged, merely one that gets the job done).
What's important here, I suppose, is that writing the Editor has taken me on a very steep learning curve but has introduced me to the vast majority of working practises, techniques, and language commands that I'll need to get the game up and running. Therefore, my advice to anyone wanting to write games in Blitz would be, write your Editor first. ;)
Saturday, August 21, 2004
Saturday 21st
Started work on the Info window, and encountered a strange flickering effect on the text - eventually tracked this down to the fact that I was using the wrong command (CreateLabel, instead of UpdateGadgetText, for Blitz fans who are reading). I really wish someone would write a GUI tutorial for Blitz - GUI editors are all very well, but I need to understand how the code works without sifting through every command in the manual looking for variations on a theme.
After fiddling around for a while positioning the text and adding the variables, I started to wonder if the multiple windows system is the way to go; it's currently very easy to "lose" the Tile window, for instance, if you're multi-tasking with other applications. Having everything on one centralised window isn't the real problem - the tricky bit is creating a layout that a) won't inhibit future expansion of the Editor, and b) will suit the majority of user preferences.
Took a little time out this evening to update this diary in response to some feedback from the YakYak forum, the main task being to change the entry order and have the most recent one at the top (certainly makes life easier on the mouse wheel!). I also added links to the last 10 entries on the left hand side - all at no extra charge. :)
Back in Editor Land, I decided to dump the Tile and Info windows, and spent a while adding a new Tabber on the right of the screen to incorporate the Tile information and the Info underneath. It's all fairly rough at the moment, and there's still plenty of options and information I need to arrange on-screen, but I have a good starting-point.
As I'm now dealing with multiple canvases (one for the Map, one for the Tiles), a few bugs have crept in regarding tracking the Mouse in each area. I need to revise my main loop anyway, so I'll make a note of the bugs but deal with them when the main loop is revamped.
I also took the liberty of tying some more functions in to the Toolbar (this wasn't my plan, but I accidentally kept clicking the Line tool on Toolbar and shouting "D'oh!" when it didn't work). Again, the tool activation is tied in to my main loop, so a couple of niggly toolbar problems will have to stay until the loop issue is addressed.
To finish off, I spent a bit of time implementing a Brush Grid, which automatically resizes itself according to the current Brush size. I then added a function to scroll this whenever the Map is scrolled, and tomorrow I shall add some code to "snap" the Brush to the Grid. This will give the user maximum flexibility grid-wise; they can have a fixed or scrollable grid, with or without the Snap option. Splendid!
After fiddling around for a while positioning the text and adding the variables, I started to wonder if the multiple windows system is the way to go; it's currently very easy to "lose" the Tile window, for instance, if you're multi-tasking with other applications. Having everything on one centralised window isn't the real problem - the tricky bit is creating a layout that a) won't inhibit future expansion of the Editor, and b) will suit the majority of user preferences.
Took a little time out this evening to update this diary in response to some feedback from the YakYak forum, the main task being to change the entry order and have the most recent one at the top (certainly makes life easier on the mouse wheel!). I also added links to the last 10 entries on the left hand side - all at no extra charge. :)
* * *
Back in Editor Land, I decided to dump the Tile and Info windows, and spent a while adding a new Tabber on the right of the screen to incorporate the Tile information and the Info underneath. It's all fairly rough at the moment, and there's still plenty of options and information I need to arrange on-screen, but I have a good starting-point.
As I'm now dealing with multiple canvases (one for the Map, one for the Tiles), a few bugs have crept in regarding tracking the Mouse in each area. I need to revise my main loop anyway, so I'll make a note of the bugs but deal with them when the main loop is revamped.
I also took the liberty of tying some more functions in to the Toolbar (this wasn't my plan, but I accidentally kept clicking the Line tool on Toolbar and shouting "D'oh!" when it didn't work). Again, the tool activation is tied in to my main loop, so a couple of niggly toolbar problems will have to stay until the loop issue is addressed.
To finish off, I spent a bit of time implementing a Brush Grid, which automatically resizes itself according to the current Brush size. I then added a function to scroll this whenever the Map is scrolled, and tomorrow I shall add some code to "snap" the Brush to the Grid. This will give the user maximum flexibility grid-wise; they can have a fixed or scrollable grid, with or without the Snap option. Splendid!
Friday, August 20, 2004
Friday 20th
By accident, I stumbled across a rather nice Map Editor which exports to Blitz+ format (though I suspect the editor itself isn't written in Blitz, as they do a number of clever things which Blitz cannot). Interestingly enough, it included a nice animation system (which allows each frame to have a millisecond timer, like animated GIFs), as well as a module to test the map to see how it appears in the finished game (as I mentioned yesterday). Some of their additions are quite nice, especially the separate layer just for pickups and bonuses and suchlike, though a few of their features (such as 100,000,000 tiles) seem somewhat excessive!
Work was cancelled again tonight, which allowed me to continue ploughing through the Windows GUI stuff. I posted a couple of messages on the Blitz forums, in the desperate hope that someone had written a GUI tutorial - alas, this was not the case, but I managed to get some answers to specific questions (and things are much clearer in my head as a result).
The first task was to get a toolbar in and working; I took the liberty of grabbing a few icons from various editors (these will be redrawn at some point, copyright fanatics!), then pasted them into a continuous strip. There seems to be no way to insert "spacers" in a toolbar, so I fired off another question to the forum to that effect, as well as a couple of menu-related issues. In the meantime, I attached a couple of functions to the buttons, and can now load and save with a single click of the mouse.
Tidied up some of the menus, inserting dummy functions for the time being, then set about creating the "Tabbers", which will ultimately allow the user to flick easily between maps. This was easier than anticipated, though the positioning was somewhat painstaking. I then attached the Tile window to the Main window, so it follows it around like a puppy when moved (awww!).
The final task of the night involved getting the tilestrip updating properly in the Tile window, allowing the user to select the tiles, and implementing a cursor. I also hit upon the idea of having the tiles currently in use highlighted by two special cursors, so this was added to my To Do list (which I'll probably tackle tomorrow), along with a small Info window, which will detail miscellaneous stats such as the cursor position, current drawing mode, tiles in use, etc.
Work was cancelled again tonight, which allowed me to continue ploughing through the Windows GUI stuff. I posted a couple of messages on the Blitz forums, in the desperate hope that someone had written a GUI tutorial - alas, this was not the case, but I managed to get some answers to specific questions (and things are much clearer in my head as a result).
The first task was to get a toolbar in and working; I took the liberty of grabbing a few icons from various editors (these will be redrawn at some point, copyright fanatics!), then pasted them into a continuous strip. There seems to be no way to insert "spacers" in a toolbar, so I fired off another question to the forum to that effect, as well as a couple of menu-related issues. In the meantime, I attached a couple of functions to the buttons, and can now load and save with a single click of the mouse.
Tidied up some of the menus, inserting dummy functions for the time being, then set about creating the "Tabbers", which will ultimately allow the user to flick easily between maps. This was easier than anticipated, though the positioning was somewhat painstaking. I then attached the Tile window to the Main window, so it follows it around like a puppy when moved (awww!).
The final task of the night involved getting the tilestrip updating properly in the Tile window, allowing the user to select the tiles, and implementing a cursor. I also hit upon the idea of having the tiles currently in use highlighted by two special cursors, so this was added to my To Do list (which I'll probably tackle tomorrow), along with a small Info window, which will detail miscellaneous stats such as the cursor position, current drawing mode, tiles in use, etc.
Thursday, August 19, 2004
Thursday 19th
Started cleaning up the code today, and planning out the various variables and arrays I'll need to implement multiple maps; I find that inserting comments into the code where I'll need to pop something (such as a variable, array, or routine) helps me to flesh things out and work through potential problems before I start coding, as new features and extra variables will always suggest themselves along the way. In essence, it's almost like pseudo-pseudo-code.
Also took the liberty of updating my To-Do list with a number of feature ideas that have surfaced in the last couple of days; one of these is being able to constrict the main drawing tools using SHIFT (in the case of lines, it restricts them to horizontal, vertical, or diagonal, while rectangles are restricted to squares). These are fairly standard fare in programs such as PhotoShop, and you really miss them when you don't have them - hence their inclusion :)
Another couple of ideas surfaced for Brush Mode (changing the grid size to that of the brush, and allowing the Brush to snap to the grid), animating the collision data for each tile as well as the tile data itself (allowing, for instance, intermittent force fields), and a Test Map module which allows the user to preview how their map will look in the context of a real game (complete with adjustable scroll speeds and parallax scrolling).
Work was cancelled tonight (such is the nature of being an Agency donkey), which gave me a chance to launch into a serious session with Blitz. I've been unhappy with certain aspects of the editor's functionality for a while, so before implementing multiple maps, I really want to get the basic GUI and window structure sorted out (as I mentioned back on August 11). This is something I'd been dreading for a while, as the documentation for Blitz's GUI and Windows functions is a little sparse in places, and most of the forums only seem to lightly scratch the surface.
Additionally, the code is often complex in terms of setting up, initialising, and de-activating the various input gadgets, so cutting 'n' pasting routines and trying to shoe-horn them into the Editor is pointless because the code is heavily fragmented - more often than not, it's better to write from scratch. Most example code is not usually indented either, making it hard or tedious to read in places.
The only graceful way to get things done, therefore, is to load up a sample program (providing I can find one that demonstrates the effect I'm after) and constantly flick back and forth between the sample, the Editor, and the GUI reference guide, and write my own version of the code. It's not pleasant and can be tough on the grey matter, but after a couple of hours I'd learned a number of new tricks, and managed to get the tilestrip displayed in its own little window. Aww, bless.
Also took the liberty of updating my To-Do list with a number of feature ideas that have surfaced in the last couple of days; one of these is being able to constrict the main drawing tools using SHIFT (in the case of lines, it restricts them to horizontal, vertical, or diagonal, while rectangles are restricted to squares). These are fairly standard fare in programs such as PhotoShop, and you really miss them when you don't have them - hence their inclusion :)
Another couple of ideas surfaced for Brush Mode (changing the grid size to that of the brush, and allowing the Brush to snap to the grid), animating the collision data for each tile as well as the tile data itself (allowing, for instance, intermittent force fields), and a Test Map module which allows the user to preview how their map will look in the context of a real game (complete with adjustable scroll speeds and parallax scrolling).
* * *
Work was cancelled tonight (such is the nature of being an Agency donkey), which gave me a chance to launch into a serious session with Blitz. I've been unhappy with certain aspects of the editor's functionality for a while, so before implementing multiple maps, I really want to get the basic GUI and window structure sorted out (as I mentioned back on August 11). This is something I'd been dreading for a while, as the documentation for Blitz's GUI and Windows functions is a little sparse in places, and most of the forums only seem to lightly scratch the surface.
Additionally, the code is often complex in terms of setting up, initialising, and de-activating the various input gadgets, so cutting 'n' pasting routines and trying to shoe-horn them into the Editor is pointless because the code is heavily fragmented - more often than not, it's better to write from scratch. Most example code is not usually indented either, making it hard or tedious to read in places.
The only graceful way to get things done, therefore, is to load up a sample program (providing I can find one that demonstrates the effect I'm after) and constantly flick back and forth between the sample, the Editor, and the GUI reference guide, and write my own version of the code. It's not pleasant and can be tough on the grey matter, but after a couple of hours I'd learned a number of new tricks, and managed to get the tilestrip displayed in its own little window. Aww, bless.
Wednesday, August 18, 2004
Wednesday 18th
Not much progress today either, what with work and the gym and seeing another man about another dog. I tapped in the code I'd written yesterday, but it still took 20 minutes to get working - couldn't work out if it was due to fatigue or lame code (probably both!). Nevertheless, I now have Insert/Delete Column/Row functions in and working.
The next big task - which I'm hoping to tackle as soon as I get a decent chunk of time - is multiple maps. The actual inclusion of these maps and their various layers isn't a problem; what will take the time to implement and debug is the myriad variables to go with each map (width, height, tileset used, has the user made any changes since the last save or load, and so forth). With this in mind, it's likely I'll be tackling the file header information at the same time - plenty of potential for huge mishaps!
The next big task - which I'm hoping to tackle as soon as I get a decent chunk of time - is multiple maps. The actual inclusion of these maps and their various layers isn't a problem; what will take the time to implement and debug is the myriad variables to go with each map (width, height, tileset used, has the user made any changes since the last save or load, and so forth). With this in mind, it's likely I'll be tackling the file header information at the same time - plenty of potential for huge mishaps!
Tuesday, August 17, 2004
Tuesday 17th
No update yesterday, partly due to lack of time, partly due to lack of progress. I did spend a little while looking at some Map Editors for the Game Boy; there are some ridiculously complex editors out there, but also some beautifully simple ones. I quite like Harry Mulder's Map Builder - does exactly what it says on the tin and will provide some useful inspiration.
I took a little time out today to have a look at tuME, an open-source editor which has been knocking around since the days on the Megadrive and SNES, but still has its uses today (I know a chap who used it to put together maps for a GBA title).
It's apparent that tuME is both extremely powerful and extremely flexible, having been written to try and accommodate every possible artist and programmer preference. While this gives you an amazingly flexible tool, it's also horrendously complicated, extremely daunting, and is loaded with features which, with the advent of decent art programs such as PhotoShop, are now a little redundant. It did, however, give me a few ideas for little features I can include, and reminded me that I'd forgotten to include blocks of multiple tiles in my features list. D'oh!
Oh, and a big thanks to Muttley from the YakYak forum, who pointed me in the direction of a nifty C64 Sprite and Character Set ripper (which means I don't have to dig out the C64 and Amiga just yet). I tested it out, and it works a treat, so I now have all the Citadel sprites in one handy bitmap.
Didn't get much code done, due to the inevitable work shift, but I did take the liberty of penning some code on a scrap of paper during my break (I'm seriously considering taking my laptop in, just to do some coding during my breaks).
I took a little time out today to have a look at tuME, an open-source editor which has been knocking around since the days on the Megadrive and SNES, but still has its uses today (I know a chap who used it to put together maps for a GBA title).
It's apparent that tuME is both extremely powerful and extremely flexible, having been written to try and accommodate every possible artist and programmer preference. While this gives you an amazingly flexible tool, it's also horrendously complicated, extremely daunting, and is loaded with features which, with the advent of decent art programs such as PhotoShop, are now a little redundant. It did, however, give me a few ideas for little features I can include, and reminded me that I'd forgotten to include blocks of multiple tiles in my features list. D'oh!
Oh, and a big thanks to Muttley from the YakYak forum, who pointed me in the direction of a nifty C64 Sprite and Character Set ripper (which means I don't have to dig out the C64 and Amiga just yet). I tested it out, and it works a treat, so I now have all the Citadel sprites in one handy bitmap.
Didn't get much code done, due to the inevitable work shift, but I did take the liberty of penning some code on a scrap of paper during my break (I'm seriously considering taking my laptop in, just to do some coding during my breaks).
Sunday, August 15, 2004
Sunday 15th
After checking yesterday's blog for early-morning typos, I realised I'd neglected to include Animated Tiles in my features list. In my experience of tile and graphic Editors, animations have always been painful to set up (and let's face it, if a feature is awkward to use, there's less chance of it being utilised by the artist, and you've compromised the quality of your game from the outset). Therefore, careful thought is required to find a simple but flexible system.
Today was long, but extremely productive (even if I did spend 90% of my time doing household chores while my brain wrestled with a few "Why won't that work?" and "That should work!" nagging niggles). If anything, it made me a little more aware of the weak areas in my coding habits, and should help me to avoid similar problems in the future.
The big task for today was the Grab mode, which allows the user to grab a "Brush" of blocks from the screen, then draw with it (see point 1 from yesterday's entry). The first task was to implement special "corner" cursors for the start and end point, to make it easier to see what's being grabbed. Then I added an overlaid "stipple" pattern which emphasises the area being grabbed even more. The main sticking point here was that the cursors and stipple are drawn to the screen and not the map, so extra code needed to be added to shunt these on and off-screen if the user scrolls the map while grabbing.
Next came the arduous task of copying the highlighted area into a custom-buffer; this seems ridiculously easy in theory, but given the fact that the start and end points can be anywhere on screen, this means that in some situation the routine has to count backwards (whereas, when plotting into an array, it's easier to count forwards using a For...NEXT loop). Struggled with the code for an hour before I realised than my brush display code hadn't been working properly!
After making a few tweaks (and a few coffees), I had the routine fully working apart from a minor bug where the Editor failed to recognise brushes that were 1 tile wide or high. After further investigation, it dawned on me that I was checking for values LESS than the cursor instead of LESS or EQUAL. So, after an hour's hair-tearing, the problem was fixed by typing four "=" characters!
I'm quite pleased with the routine, however (as mentioned earlier, it highlighted a few areas of my code where things weren't going as planned, again thanks to the LESS or EQUAL scenario). It was also my first foray into dynamic arrays - because the Brush array is generated on-the-fly, I can definitely have brushes as big than the entire map. Beans of coolness.
I finished off by adding a red box around the current Brush, which makes things much clearer. I need to invest a little time in some colour-cycling routines at some point, to allow me to "pulse" certain colours to make things easy for the user (the current bog-standard tile cursor cheats by using a small animation), so this has been added to my to-do list.
The final task of the night, and something which was utterly painless to implement, was the Brush clipping at the right and bottom edges of the map. I'm toying with the idea of allowing the user to grab a brush from one map and import the tiles (and brush) into another - this all depends on how the maps are structured (i.e. does every map have its own brush library? Even collision and effects maps?), so tomorrow's main task will involve planning out the map logistics then implementing multiple maps.
Today was long, but extremely productive (even if I did spend 90% of my time doing household chores while my brain wrestled with a few "Why won't that work?" and "That should work!" nagging niggles). If anything, it made me a little more aware of the weak areas in my coding habits, and should help me to avoid similar problems in the future.
The big task for today was the Grab mode, which allows the user to grab a "Brush" of blocks from the screen, then draw with it (see point 1 from yesterday's entry). The first task was to implement special "corner" cursors for the start and end point, to make it easier to see what's being grabbed. Then I added an overlaid "stipple" pattern which emphasises the area being grabbed even more. The main sticking point here was that the cursors and stipple are drawn to the screen and not the map, so extra code needed to be added to shunt these on and off-screen if the user scrolls the map while grabbing.
Next came the arduous task of copying the highlighted area into a custom-buffer; this seems ridiculously easy in theory, but given the fact that the start and end points can be anywhere on screen, this means that in some situation the routine has to count backwards (whereas, when plotting into an array, it's easier to count forwards using a For...NEXT loop). Struggled with the code for an hour before I realised than my brush display code hadn't been working properly!
After making a few tweaks (and a few coffees), I had the routine fully working apart from a minor bug where the Editor failed to recognise brushes that were 1 tile wide or high. After further investigation, it dawned on me that I was checking for values LESS than the cursor instead of LESS or EQUAL. So, after an hour's hair-tearing, the problem was fixed by typing four "=" characters!
I'm quite pleased with the routine, however (as mentioned earlier, it highlighted a few areas of my code where things weren't going as planned, again thanks to the LESS or EQUAL scenario). It was also my first foray into dynamic arrays - because the Brush array is generated on-the-fly, I can definitely have brushes as big than the entire map. Beans of coolness.
I finished off by adding a red box around the current Brush, which makes things much clearer. I need to invest a little time in some colour-cycling routines at some point, to allow me to "pulse" certain colours to make things easy for the user (the current bog-standard tile cursor cheats by using a small animation), so this has been added to my to-do list.
The final task of the night, and something which was utterly painless to implement, was the Brush clipping at the right and bottom edges of the map. I'm toying with the idea of allowing the user to grab a brush from one map and import the tiles (and brush) into another - this all depends on how the maps are structured (i.e. does every map have its own brush library? Even collision and effects maps?), so tomorrow's main task will involve planning out the map logistics then implementing multiple maps.
Saturday, August 14, 2004
Saturday 14th
I was up extremely early this morning (had to see a man about a dog, and all that jazz), and so managed to steal a little time in front of the PC to address the Line mode once and for all. The problem stemmed from the fact that the virtual line was being drawn to the screen buffer, and the floating point caused it to look smoother than the finished product (which, if you've been paying attention, is plotted to an array).
The simple (although not altogether graceful) solution, is to have a temporary array the same size as the existing map which is used to preview the line while it is being drawn - once the mouse button is released, the temporary line is plotted to the map proper. Nailed this code in a matter of minutes, and the routine worked beautifully.
The code won't go to waste, either, as most of the other drawing tools will also utilise this temporary buffer. With this in mind, I quickly knocked up the code for plotting rectangles on the screen.
After this came the job of tackling the Fill option; I spent some time reading up on various fill techniques, and most obvious answer seemed to be, work out how it is done, choose the best method, then see if someone else has written the code already. :)
As luck would have it, I managed to track down some fill code which was both accurate and fast (as opposed to recursive and clever, but dreadfully slow), and after a few minutes tinkering and debugging, the fill routines were in and working.
After getting some much-needed sleep, I decided to spruce up the editor a little by adding a nice pulsing cursor that isn't as heavy on the eyes as the old random one. I also corrected a few little flickers here and there (just because it's an Editor doesn't mean it has to be flaky).
I'm starting to get a clearer idea of the remaining functions and features I want the editor to include, so here's a brief rundown of the major tasks on the horizon in no particular order (which also doubles as my to-do list):
1. Brushes: it would be extremely nice to be able to grab chunks of on-screen data and paste them around as required. I might impose a limit on the size of brushes, but certainly, the user will be able to build up a library of common brushes (and save these out with the current maps / tilesets as part of a project file). Some Editors allow the user to grab a brush from multiple layers - I'll be neglecting to implement this level of complexity (it's hard to work in three dimensions when one of those dimensions is obscured by the other two!).
2. Multiple Maps: The editor deals exclusively with one map at present - this will be expanded to 8, accessible via the number keys.
3. Multiple Map Layers: For those wishing to create multi-layer, parallax backdrops, the editor will allow the user to have up to 4 layers for each map (foreground, background, static backdrop, and "copperlist" sky).
4. Multiple Tilesets: Currently there is only one tileset in memory but ideally, the user should be able to pick from a library of available tilesets when creating a map (and even change them on-the-fly - if they've organised their tiles in an orderly fashion, with wall tiles and suchlike in the same locations, there's no reason why this wouldn't be a useful feature).
5. Grab Tiles: Most decent editors allow the user to load in a bitmap and grab a tileset from the image. I'm toying with the idea of using a cursor to grab tiles from anywhere on the image (i.e. not using just a rigid grid of 16x16 or suchlike).
6. Tile Load & Save: Currently the user can only load and save maps, this needs to be expanded to encompass tiles, too.
7. Grid Display: Simple feature to display an overlaid grid in order to make map construction easier (this will be intelligent enough to automatically detect the current tilesize and draw itself accordingly).
8. File Headers: The various files will need proper header information, ultimately so that they will interface with the game seamlessly - there's no point writing specific code to set up each map when the game can read the header information and do it all automatically.
9. Tile Collision Data: I'd like to add a separate array which holds the collision data for each tile (i.e. solid wall, walk through, death, drain energy, solid to enemy but not player, enemy only, player only, etc.). This allows the user - if desired - to check collisions using just one map, as opposed to having a separate collision map. Speaking of which...
10. Collision Maps: Sometimes known as an Edge of Road map, this is a physically different map to the one which the player sees, but is used to dictate the collision detection. This is more flexible than defining collision data for each tile: for instance, you may want to have a swamp that the player can walk across safely, and one which drains their energy. By defining the safe and dangerous areas on the collision map, you can use the same tiles for both swamps without resorting to having duplicate tiles with different (i.e. safe / dangerous) attributes.
11. Collision Map Generator: As an extension of points 9 and 10, the user will be able to set up collision data for each tile, and then the editor will generate the collision map based on this data - this allows the user to very quickly set up collision maps, then go in and tweak by hand (rather than create an entire collision map from scratch).
12. Effects Map: Useful for triggering bonuses, enemies, and - as its name suggests - other effects, this will be an overlaid map tied to the main playfield like the collision map.
13. Tile Flipping: Gone are the days when artists have to produce flipped versions of their tiles - any editor worth its salt nowadays has a flip tile flag which tells the game engine to flip the tile as it is being drawn. Absolutely no idea how I'll be implementing this, but it's on my list.
Work continued into the wee small hours; after updating this blog, I set about tackling a few more drawing tools, including the Box Fill command (which draws solid rectangles instead of hollow ones), and the Box Fill Continuous command (which fills the rectangle with a continuous chunk of tiles - useful if you have large or complex graphics in your tileset). I also implemented multiple tilesets, added the Grid function, and fixed a couple of small bugs that had slipped through the net.
Despite this rapid progress, things have to proceed a little more carefully and methodically from now on; all of my drawing routines currently reference just a single map, so to avoid changing more routines than necessary, once I've implemented the Brush options I'll set about implementing multiple maps and tweak things accordingly. I also have to keep tabs on my routine order, as some routines affect a variable which may not get updated for another frame, causing glitches and flickers. Careful planning is the key - wish me luck!
The simple (although not altogether graceful) solution, is to have a temporary array the same size as the existing map which is used to preview the line while it is being drawn - once the mouse button is released, the temporary line is plotted to the map proper. Nailed this code in a matter of minutes, and the routine worked beautifully.
The code won't go to waste, either, as most of the other drawing tools will also utilise this temporary buffer. With this in mind, I quickly knocked up the code for plotting rectangles on the screen.
After this came the job of tackling the Fill option; I spent some time reading up on various fill techniques, and most obvious answer seemed to be, work out how it is done, choose the best method, then see if someone else has written the code already. :)
As luck would have it, I managed to track down some fill code which was both accurate and fast (as opposed to recursive and clever, but dreadfully slow), and after a few minutes tinkering and debugging, the fill routines were in and working.
After getting some much-needed sleep, I decided to spruce up the editor a little by adding a nice pulsing cursor that isn't as heavy on the eyes as the old random one. I also corrected a few little flickers here and there (just because it's an Editor doesn't mean it has to be flaky).
* * *
I'm starting to get a clearer idea of the remaining functions and features I want the editor to include, so here's a brief rundown of the major tasks on the horizon in no particular order (which also doubles as my to-do list):
1. Brushes: it would be extremely nice to be able to grab chunks of on-screen data and paste them around as required. I might impose a limit on the size of brushes, but certainly, the user will be able to build up a library of common brushes (and save these out with the current maps / tilesets as part of a project file). Some Editors allow the user to grab a brush from multiple layers - I'll be neglecting to implement this level of complexity (it's hard to work in three dimensions when one of those dimensions is obscured by the other two!).
2. Multiple Maps: The editor deals exclusively with one map at present - this will be expanded to 8, accessible via the number keys.
3. Multiple Map Layers: For those wishing to create multi-layer, parallax backdrops, the editor will allow the user to have up to 4 layers for each map (foreground, background, static backdrop, and "copperlist" sky).
4. Multiple Tilesets: Currently there is only one tileset in memory but ideally, the user should be able to pick from a library of available tilesets when creating a map (and even change them on-the-fly - if they've organised their tiles in an orderly fashion, with wall tiles and suchlike in the same locations, there's no reason why this wouldn't be a useful feature).
5. Grab Tiles: Most decent editors allow the user to load in a bitmap and grab a tileset from the image. I'm toying with the idea of using a cursor to grab tiles from anywhere on the image (i.e. not using just a rigid grid of 16x16 or suchlike).
6. Tile Load & Save: Currently the user can only load and save maps, this needs to be expanded to encompass tiles, too.
7. Grid Display: Simple feature to display an overlaid grid in order to make map construction easier (this will be intelligent enough to automatically detect the current tilesize and draw itself accordingly).
8. File Headers: The various files will need proper header information, ultimately so that they will interface with the game seamlessly - there's no point writing specific code to set up each map when the game can read the header information and do it all automatically.
9. Tile Collision Data: I'd like to add a separate array which holds the collision data for each tile (i.e. solid wall, walk through, death, drain energy, solid to enemy but not player, enemy only, player only, etc.). This allows the user - if desired - to check collisions using just one map, as opposed to having a separate collision map. Speaking of which...
10. Collision Maps: Sometimes known as an Edge of Road map, this is a physically different map to the one which the player sees, but is used to dictate the collision detection. This is more flexible than defining collision data for each tile: for instance, you may want to have a swamp that the player can walk across safely, and one which drains their energy. By defining the safe and dangerous areas on the collision map, you can use the same tiles for both swamps without resorting to having duplicate tiles with different (i.e. safe / dangerous) attributes.
11. Collision Map Generator: As an extension of points 9 and 10, the user will be able to set up collision data for each tile, and then the editor will generate the collision map based on this data - this allows the user to very quickly set up collision maps, then go in and tweak by hand (rather than create an entire collision map from scratch).
12. Effects Map: Useful for triggering bonuses, enemies, and - as its name suggests - other effects, this will be an overlaid map tied to the main playfield like the collision map.
13. Tile Flipping: Gone are the days when artists have to produce flipped versions of their tiles - any editor worth its salt nowadays has a flip tile flag which tells the game engine to flip the tile as it is being drawn. Absolutely no idea how I'll be implementing this, but it's on my list.
* * *
Work continued into the wee small hours; after updating this blog, I set about tackling a few more drawing tools, including the Box Fill command (which draws solid rectangles instead of hollow ones), and the Box Fill Continuous command (which fills the rectangle with a continuous chunk of tiles - useful if you have large or complex graphics in your tileset). I also implemented multiple tilesets, added the Grid function, and fixed a couple of small bugs that had slipped through the net.
Despite this rapid progress, things have to proceed a little more carefully and methodically from now on; all of my drawing routines currently reference just a single map, so to avoid changing more routines than necessary, once I've implemented the Brush options I'll set about implementing multiple maps and tweak things accordingly. I also have to keep tabs on my routine order, as some routines affect a variable which may not get updated for another frame, causing glitches and flickers. Careful planning is the key - wish me luck!
Friday, August 13, 2004
Friday 13th
A semi-productive session before work saw the Line tool virtually finished. I'd not been looking forward to implementing this, mainly because of the checks required to see if the user is drawing a line, holding the mouse, releasing the mouse, etc.
I examined the code from an example paint program and surmised that they were doing their drawing routines using simple buffer swaps, which seemed promising - after a little tinkering, and more than a little rational thought, the conundrum was solved and the code written in just a few minutes (it's all flooding back, just a little too slowly!).
After I got the controls working, however, I hit a stumbling block: when the user is holding the mouse, a "virtual" line is plotted to the screen (so you can see where the line will be); when the mouse is released the "actual" line is plotted to the map array. A problem arose with the maths behind the routine - the virtual line is drawn with floating point numbers, while the plotted line isn't. This makes the virtual line ultra-smooth and not at all representative of the finished line.
After 20 minutes of trying various commands such as Mod and Floor (which discard remainders and round down numbers respectively), I had to leave for work and thus left the unsolved problem swimming around in my head. Grrr.
I examined the code from an example paint program and surmised that they were doing their drawing routines using simple buffer swaps, which seemed promising - after a little tinkering, and more than a little rational thought, the conundrum was solved and the code written in just a few minutes (it's all flooding back, just a little too slowly!).
After I got the controls working, however, I hit a stumbling block: when the user is holding the mouse, a "virtual" line is plotted to the screen (so you can see where the line will be); when the mouse is released the "actual" line is plotted to the map array. A problem arose with the maths behind the routine - the virtual line is drawn with floating point numbers, while the plotted line isn't. This makes the virtual line ultra-smooth and not at all representative of the finished line.
After 20 minutes of trying various commands such as Mod and Floor (which discard remainders and round down numbers respectively), I had to leave for work and thus left the unsolved problem swimming around in my head. Grrr.
Thursday, August 12, 2004
Thursday 12th
No work tonight, which gave me chance to have a good session with Blitz and get the Editor working in a proper window. The main problem with this is really the lack of documentation that comes with Blitz - every command is explained, but seldom few are properly discussed or come with examples. This paves the way for a lot of command clashes and errors, and it's often a nightmare to work out what's going on.
Nevertheless, patience reaped its rewards and after a couple of hours tinkering I had the editor running in a proper window, file loading and saving was sorted (the previous system used a DOS box and was far from graceful), and the mouse scaling issues were rectified.
To finish off, I grabbed the map from Citadel's second level on the C64 emulator and stitched it together in PhotoShop (the reason being, I'll soon be implementing multiple maps and tilesets and will need visibly different data to use). As an afterthought, I also devised a neat way of generating collision maps by allowing the user to store collision data for every tile; that way, their code can either use the collision map as an "edge of road" map, or check for collisions on a per-tile basis.
Nevertheless, patience reaped its rewards and after a couple of hours tinkering I had the editor running in a proper window, file loading and saving was sorted (the previous system used a DOS box and was far from graceful), and the mouse scaling issues were rectified.
To finish off, I grabbed the map from Citadel's second level on the C64 emulator and stitched it together in PhotoShop (the reason being, I'll soon be implementing multiple maps and tilesets and will need visibly different data to use). As an afterthought, I also devised a neat way of generating collision maps by allowing the user to store collision data for every tile; that way, their code can either use the collision map as an "edge of road" map, or check for collisions on a per-tile basis.
Wednesday, August 11, 2004
Wednesday 11th
Nothing much to report for today. Tinkered around with a line-drawing algorithm, managed to find a piece of code that works - now all I have to do is integrate this into the editor (which is easier said than done, as it's pretty hard to read the mouse and deduce when the user is holding and letting go of the mouse button). Further exploration unearthed a small paint program, so I'll have a shufty through the source for that tomorrow.
Though the program is currently running in a window, it's getting to the point where the Editor really needs the functionality you'd expect from a window-based program (menus, toolbars, tabs, etc.), so this is the next big task at hand. Luckily it merely involves enclosing the current code within a Windows "shell", and should be a painless process. With this in mind, here's a screenshot of the Editor as it currently stands - expect it to look significantly different next time you see it. :)
Though the program is currently running in a window, it's getting to the point where the Editor really needs the functionality you'd expect from a window-based program (menus, toolbars, tabs, etc.), so this is the next big task at hand. Luckily it merely involves enclosing the current code within a Windows "shell", and should be a painless process. With this in mind, here's a screenshot of the Editor as it currently stands - expect it to look significantly different next time you see it. :)
Tuesday, August 10, 2004
Tuesday 10th
Quite a fruitful session before work; tweaked a few values here and there to cope with certain things starting at 0 and others at 1 (for instance, you define a 10x10 array as 10,10 but index it using 0-9... seems obvious, but nobody told me!). Added the ability to 'store' different tiles in the Left and Right mouse buttons, then added a tilestrip at the bottom of the editor, got it scrolling using keypresses, and allowed the user to choose their Left/Right tile by clicking on the tilestrip. Also had to expand the current tileset to hold 256 tiles (and fix more nasty indexing problems... grrr...).
Admittedly, none of this is exactly rocket science to the average coder, but I'm having a lot of fun coding again, getting results, and working through bugs. And considering I've only officially been using the package since Friday, I'm pretty pleased with my results.
Admittedly, none of this is exactly rocket science to the average coder, but I'm having a lot of fun coding again, getting results, and working through bugs. And considering I've only officially been using the package since Friday, I'm pretty pleased with my results.
Monday, August 9, 2004
Monday 9th
Not much to report today, as I was up late and also had a work shift to contend with (which is a bugger, because I was itching to do some coding). I went back through the Editor code and did some tidying up, removing some debug variables and generally making the thing a little more efficient. I have a couple of immediate goals regarding the editor, the main one being to display a strip of tiles across the bottom of the screen, and having the user click on any tile to select it. Fairly straightforward stuff, but I'm still getting my head around arrays and indexing (mainly because the screen variables start at 1 but arrays start at 0). I'll get there.
Sunday, August 8, 2004
Sunday 8th
I set myself a few goals today: the first was to sort out a bitmap font routine, to start work on the scroller, and to fix some timing issues (the game is running in a window, and speeds up when the mouse is moved - something suggests that the frame swap isn't being done on every vsync). Thankfully, I managed to get the timing problem sorted out straight away, thanks to a chap at the Cool Creations Forum, so I cracked on with the font routine without delay.
This is really where things start to get interesting, as I can poach someone else's font routine, dissect it and work out how things are done, then make changes and modifications to suit my needs. Which is precisely what I did; I now have a routine which allows for multiple fonts, can centre text according to the font size and screen resolution, and also flash it to get the player's attention. There are a couple of features I'd like to add to this routine, such as scaling, shadows, and colour effects, but that will come later. Seeing as I "borrowed" the font routine from the CC forum, I decided to give something back and posted a few links to bitmap fonts from various demos. Aren't I nice? :)
Spent the rest of the night tinkering with a Map Editor; I've been toying with the idea of writing a decent, open-source editor (I'm going to need one for Citadel anyway, and there are precious few out there which are flexible enough to do what I need). In the traditional fashion, I took a couple of existing editors - both of which were fairly basic - and merged the functionality, adding things like mouse control in the process. After staying up until 6am tracking down bugs, I finally had the thing working. Ah, the joys of code. :)
This is really where things start to get interesting, as I can poach someone else's font routine, dissect it and work out how things are done, then make changes and modifications to suit my needs. Which is precisely what I did; I now have a routine which allows for multiple fonts, can centre text according to the font size and screen resolution, and also flash it to get the player's attention. There are a couple of features I'd like to add to this routine, such as scaling, shadows, and colour effects, but that will come later. Seeing as I "borrowed" the font routine from the CC forum, I decided to give something back and posted a few links to bitmap fonts from various demos. Aren't I nice? :)
Spent the rest of the night tinkering with a Map Editor; I've been toying with the idea of writing a decent, open-source editor (I'm going to need one for Citadel anyway, and there are precious few out there which are flexible enough to do what I need). In the traditional fashion, I took a couple of existing editors - both of which were fairly basic - and merged the functionality, adding things like mouse control in the process. After staying up until 6am tracking down bugs, I finally had the thing working. Ah, the joys of code. :)
Saturday, August 7, 2004
Saturday 7th
I spent a little bit of time today grabbing various pieces of "inspiration" for the game; first came the arduous job of tracking down a copy of Paradroid 90. Now, Citadel has always owed a small debt to Paradroid, but in my mind the games were always poles apart in terms of gameplay (Citadel being more strategic in nature). However, the more ideas I think of to update the game, the closer it edges towards Paradroid. Hmmm. The last thing I want to do is a Paradroid clone, hence hunting down a copy of the game to see how Braybrook updated his baby for the Amiga.
After a couple of hours slaving over a hot emulator, I came away most disappointed; Paradroid 90 is a nice game, don't get me wrong, but the vertical scrolling really changes (and restricts) the gameplay, and some of the background obstacles are annoyingly obtrusive. It did spawn a couple of ideas, however, regarding the hierarchy of the robots and the communication structure they would use (I worked on a PS2 game a couple of years ago, and had an extremely tight set of security droids which communicated in a very specific way - the player had to work around this, but could also use it to his/her advantage by luring robots to other parts of the level).
I rounded off the night with a coding session; up until now, I'd merely been fiddling about with other people's programs, but considered it about time I went back to the start and ploughed through the Getting Started and Tutorial sections. Five hours later, I'd been through everything and had started work on a test-bed for the title screen (complete with Citadel logo and a scrolling backdrop of Monitor craft!).
After a couple of hours slaving over a hot emulator, I came away most disappointed; Paradroid 90 is a nice game, don't get me wrong, but the vertical scrolling really changes (and restricts) the gameplay, and some of the background obstacles are annoyingly obtrusive. It did spawn a couple of ideas, however, regarding the hierarchy of the robots and the communication structure they would use (I worked on a PS2 game a couple of years ago, and had an extremely tight set of security droids which communicated in a very specific way - the player had to work around this, but could also use it to his/her advantage by luring robots to other parts of the level).
I rounded off the night with a coding session; up until now, I'd merely been fiddling about with other people's programs, but considered it about time I went back to the start and ploughed through the Getting Started and Tutorial sections. Five hours later, I'd been through everything and had started work on a test-bed for the title screen (complete with Citadel logo and a scrolling backdrop of Monitor craft!).
Friday, August 6, 2004
Friday 6th
I've decided to treat my Blitz project with the respect it deserves and give it a small blog all of its own (as opposed to bundling it into my LiveJournal). And so, after spending far too much time setting up a basic template for this page, here it is. Er, great. Hi. Come in. :)
I must admit, I wasn't planning on learning a C-orientated language; I've never been able to get to grips with that particular coding style, much preferring the logical, step-by-steppedness of assembly language. That was, until I was nudged in the direction of Blitz Basic. After piddling about with the demo version for a few days, the potential soon became apparent - it's a beautiful program, allows you to get results up on screen straight away, and best of all, there are plenty of support resources should you get stuck (I've stuck a couple of these in the Links column, over there on the left).
One thing that was clear in my mind, however, was the project I wanted to tackle: the unsung C64 classic-that-never-was, Martin Walker's Citadel. I followed Martin's Zzap!64 diary word by word each month (and even contributed a few ideas of my own, which gained me a wee hello from Martin in one of the entries), was completely obsessed with the game when it was released, and subsequently produced the maps and tips that appeared in Zzap!64.
I re-read the Walker's Way diaries last week in preparation for the project, furiously scribbling down any ideas or concepts that never made it into the final game (yep, all four of them). What was most useful, however, was the behind-the-scenes knowledge of how the scroller worked, along with the 'scalextric' structure of the data. This now gives me a few ideas on how to create updated maps.
Rounded off the night by grabbing the entire first level and stitching it together in PhotoShop, as well as a few other choice screens such as the Loading Screen, Title Screen logo, and Status Panel. The chessboard tiles for the floor were a bit harsh, however, so I replaced them with a stonework tile which is much easier on the eye (well, my eyes, at least).
Grabbing sprites is another matter, however; on the Amiga, I have a utility called TransSprite (written by Ash Hogg), which allowed me to download sprites to Amiga bitmaps via my C64 cross-assembler. I want to use this again, but this involves the task of dragging the C64 and Amiga from the attic and get them set up again, then getting the Amiga talking to the PC, so I can drop the graphics files straight onto my hard drive. These both require a fair amount of space, so a slight re-organisation of my desk might be in order. Hmmm.
I must admit, I wasn't planning on learning a C-orientated language; I've never been able to get to grips with that particular coding style, much preferring the logical, step-by-steppedness of assembly language. That was, until I was nudged in the direction of Blitz Basic. After piddling about with the demo version for a few days, the potential soon became apparent - it's a beautiful program, allows you to get results up on screen straight away, and best of all, there are plenty of support resources should you get stuck (I've stuck a couple of these in the Links column, over there on the left).
One thing that was clear in my mind, however, was the project I wanted to tackle: the unsung C64 classic-that-never-was, Martin Walker's Citadel. I followed Martin's Zzap!64 diary word by word each month (and even contributed a few ideas of my own, which gained me a wee hello from Martin in one of the entries), was completely obsessed with the game when it was released, and subsequently produced the maps and tips that appeared in Zzap!64.
I re-read the Walker's Way diaries last week in preparation for the project, furiously scribbling down any ideas or concepts that never made it into the final game (yep, all four of them). What was most useful, however, was the behind-the-scenes knowledge of how the scroller worked, along with the 'scalextric' structure of the data. This now gives me a few ideas on how to create updated maps.
Rounded off the night by grabbing the entire first level and stitching it together in PhotoShop, as well as a few other choice screens such as the Loading Screen, Title Screen logo, and Status Panel. The chessboard tiles for the floor were a bit harsh, however, so I replaced them with a stonework tile which is much easier on the eye (well, my eyes, at least).
Grabbing sprites is another matter, however; on the Amiga, I have a utility called TransSprite (written by Ash Hogg), which allowed me to download sprites to Amiga bitmaps via my C64 cross-assembler. I want to use this again, but this involves the task of dragging the C64 and Amiga from the attic and get them set up again, then getting the Amiga talking to the PC, so I can drop the graphics files straight onto my hard drive. These both require a fair amount of space, so a slight re-organisation of my desk might be in order. Hmmm.
Thursday, July 29, 2004
Faded Limes
In the movie The Green Mile, Paul Edgecombe's older self takes long walks up into the hills every day. It's one of my favourite film sequences, for reasons which escape me. I guess I just like the sense of exploration and freedom it captures; the idea that nobody in the entire world knows where you are at that precise moment.
Well, my mind is finally "doing an Edgecombe". The job that I do is not particularly mentally taxing, so it's nice to have a lot of free thinking time while the hands are busy. Recently, I got to thinking about a project I could tackle in my spare time (and though I'd dearly love to do something on the C64, and will no doubt tinker with the beast when it emerges from the attic, I think the limitations would start to annoy me).
After much thought - and more than a little help from the chaps at the Llamasoft Forum - I've decided to plumb for Blitz Basic and remake some old C64 games. This has several benefits, not least the fact that my old chum Jon Wells is a Blitz user and is always on hand with suggestions and tips. :)
I have a project in mind. I have a vision of how it will look. I also have several ideas for interesting ways to expand the game.
Now all I have to do...
Well, my mind is finally "doing an Edgecombe". The job that I do is not particularly mentally taxing, so it's nice to have a lot of free thinking time while the hands are busy. Recently, I got to thinking about a project I could tackle in my spare time (and though I'd dearly love to do something on the C64, and will no doubt tinker with the beast when it emerges from the attic, I think the limitations would start to annoy me).
After much thought - and more than a little help from the chaps at the Llamasoft Forum - I've decided to plumb for Blitz Basic and remake some old C64 games. This has several benefits, not least the fact that my old chum Jon Wells is a Blitz user and is always on hand with suggestions and tips. :)
I have a project in mind. I have a vision of how it will look. I also have several ideas for interesting ways to expand the game.
Now all I have to do...
Subscribe to:
Posts (Atom)

