Sanctimonia Updates: Client progress, coder needed

[singlepic id=566 w=320 h=120 float=center]

The Sanctimonia rendering environment

Kevin Fishburne dropped me an email to let us know that work on his Ultima-inspired project Sanctimonia is continuing at a fairly brisk pace. He has made huge strides in developing the game’s client over the last while:

Recent work on the game has included reworking the networking code to allow the server to independently keep track of all client transactions as well as its own. The clients also keep track of their transactions as well as the server’s…It was a little painful but thankfully works now.

…The client also now receives a 3×3 grid of map data from the server, each grid cell being 32×32 tiles or 32×32 feet in size. The tile data is loaded directly from Littoral-produced data files and includes the various layers of bedrock, sand, soil, vegetation and snow depth. The client’s rendering module interprets these layers and depths accordingly (currently using GIMP remixes of old Ultima V tiles; this is temporary).

The map in the screenshot [Seen above-right — WtFD] was created in Littoral and is a 1024×1024 tile representation of Britannia. The client and server now automatically support varying map sizes from Littoral based on the square root of the data file size, but the smaller maps are easier for debugging visually. The final map will be 65536×65536 tiles, or 12×12 miles, which while supported by Littoral takes about 24 hours to generate. Though it’s hard to see, the client is receiving and rendering each of the five separate landscape layers (bedrock, sand, soil, vegetation and snow). Not only are there five layers to the landscape, but every tile of each of these layers has a varying thickness/density.

Unfortunately, not all is roses with the project. Currently, Kevin is looking for some help backporting a specific graphics function, which will be essential to his final plan for terrain rendering:

[I am in need of a] C or C++ programmer that could devote about one hour of their time to the project. I need a single method from GAMBAS 3 (Image.DrawAlpha) to be backported to GAMBAS 2. Benoît Minisini, the lead dev of GAMBAS, was kind enough to write the graphics function for me for Sanctimonia, but he wrote it for GAMBAS 3 which is still in alpha and is terribly unstable. I’ve asked repeatedly in the GAMBAS dev mailing list for it to be backported, even offering a $50 bounty, but no one’s taken me up on it. That graphic function is critical to Sanctimonia’s client rendering engine.

If I can get that function backported there will be eight “megatextures” per landscape layer, each representing a different thickness/density of that particular layer. Small interconnective alpha tiles will be copied (Image.DrawAlpha) to each megatexture for each layer to make them mesh and overlap appropriately depending on the layer. When finished it will look incredibly organic and detailed, but because it’s completely dynamic it will be more than just eye-candy. Players walking over vegetation tiles, for example, will reduce their density by a unit. Once the threshold has been crossed (32 units per megatexture) the “lower” megatexture will be exposed for those tiles. Likewise the vegetation layer tiles will naturally increase in density over time. This will cause dirt paths to be exposed as the vegetation is repeatedly trampled or harvested. I’m going for the most realistic and interactive landscape ever created for a game, and so far so good.

It sounds ambitious, to say the very least! That is a level of detail that I don’t think has yet been seen in a game, and I for one would very much like to see it happen.

* [download id=”561″]

I’ve bundled the dependency and installation files that Kevin sent me into a single ZIP, which is presented here for download. If anyone wants to take a stab at backporting the function Kevin requires, please do so, and then let me know; I will pass the results of your hard work along to Kevin for use in his project.

18 Responses

  1. Thank you so much Ken for helping out with the game. I really appreciate it and am happy that such a forum exists for Ultima fans carrying the torch onward.

    I’ve echoed my request and this article here:

    http://www.eightvirtues.com/sanctimonia/journal.html

    I’d also like to add that the $50 bounty is yet unclaimed. The journal entry outlines the code that needs to be backported, as well as the file names that contain the method. It also provides the full source code (files) for GAMBAS 2 and 3 and the scripts to get it running.

    I can test the method to see if it actually works; I only need the code submissions. I will integrate the changes and compile/run the code myself for verification. All help is appreciated, and the one who helps me get it to work gets $50 by the method of their choice.

  2. While it may seem sad that one person continually responds to, essentially, their own post, I’d like to give a gift to those who took the time to read this and who enjoy old game music.

    http://www.eightvirtues.com/mt-32/

    This is an oft-updated repo of MT-32 music that I record and mix as I like. I hope you find it enjoyable, programmer or no. The Ultima VI and VII music, while not yet added, is especially pretty on an MT-32. The soundtrack to Wing Commaner and WC II is also pretty awesome.

  3. Fearyourself says:

    Hey,

    Last night, I saw this post and was reading about gambas on the way home. Though interesting I’m surprised you used that technology.

    Anyway, reading up about it and looking at your posts with the developers I downloaded and installed the 2 to start looking at how it is coded. It is a complex code which will likely take more than an hour to do your port but I don’t think it is impossible.

    I can’t promise anything, having a job, a life, my own ultima port in the works but I’ll give it a shot if you like. However, the simplest is to meet up on a irc channel (WTF: get the hint? ;-)) so that you can walk me through launching your code example, explaining what you need etc.

    Jc

    Ps: keep your 50$ btw, give it to charity in my name or to wtf for his website. Buy me a drink one day if we get it done 😉

  4. @FEARYOURSELF (Jc):

    Awesome, you’re the first person to tell me something other than, “Use GAMBAS 3.” I appreciate the ability to compile and run alpha software under Linux, but damn, for an actual project to be developed under alpha software that is still, well, highly alpha, isn’t really a solution.

    The reason I chose GAMBAS to develop a game in, despite it’s relative obscurity and lack of a native Windows or Mac OS version, is primarily because it (1) is an awesome and powerful language with a slick, robust IDE, and (2) I’ve been programming in various dialects of BASIC since I was 13 (22 years this month). It wouldn’t be possible for me to pull off a feat of this caliber using a language I wasn’t comfortable with.

    GAMBAS essentially is what VB 6 programmers ruined their sheets over in their deepest REM sleep. It’s everything that VB should have been but never was. Easy, powerful, extensible, object-oriented and open source.

    I plan on distributing the game for Windows and Mac OS using something like andLinux (http://www.andlinux.org/), so it won’t really be a niche game in that respect hopefully. I’ll also supply VirtualBox VM’s that are ready-to-run. If it gets big and someone wants to throw some money at it I’ll oversee it being ported to C/C++ and OpenGL so it will run on the major consoles (I’m getting ahead of myself now).

    Let me know if you have any insight into the code/method analysis. I noticed the code structure for GAMBAS 2 is different than that of GAMBAS 3, so comparing the Image.DrawAlpha and Image.Draw methods in gb3 to the Image.Draw method in gb2 made my head spin a bit, not being familar with C or the GAMBAS code base.

    I can throw together a simple example project using the method and send it to you if you like. It could use the Image.Draw method so that it works under gb2, and changing “someimage.Draw” to “someimage.DrawAlpha” would test the backported method. A basic description of the method’s effect would be to punch a transparent hole in the target texture by overwriting it’s alpha channel using the alpha channel of the source image. Instead of bit-blitting the RGB channels or RGBA channels, it would bit-blit just the A channel.

    You can reach me directly at kevinfishburne at eightvirtues dot com [phone number removed; everyone who needs it probably already has it by now. — WtFD] if need be. If I can get this method working, I’ll donate $50 to any organization you like outside of Al-Qaeda, and the beer will flow like Niagara. 😉

  5. @FEARYOURSELF (Jc):

    Forgot to ask… What’s the story with your Ultima port? I still love the originals and play them occasionally in DOSbox. IV, V, VI and VII are pure awesome. My first free hit was III for the NES after fooling around with the original Dragon Warrior and Final Fantasy. Imagine what I thought the first time I played IV for IBM PC. Gaming really opened up for me at that point.

  6. wtf_dragon says:

    GAMBAS, you say?

    I’m a VB6 guy from way back; still use the language occasionally. It’s messy and inefficient, but when I need to slam together an app that will run on any flavour of Windows (which happens from time to time), it’s perfect. NT4 through to Win7; it’ll run, every time, on even a vanilla install.

    So I might just have to give this GAMBAS stuff a learnin’.

  7. In the words of the Unreal Tournament announcer, GAMBAS is wicked sick. The docs are reasonably well thought out and are here:

    http://gambasdoc.org/help/lang

    It’s component based and you can check/select which components any given project uses in the IDE. The component breakdown with references is here:

    http://gambasdoc.org/help/comp

    gb.image is what I’m using for the graphics and is the component I’ve requested the DrawAlpha method to be backported to:

    http://gambasdoc.org/help/comp/gb.image/image

    I’m also using SDL for the audio, as afforded by this component:

    http://gambasdoc.org/help/comp/gb.sdl.sound

  8. Fearyourself says:

    First: you should (or WTF should) take down your phone number. No need to get spammed ;-). Sadly I’m back in good ol’ Europe right now so calling is not really an option.

    Anyhow, I dabbled myself in VB at the same age you did. But I got frustrated and wanted to do C. Being a kid without internet, I had to wait a bit (give or take six years ;-)).

    About my port: much less ambitious than yours. I started a game engine in C++/OpenGL/SDL that was ultima like. I found a sprite sheet from ultima 5 and played with that. Fast forward the summer and autumn, I got to the point where my engine was getting there but I didn’t have the courage to write a story, create cities, etc.

    So I’m now integrating the U4 data and making it run there. I’ve got all the cities decoded and am using the original sprites up (though I added a feature that allows you to go between the VGA and ega versions at runtime). Most of the conversations are up, stores, etc.

    I haven’t decided how faithful I’ll remain but it’s a lot of fun. For those who wonder: yes xu4 works and is awesome. I just am having fun. Where am I going: once cities and world map are handled for U4, I will stop the U4 integration and start the U5 integration. Why?

    I’ve separated the engine from any real U4 specificity but I want to make sure it is the case. After that I will hit the dungeon handling etc. Combat and AI is already in the engine so I won’t have too much work.

    And there I went and rambled off.

    Kevin: I’ll send you where I hang out and if you want we can meet up there and I can explain what I need from you to try to help out, ok?

    • wtf_dragon says:

      Fearyourself: By any chance, is your project online somewhere? Do I have it on the site under a different name?

      If not…did you want to put it online?

  9. fearyourself says:

    WTF: no actually it wasn’t. When I started getting a strong enough engine, I went looking for Ultima related forums and such and found Dino’s page and contacted him. We talked about it and I have the issue and sentiment that it is a bit of a YAUP (Yet Another Ultima Port), and I’m not sure what really makes it special (or will make it any better than previous ones).

    For the moment, I’m having a good time and making it move forward relatively well and quickly, it would be nice to put it up here if you think it’s worth at all mentioning.

    But here goes, I’ll let you judge for yourself : http://backtoroots.sourceforge.net/

    Jc

  10. wtf_dragon says:

    Of course it’s worth mentioning. There will be a project entry by the end of the day! Now I just need to pick a screenshot.

    BTW, it does look pretty darn good; you seem to be having a lot of fun and doing some interesting things with the engine, which is nice to see.

  11. Check out this guy in the GAMBAS dev mailing list. I had to make my best effort to rip him a new one:

    http://old.nabble.com/$50-bounty-for-backporting-a-gb3-method-to-gb2-tree-td29940630.html#a30146639

    Jeeze… Reminds me of the flame wars of old, though hopefully shorter. I have better things to do despite my tendency to rant.

  12. All -is- now roses. The method has been backported and works:

    http://www.eightvirtues.com/sanctimonia/journal.html

    I know I sound like Steven Wright (or Monty Python), but I am extremely happy. This is awesome, and thank you for helping me. Hopefully soon I can have a screenshot demonstrating the new method’s proper implementation.

  13. fearyourself says:

    Ok, continuing the discussion here (sorry Wtf). If you don’t care about that wrap around, here is a version that crops it. Notice that if (x,y) is negative, I set it simply to 0 but we do crop if the source goes over the destination.

    This will be faster than the previous method because we won’t have the % in it.

    The day you are looking for speed, there are a couple of things you might care about changing but normally this function should not be called in your rendering but as a pre-rendering or side-rendering because :

    – You should render your tiles before hand and use them pre-generated during the rendering.
    – Keeping a map style system should be easy anyway and is how we normally do things.

    But you surely know that anyway,
    Good luck with your project, I can’t wait to see it work out.
    Jc

    BEGIN_METHOD(CIMAGE_drawAlpha, GB_OBJECT img; GB_INTEGER x; GB_INTEGER y; GB_INTEGER sx; GB_INTEGER sy; GB_INTEGER sw; GB_INTEGER sh)
    int x, y, sx, sy, sw, sh;
    int i, j;
    QImage dest (THIS);
    QImage src (VARG(img));

    x = VARGOPT (x, 0);
    y = VARGOPT (y, 0);

    sx = VARGOPT (sx, 0);
    sy = VARGOPT (sy, 0);
    sw = VARGOPT (sw, src.width ());
    sh = VARGOPT (sh, src.height ());

    int dest_width = dest.width ();
    int dest_height = dest.height ();
    int destI, destJ;

    //Let’s crop it
    if (x < 0)
    x = 0;
    if (y dest_width)
    sw = dest_width – x;
    if (y + sh > dest_height)
    sh = dest_height – y;

    for (i = 0; i < sh; i++)
    {
    for (j = 0; j < sw; j++)
    {
    destI = y + i;
    destJ = x + j;

    //Get color
    QRgb baseColor = dest.pixel (destJ, destI);

    //Now separate them
    int r = qRed (baseColor);
    int g = qGreen (baseColor);
    int b = qBlue (baseColor);

    //Now get alpha of src
    baseColor = src.pixel (j + sx, i + sy);
    int a = qAlpha (baseColor);

    QRgb color = qRgba (r, g, b, a);

    dest.setPixel (destJ, destI, color);
    }
    }
    END_METHOD

  14. Awesome, thanks. I’ll do a benchmark on both to decide which to use and add the revised version to my site journal.

    The method will have to be used in real time due to the way the landscape textures are incorporated. While most games use small, seamless tiles that are repeated (Ultima/DQ/FF), Sanctimonia will use much larger textures that cover multiple tiles. Each sub layer texture is going to be tileable and either 2048×2048 or 4096×4096 pixels (haven’t decided yet), but the tiles are only 128×128 pixels. These large textures are then modified by the nine smaller alpha tiles to expose the underlying layers and give their edges a natural look. Prerending the different alpha combinations for a single sub layer’s texture at 2048×2048 pixels would produce 2048 tiles: (2048 / 128)^2 * 8. The ninth alpha tile is pure alpha, so there’d only be one version for all the sub layer textures. Multiplying that by five (the number of layers) and eight (the number of sub layer textures per layer) would produce 81920 tiles…madness. 😉

    The good news is that as a player is walking around the map only the “new” tiles will be rendered with DrawAlpha. Those that have already been rendered will just be shifted over a tile in the buffer to make room for the new ones. It should be fast enough to not create a stutter/pause every time the player crosses into a new tile.