![]() |
|||||||||
|
|||||||||
| Journal Client Rendering Engine Rewritten
February 7, 2011
C/C++ Method Backport Granted
November 7, 2010 An Ultima Aiera contributor has heeded the call to arms and backported the DrawAlpha method from the gb.image component of GAMBAS 3 to GAMBAS 2. After applying the patch and recompiling GAMBAS 2 the test app worked as I'd hoped. The addition to GAMBAS hasn't yet been submitted upstream since it is a backport, but will be upon request. It is available here, however: Index: gb.image/src/CImage.cpp
=================================================================== --- gb.image/src/CImage.cpp (revision 3275) +++ gb.image/src/CImage.cpp (working copy) @@ -324,7 +324,59 @@ END_METHOD +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 ()); + + if (sw + sx > src.width ()) + sw = src.width () - sx; + + if (sh + sy > src.height ()) + sh = src.height () - sy; + + int dest_width = dest.width (); + int dest_height = dest.height (); + int destI, destJ; + for (i = 0; i < sh; i++) + { + for (j = 0; j < sw; j++) + { + //Calculate destination + destJ = x + j; + destJ %= dest_width; + destI = y + i; + destI %= dest_height; + + //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 + + GB_DESC CImageDesc[] = { GB_DECLARE("Image", 0), @@ -377,6 +429,7 @@ GB_METHOD("Wave", "Image", CIMAGE_wave, "[(Amplitude)f(WaveLength)f(Background)i]"), GB_METHOD("Noise", "Image", CIMAGE_noise, "(Noise)i"), GB_METHOD("Implode", "Image", CIMAGE_implode, "[(Factor)f(Background)i]"), + GB_METHOD("DrawAlpha", NULL, CIMAGE_drawAlpha, "(Image)Image;(X)i(Y)i[(SrcX)i(SrcY)i(SrcWidth)i(SrcHeight)i]"), GB_END_DECLARE }; The command to execute the patch is something like: patch ./gb.image/src/CImage.cpp ./patch_drawalpha
Below is the result of the test app properly exposing the sand layer underneath the vegetation layer. It compiled and ran without error on two different systems. It shows a simple test with a 4x4 grid of tiles, each tile being 128x128 pixels. The surrounding ten tiles used a fully-transparent interconnective alpha tile. The four center tiles used four partially-transparent interconnective alpha tiles. While this is a simple demonstration, ultimately the seamless dynamic layering will produce stunning real-time results. ![]() This is probably the most important bit of news that will ever exist regarding the progress and power of Sanctimonia's client rendering engine. This enables, as I poorly attempted to describe earlier: Everything in the client landscape data arrays and graphics
rendering breaks down nicely into predictable tiles of 128x128 pixels.
While a polished, "release ready" method would probably include clipping
and such, in our case it isn't needed as no DrawAlpha blits will fall
outside the range of the target images. I'm guessing that adding
clipping or anything else would probably slow the routine down, so fast
and dirty is probably preferable in this case. Especially because it's
software rendering. Frame rate is one of my primary concerns at this
point and it'll require a lot of tweaking on my part to keep it around
30 fps.
As far as how Sanctimonia will render a scene, the client knows of a 3x3 "cell" grid of landscape data (nine cells). Each cell is 32x32 tiles. Each tile is 128x128 pixels. When the player starts the game, the server sends the player the landscape data for the five layers for the 3x3 cell grid. Each tile of each of the layers is one byte, the values (0-255) representing the depth or density of the tile for the layer. The client stores this landscape data in five arrays. Initially the entire screen must be rendered, so the client renders the visible subset of the grid (variable based on zoom level). As the player moves around the map, only the new tiles will be rendered. The existing on-screen tiles will be shifted to make room for the new. A "camera" will keep track of which part of the small buffer to render to the DrawingArea so it appears as though smooth scrolling is occurring. Each landscape layer has eight "sub" layers with a different variation of the texture. The vegetation layer for example will look like: Tile Depth/Density Texture File Name 000-031 vegetation_0.png 032-063 vegetation_1.png 064-095 vegetation_2.png 096-127 vegetation_3.png 128-159 vegetation_4.png 160-191 vegetation_5.png 192-223 vegetation_6.png 224-255 vegetation_7.png These sub layers will be individually modified by DrawAlpha using an algorithm that examines the adjacent tiles and the sub layer range that they fall in to. The algorithm will make each sub layer seamless, choosing the appropriate interconnecting tile based on its neighboring tiles. After each sub layer has been modified, the next layer will undergo the same treatment. When all the sub layers for each of the five main layers have been made seamless with DrawAlpha, they'll all be combined, stacked like a pancake, and sent to the main rendering pipeline. Things like water, fog, rain, etc., will be added per frame on top of the final landscape texture. The next order of business is integrating the method into the client rendering engine and allowing proper movement and scrolling. C/C++ Method Backport Requested
November 3, 2010 Sanctimonia needs a single method from the gb.image library backported from GAMBAS 3 to GAMBAS 2. This method is critical to the further development of the client rendering engine. I'd use GAMBAS 3 but it is still in alpha and is entirely too unstable at this time to develop Sanctimonia with it. Ultimately Sanctimonia will be ported to GAMBAS 3, but the game cannot wait. The method is called Image.DrawAlpha (Image_DrawAlpha) and is in the file 3.0.x/trunk/main/lib/image/CImage.c. There are some other files associated with the method, detailed below. The source files, dependency and GAMBAS installation scripts for GAMBAS 2 and GAMBAS 3 are located here. While these scripts may work on other distributions, they are designed for Ubuntu 10.04 (Lucid Lynx). If you are a Windows user you may easily install Lucid in VirtualBox. I am not a C or C++ programmer, but I believe these are the GAMBAS 3 source files and code exerpts that need to be backported to enable this method in GAMBAS 2: 3.0.x/trunk/main/lib/image/CImage.c BEGIN_METHOD(Image_DrawAlpha,
GB_OBJECT image; GB_INTEGER x; GB_INTEGER y; GB_INTEGER srcx;
GB_INTEGER srcy; GB_INTEGER srcw; GB_INTEGER srch)
CIMAGE *image = VARG(image); if (GB.CheckObject(image)) return; IMAGE_draw_alpha(THIS_IMAGE, VARGOPT(x, 0), VARGOPT(y, 0), &image->image, VARGOPT(srcx, 0), VARGOPT(srcy, 0), VARGOPT(srcw, -1), VARGOPT(srch, -1)); GB.ReturnObject(THIS); END_METHOD 3.0.x/trunk/main/lib/image/image.h void IMAGE_draw_alpha(GB_IMG *dst, int dx, int dy, GB_IMG *src, int sx, int sy, int sw, int sh);
The comparable function in GAMBAS that Image.DrawAlpha is based upon is Image.Draw, which copies a rectangular portion of one image to another and includes all four channels (red, green, blue and alpha). The Image.DrawAlpha method however only copies the alpha channel of an image to another. For specific questions about this method and how it is integrated into the GAMBAS 3 code base, please refer questions to me or, more directly, to the GAMBAS dev mailing list here. Benoît Minisini is the lead developer of GAMBAS. If you'd like to know why this method is of such importance, please see the following article about its imminent implementation: http://www.ultimaaiera.com/blog/sanctimonia-updates-client-progress-coder-needed/ The programmer who is successful will be rewarded greatly, and I sincerely appreciate any time or effort expended in making this possible. Tentative Title Sequence Penned
September 10th, 2010 An initial introductory sequence has been created in code and finely tuned. The theme borrows heavily from the dramatic intro of Silpheed for DOS and MT-32 by Game Arts. The famous quote, "How many ages hence..." from Shakespeare's Julius Caesar is ironically as appropriate for Sanctimonia's themes as it was for Silpheed's, despite being worlds apart in most every respect. Here it is saved frame-by-frame in code (h264, 1280x720 or 720p): Decent Quality and here it is saved by YouTube's transcoders: YouTube Quality Gamepad Input Cornered, Allowing Taps and Holds
September 7th, 2010 Per-button/axis gamepad input is accepted and interpreted with respect to the previous corresponding input, meaning button "taps" and "holds" are differentiated, enabling two actions per button. This has enabled the current default control scheme, which is as follows: Button Action Result Start any main menu Select any toggle spectator/interactive modes D-Pad any cardinal/traditional player movement Left Analog any player movement/strafing Right Analog any player orientation/rotation 1 ? ? 2 any jump/okay 3 ? ? 4 ? ? L1 tap use object in left hand L1 hold use left hand R1 tap use object in right hand R1 hold use right hand L2 tap pick up object with left hand L2 hold drop object in left hand R2 tap pick up object with right hand R2 hold drop object in right hand L3 tap unequip object in left hand or re-equip object previously in left hand L3 hold inventory menu to select object to equip in left hand R3 tap unequip object in right hand or re-equip object previously in right hand R3 hold inventory menu to select object to equip in right hand Using the four shoulder buttons (L1, L2, R1, R2) with taps and holds creates eight commands exclusively for a player's arms and hands. This will allow players to quickly pick up or drop objects with a specific hand, move objects from one place to another, carefully arrange objects and will increase the detail level of combat. For example, a player may attack another player, knock the weapon out of their hand, pick up their weapon with their free hand, then continue to attack them using both weapons with independent control for the right and left hands. Tapping R1 will attack using the weapon in the player's right hand, while holding R1 will punch them while still gripping the weapon. Another example would be a player with a flaming oil flask in their hand. Tapping the button for that hand will use/throw the flaming oil but holding the button will punch with the oil still in hand, effectively burning the opponent and the player upon impact. This should make for fast and chaotic combat depending on the weapons and players involved. Littoral Generates Usable World Data, Client-Server Coding to Resume September 1st, 2010Littoral, the procedural world generator for Sanctimonia, is now able to generate usable data files for the server and client modules. The elevation (bedrock layer) and tile (sand, soil, vegetation and snow layers) data files may be created from an elevation template image to create world maps ranging from 1024x1024 to 65536x65536 units. Smaller maps take less than a minute to generate and larger maps take about 24 hours on a 3 GHz 64-bit CPU running Ubuntu 10.04. Sanctimonia will ultimately be using a 65536x65536 vertex map, which at one square foot per vertex amounts to a 12x12 mile world. While work still needs to be performed on Littoral for truly outstanding results, intense coding is commencing tonight on the client-server application now that viable landscape data files are available. Since the basic client-server networking code is finished, priority one is to create the client input and rendering engine that will make Sanctimonia playable. For the time being tile graphics from Ultima IV will be used to represent the various landscape features, both to save time and for my own amusement. Ultimately high-resolution "mega-textures" will be used for each landscape layer, blended seamlessly using a GAMBAS function created by Benoît Minisini to bit-blit only the alpha channel of an image. I still consider Littoral to be in an alpha state, although it is completely usable for various game projects that require a vertex- (3D) or tile-based (2D) landscape. In the spirit of open source software I'm releasing it in its early state here. All feedback and possible code improvements are greatly appreciated. To run Littoral you will need to use GAMBAS 2, available in the Ubuntu software repositories or by running the following script in a terminal in Ubuntu 10.04: sudo apt-get install build-essential autoconf libbz2-dev libfbclient2 libmysqlclient15-dev unixodbc-dev libpq-dev libsqlite0-dev libsqlite3-dev libgtk2.0-dev libldap2-dev libcurl4-gnutls-dev libgtkglext1-dev libpcre3-dev libsdl-sound1.2-dev libsdl-mixer1.2-dev libsdl-image1.2-dev libsage-dev libxml2-dev libxslt1-dev libbonobo2-dev libcos4-dev libomniorb4-dev librsvg2-dev libpoppler-dev libpoppler-glib-dev libasound2-dev libesd0-dev libesd-alsa0 libdirectfb-dev libaa1-dev libxtst-dev libffi-dev kdelibs4-dev firebird2.1-dev libqt4-dev libglew1.5-dev libimlib2-dev libv4l-dev libsdl-ttf2.0-dev mkdir 2.0 svn checkout https://gambas.svn.sourceforge.net/svnroot/gambas/gambas/branches/2.0 cd 2.0 ./reconf-all ./configure make sudo make install gambas2 Littoral, First Release (source tarball) Littoral, First Release (Ubuntu .deb package) Littoral, First Release (GAMBAS2 executable) Here are some screenshots (minus window decoration) to give you an idea of what Littoral currently does. Elevation
template created in The GIMP from the Ultima V cloth and game maps,
used by Littoral to generate both elevation data using the
Diamond-Square algorithm and the tile data for surface type coverage ![]() Completed rendering of
the elevation template from the previous image along with an
elevation-based preview of the four tile layers ![]() Test elevation template ![]() Rendered preview of the test elevation template ![]() All the options in the screenshots with the exception of the "Persistent World Objects" tab are usable and contain no significant bugs. Chris "Absynth" Waugh to Score Sanctimonia Soundtrack July 4th, 2010Drum and bass composer and DJ Chris Waugh, known to his fans as Absynth, has already begun work on the Sanctimonia soundtrack. Combining traditional eastern and western instrumentation with cutting edge electronic sounds Chris is creating a unique blend of the ancient and the modern. Here are a few examples of early works-in-progress being composed for Sanctimonia: How to Contribute if Strapped for Cash June 24th, 2010While pledges are the bread and butter that will allow Sanctimonia to be completed in a timely manner, you can also help greatly by simply spreading the word. Here are some ways you can help without having to dip into your purse:
Thanks so much to everyone for their support and encouragement, and keep up the great work. Thoughts on Allowing Total Freedom in an Online World June 22nd, 2010This is an excerpt from a reply to a backer, Toops of www.geeks.co.uk: Communication is one of the key elements of Sanctimonia, largely because it can be expressed more than just verbally. The idea is to put in place very simple sets of game mechanics, both social and physical, that ultimately allow the same basic freedoms and self-imposed restrictions people have in real life. Once those basic building blocks of player freedom and interaction are discovered they can be used by individuals or groups to facilitate the more complex systems of human behavior and creative endeavors. Sanctimonia's gameplay is being designed from the bottom up rather than the top down. A big mistake I think a lot of developers make is doing the opposite. They think first of story, genre, graphics or levels and work their way down to the gameplay specifics. That kind of top down thinking ends up constraining the gameplay within the confines of the initial concept and gives us things like "invisible walls", instantiated quests and game rules that don't make sense within the game world but only exist to curb griefing or other undesirable gameplay. As in real life, the dark side of total freedom may be mitigated in two ways: First constrain players to the physical realities of being human. If a human must eat, drink, use the bathroom and sleep then they need to work and find reliable shelter or they will die. That leaves less time to do things like wait around for new players and repeatedly kill them or perform random acts of vandalism and theft. Humans also can't reach level 50 and crush stones between their pectorals, which means picking a fight even with a new player may get you killed if he picks up a shovel and is good with a gamepad. Second allow the same social developments that prevent bad behavior in real life. We all have the freedom to go out and steal, assault or kill other people, yet we're constrained by our conscience and the fear of punishment if caught. The sense of accomplishment players will feel working together to raise livestock, tend farms and build their homes will create a sense of community. That community will then naturally want to protect itself from outsiders with bad intentions and will take advantage of the ability to pass, post and enforce laws. One example would be to build a wall around the village, post guards at the entrances and require all those entering to leave their weapons in a guard tower before entering. Any unarmed griefer who started trouble would quickly be knocked unconscious by the townspeople and placed in custody, exiled or worse. All without invisible walls or restricted PVP. ;) |
|||||||||
© 2011 Eight Virtues |