Updates to TGB Dungeon Builder
I’ve spent the past week cleaning up the Dungeon Builder code, 15 minutes here, 15 minutes there … and have taken it from “prototype code” to “alpha code” … it’s now much cleaner looking, a hell of a lot easier to work with, and makes damn near perfect sense now … and boy, let me tell you … going from prototype to alpha … WHAT A BITCH … I damn near lost it a few times … couldn’t figure out what the hell I was thinking when I wrote some of the code, only to find out … most of the code that was giving me headaches didn’t work and wasn’t rendering stuff anyhow … I must have just left it in there when I was doing the prototype “just in case” … and figured “its not putting stuff on screen, who cares …” and kept going …
But now the code has a fairly easy to follow structure … and I’ve even created an Image Map mock-up that I’m using …
To see more “pretty” pictures, continue reading …
TGB Dungeon Builder
For those of you who remember the original “3D” dungeon crawlers, such as Stonekeep, Eye of the Beholder, Lands of Lore or Bard’s Tale … this might be of interest to you.
I saw a post on the GG forums a couple days ago, and it peaked an interest … and, being me, I had to scratch the itch … so I started working on it. I’ve got some pretty decent progress so far, especially for a few hours of prototyping work … Images are attached for your viewing pleasure.
The general concept is this, using a 2D Tile-Layer (multiple layers, possibly?), the “player”can move around a “pseudo-3D” environment. Basically, using 2D Sprites, which are custom made (I’ll tell you how a little further down …), we draw the first set of sprites and only show a portion of them, to simulate ‘being in the room’, then we draw the next set of sprites … at a reduced size, and butted up against the previous sprites on the X/Y coords … and we repeat this process until we feel we have a good ‘distance’ in front of us (for my tests, 6 rooms seems about the extent of viewable distance with -my- artwork — other artwork may allow for up-to maybe 10 rooms?).
The trick is … if we have a 512×512 seamless tiling texture, and we skew the right side of it so that the right edge is only 256 tall and perfectly centered (128-384) and then we squish the graphic’s width and divide by 4 (512/4 = 128) … we wind up with a … Perspective Tile … Nice, eh?
Now, if we take the image we just created, and duplicate it so we now have 4 copies … then rotate one, place it ontop of the first so the top-left edges are have the same coords, then flip the next one and make it so the top-right corners are touching the one we just rotated … then rotate the next and smack it down at the bottom… we have a ‘pseudo-3D’ room.
Now, if it were only this simply in code, right?
Well, it sort of is … difference is, the code should be intelligent enough to draw the right texture in the right place, and only draw a texture when it should …
Say what?
Yeah, ok … so, we build a 2D Tile-Layer, and every three horizontal squares are a ‘room’ … the left tile is the left wall and the right tile is the right wall, and the center tile represents the floor/ceiling (eh?) … so, if we use this to determine what artwork to draw, the previous example still applies, we just don’t make 4 copies of the same image anymore, we make copies of the images we want to draw …
So what about drawing rooms in front of us? Well, the same logic as mentioned above applies, but, we have to just simply scale our images … given the 512×512 to 128×512 image example i mentioned, our scale is literally 50% (hence the simplicity of the image I made for testing). We scale everything down by 50% … and just make sure that our left-wall image (the basis of our coordinates) is in the right place … which would be the width of the wall before it, minus the width of the current wall divided by four … why? I honestly don’t remember off hand… haha …
I intend to have a much more detailed description, and hopefully some more useful screenshots in the near future….
Here’s a diagram of the general concept:

A working “prototype” layout, completely faked in Level Builder with scaling and positioning of artwork

This is actually ‘rendered’ with some code that looks at a 2D Tile-Layer to know what to draw …

And here we are after another hour of coding, with a hallway and a t-junction … all determined from a 2D tile-layer.

Tile-Match Logic Explained
I posted this in the TGB Private Forums as a response to someone’s question of how to ‘perform tile-match logic’, and after I posted it and took a look at how much I wrote in such a short time, I felt the need to ‘record’ it for later use (perhaps a tutorial?)
So here goes…
For the general logic, you have a number of ways to approach the matter — you can create your tiles and apply ‘customData’ to them, such as that all tiles that ‘match’ have the same customData — as TorqueScript is type-less and numbers and words are treated as the same thing, I do not think that using numeric values would increase search performance, but it’s always best to assume numerics are faster unless you know otherwise.
As for the search … in a game like Bejewelled, you would search the entire grid, over and over, and over again until you ran out of matches — every tile has to be searched, and the search should (depending on game logic, and visual appeal) start from scratch each time a match is completed –
I believe the general ‘logic’ for bejeweled follows this, where say you have the following:
ABCD
ACCC
ABDD
BCDD
You would first find the ‘A’ (top-left) match (two tiles below), remove them, then replace them with new tiles — we’ll assume the new tiles do not cause any additional matches, k?
Now, we find the ‘CCC’ match in the second row … we remove them, move all the tiles above down one row, then fill the missing tiles (assume again, no additional matches are generated by the new tiles)
This will then create a new match, causing ‘DDD’ (bottom right) … and we then remove those tiles, move the rest down, then replace them –
For a game with bejewel’s basic ‘logic’, we would scan the tile-layer repeatedly, until we stop finding matches …
You can ‘pause’ general gameplay (user interactions) by setting some sort of a ‘search in progress’ flag, that is checked for at the start of the tilelayer::onMouseDown event (or whatever triggers your user-interaction for the tile-map)
Storing the data in the tile-layer allows for an ‘easy to code’ search to take place, but may not necessarily be the best approach for performance, especially if your scanning over hundreds of things (in the case of bejeweled, I think it’s like what … 30-60 gems on screen at a time? Thats not too bad … scanning and replacing 20 matches can be done in the blink of an eye — without special ‘match’ animations, of course)
If your looking for a performance boost, it’d be best to store a reference to your tiles custom-data in an array (you can make it multidimensional if you want, or just do some fun math)
For example, if you have a “grid” that is 8×8
ABCDEFGH
HGFDSABV
AVBGFDSS
ABCDFGEH
ABCDFGEH
ABCDFGEH
ABCDFGEH
You could store the 64 tiles ‘customdata’ in a single dimension array:
[js]$tiles[0] = “A”;
$tiles[1] = “B”;
…
$tiles[63] = “H”;[/js]
You could then determine matches quickly with the following math:
Tile 0,0 = 0
Tile 0,1 = 1
Tile 1,0 = 8
Tile 2,0 = 16
Tile 3,3 = 26
To find the next row, just add 8 to the current row –
Here’s a coded example:
[js]%tile = %this.pickTile(%worldPosition); // returns “4 5″;
%x = getWord(%tile, 0);
%y = getWord(%tile, 1);
%idx = %x * 8 + %y – 1;[/js]
Now — in the example grid above, all 8 columns in the last 4 rows create a ’4-part match’
Given that our ‘match’ search algorithm is at 4,0 (5th row, 1st column == “A”)
We know that checking ‘above’ is useless, since if a match from ‘above’ were made, it would have been caught by an earlier iteration of our ‘search’ algorithm, so we simply have to look in the next possible directions — (using bejeweled logic here)
[js]%x = 4;
%y = 0;
%idx = ((%x *
+ %y) – 1;
if($tiles[%idx] $= $tiles[%idx + 1]) match(%idx, 1);
else if($tiles[%idx] $= $tiles[%idx + 8]) match(%idx, 8);[/js]
Now, this assumes we have a function called “match()” which takes two-parameters, the “start tile” and “offset tile” that match — this “match” function would then have some logic, and would be able to determine by using the difference of %startTile and %offsetIdx, like so;
[js]function match(%startTile, %offsetIdx)
{
if($tiles[%startTile] $= $tiles[%startTile + (%offsetIdx * 2)])
{
// special ‘found a 3-way match’ logic goes here
}
else
{
return false;
}
}[/js]
Now — this is by no means a “Tutorial” on how to do matching games — and it’s not even really a thorough explaination of how to find a match — but this should definately give you both a good starting point –
Oh and, remember one thing, I love testing new games … *hint hint*
First Game Release – Beta Build
Zoul Creation’s is proud to announce the release of it’s first Beta — DinoMemory.
If your interested in giving the beta a try, and providing some feedback, please download the beta from the following link: http://projects.zoulcreations.com/releases/DinoMemory.zip
For those of you with Mac OSX, Rob Sandbach from Urban-Games was kind enough to build a Universal Binary, you can download it here: http://projects.zoulcreations.com/releases/DinoMemoryOSX.zip
Currently, it’s called “DinoMemory” as the only card sets you can work with are Dinosaurs, however, before the project is made public, I intend to hopefully include some “girl friendly” and “unisex” artwork (Dinosaurs tend to be “male”-ish).
If you download the beta, and wish to provide feedback (good, bad, negative, bug reports, what have you), please email me at BetaFeedback@zoulcreations.com. This email address is being protected from spam bots, you need Javascript enabled to view it
Thank you, and enjoy the beta.
TGB Resource: Bitmap Fonts
Ok, so I’ve been on a role in the past 24 hours. I just released the ‘Easy Edit’ resource, mentioned in a previous post, and have now just released the ‘Bitmap Fonts’ resource earlier this morning.
This latest resource, Bitmap Fonts, allows for the use of Bitmap Fonts in TGB. What does this mean? Well, remember the old days where fonts were actually just ’tiles’ in an “image map” and had to be drawn to the screen just like any other graphic? Well, those fonts were cool, blocky and pixelated, etc, etc — this resource allows you to bring back some of the old, and even mix it with a bit of the new, by creating font images, which are just a series of tiled characters on an image in a specific order. The resource even allows for multiple fonts to exist in the same image map.
For ‘purty’ screenshots of the resource in action, as well as an example ‘font’ image, read this entire post, or jump over to the GG .plan
TGB Resource – Easy Edit v1.0.0
I have just recently posted a .plan on the GarageGame’s website, with links to a recently released TGB Resource that I am proving to the community for free.
The resource in mention is called “Easy Edit v1.0.0″, and is a simple floater that can be toggled on/off with a shortcut or menu option, and it’s functionality is quite simple. It contains 9 buttons, 8 buttons for each map direction and a center button.
Each button moves the level builders active camera position in the direction clicked. The resource is intended more as an example of how to create custom resources, and to also promote the creation and distribution of custom resources.
Here’s a screenshot of the resource:

XMLObject v1.0 Beta Release
I have released the existing XMLObject code as a v1.0 Beta, and the details can be found in this GG .plan.
The current object supports the majority of the expat libraries standard callbacks, with the exception of it’s Schema/DTD callbacks, as well as the ability to parse both a full file and a string (obtained from network resources such as SOAP and XML-RPC requests).
Additional features, demos and examples of use for the XMLObject will be released in time, these examples include integrating my existing HighScores object as an XML document, as well as retrieving the HighScores object from a network resource.
For more details, and a download link, please drop by and read the GG .plan.
XMLObject Updates
Ok, I’ve finished some more of the XMLObject code, and now have the following SAX methods implemented as TorqueScript callbacks:
- onElementStart(%this, %name, %attributes)
- onElementEnd(%this, %name)
- onCharacterData(%this, %name, %data) // %name is a reference to the last element started
- onProcessingInstruction(%this, %target, %data)
- onComment(%this, %data)
- onCdataSectionStart(%this)
- onCdataSectionEnd(%this)
- onDefault(%this, %data, %len)
Not all of the callbacks have been thoroughly tested, but the following callbacks have been tested and found to be in full working order so far;
OnElementStart, onElementEnd, onCharacterData and onComment.
It looks like I’m getting nearer and nearer to having my saveXml() and loadXml() methods fully functioning, and as seen in my previous post, I’ve already got the makings of a TorqueScript-based object/level loader.
TorqueScript XML Object Loads
I’ve managed to get the XMLObject to a fairly useable point, so far, the following script, is useable:
[js]
function sceneObjectParser::onElementStart(%this, %name, %atts)
{
switch$(%name)
{
case “objects”: %this.objectBlock = true;
default:
if(%this.objectBlock)
{
%obj = new (%name)()
{
class = getAttribute(%atts, “class”);
superClass = getAttribute(%atts, “superClass”);
};
%obj.dump();
}
}
}
function sceneObjectParser::onElementEnd(%this, %name)
{
switch$(%name)
{
case “objects”: %this.objectBlock = false;
}
}
function sceneObjectParser::onCharacterData(%this, %name, %data, %len)
{
echo(“CDATA: —” @ %name @ ” – ” @ %data @ “—”);
}
function getAttribute(%atts, %name)
{
for(%x = 0; %x < %atts.getCount(); %x++)
{
if(%atts.getObject(%x).AttributeName $= %name) return %atts.getObject(%x).AttributeValue;
}
return "";
}
$xml = new XMLObject() { class = "sceneObjectParser"; objectBlock = false; };
$xml.parseDocument("XMLTestFile.xml");
[/js]
This will actually create instances of the objects identified by the xml elements inside of an "objects" node, for example, the following XML document was parsed for testing;
[xml]
[/xml]
I’ve not yet thoroughly tested it, but once I find a useful and reusable XML format for Objects and Levels, I’ll start working on the saveXml and loadXml functions respectively, and add them as either ConsoleFunctions which take in any SimObject, or add them as addon functions to the base SimObject within the XMLObject.cc itself (little to no engine code should need to be updated for this resource to work effectively)
TorqueScript XMLObject
I have started working on an implementation of Expat (the Gnome XML Parser) library into TGB, and expect that a large portion of the code should work with TGE as well, as it’s just a simple Console Object being added to the system.
So far, I’ve managed to create and expose the XMLObject class to TorqueScript, as well as added a ‘parseDocument’ method to the object, which is exposed to TorqueScript and takes in a Filename as it’s only parameter. This then makes numerous calls to the startElement and endElement C++ methods (there’s a static and non-static version of each, something to do with the function pointers that expat uses since its written in C). These C++ methods then call there TorqueScript equivalents, onStartElement and onEndElement, which allows a script developer to very simply use the SAX parser functionality of Expat within TorqueScript by doing the following:
[js]
function MySax::onStartElement(%this, %name, %atts)
{
echo(“ElementStart: ” @ %name);
for(%x = 0; %x < %atts.getCount(); %x++)
{
echo(” Name: ” @ %atts.getObject(%x).AttributeName);
echo(” Value: ” @ %atts.getObject(%x).AttributeValue);
}
}
function MySax::onElementEnd(%this, %name)
{
echo(“TS ElementEnd: ” @ %name);
}
%sax = new XMLObject()
{
class = “MySax”;
};
%sax.parseDocument(“XMLFile.xml”);
[/js]
I am intending to release the XMLObject code, along with any other TGB engine hacks I make that use the code, as a resource on GG’s site. I’ll post my progress here, and when I get a more completed version, I’ll post a .plan on GG’s site.
So far, all I’ve managed to cover is the Start and End element handlers, and the CDATA handler for the XML, my plans include to add the following:
- SimObject.saveXml() — save SimObjects as XML Files rather then TorqueScript
- SimObject.loadXml() — load SimObjects from XML Files, rather then exec()ing the TorqueScript
- Full list of SAX Methods, as made available through Expat
- Possibility of adding a DOM to the Code (Adding a DOM may require using yet another library, other then SAX, or a replacement to SAX that supports DOM — but I’m going to take a look at implementing a very simple DOM using my own code, and my own XPath implementation — just cause I wanna see how hard it’ll be to do ;p)


