If you've ever tried to get attention in the gaming world, you know how well-neigh impossible it is. There are literally tens of thousands of game developers of every budget category, from the smallest single-person outfits to kings like Blizzard and CCP. Even getting someone to review your game can sometimes be a lost cause.
With that as a backdrop, Alter Aeon this weekend got a spontaneous review on the GamingHUD web site. This is a pretty big website that reviews a lot of mainstream games. For AA to even be seen by fish of this size is pretty amazing.
The review also isn't some slapdash piece of filler material. The reviewer spent a lot of time on the game and even emailed me for additional information. The final article came out very positive and very long.
The link is:
Alter Aeon MUD - A World of Infinite Possibilities
Feel free to check it out and maybe drop a thank you to the author for their hard work.
Wednesday, July 13, 2011
Saturday, July 9, 2011
wxWidgets GTK font rendering
In my previous post, I managed to fix the bugs in wxDC::DrawPoint() by using my own custom drawing class. Unfortunately, a lot of the places I where I used DrawPoint were also places where I needed to draw text, and in order to draw text I needed a wxDC. No problem, I'll just draw the text using a temporary wxMemoryDC on the bitmap, and to make sure there's no clobbering problems I'll make sure that I don't intermingle direct drawing scope with the DC object scope.
This appeared to work, except for the scrolling/updating windows. For some reason, even though there was a Clear() call before the font rendering, the windows would never clear. If I destroyed and recreated the bitmap every time, it worked fine but was very slow. If I cleared after drawing the text, the clear worked. If I cleared before drawing the text, the clear did not work.
Eventually I figured out the reason:
Under wxGTK, wxDC drawing and rendering are done to a separate bitmap/bitmap layer that is permanently attached to the real bitmap. When font data is drawn using wxDC::DrawText(), the text is drawn to the hidden layer, then the hidden layer is blitted in its entirety on top of the real bitmap. The end result is that anything you do prior to constructing the DC and rendering text with that DC is overwritten/deleted when the DC destructs.
Just how the hell does this make any sense? Nevermind, forget I asked. On the plus side, this explains why full screen font rendering is so slow in wxGTK. I never could figure that part of it out.
For roughly a day, I was utterly at a loss when faced with this problem. Switch back to the old code and lose the MacOS X platform; stay with the new code and lose wxGTK (and possibly other platforms, I only ever tested it on GTK.) I couldn't even think of a way to work around it.
Eventually, a possible solution presented itself: add font rendering to my custom bitmap class. I wasn't real clear on how to do this at first, but the key breakthrough came when I realized I could just use a cheap glyph rendering scheme. Use wxDC to draw each of the letters I needed (ascii chars 32 through 126) into tiny, clean bitmaps, then use a modified alpha channel copy routine to draw them to my custom bitmaps.
I'm proud to say that I now have proper text rendering and graphical drawing primitives on all three platforms. And to think that all I needed to do was rewrite the entire wxDC rendering system to do it!
I should have just done it in the first place, as I recommended to myself in a past life. Sometimes our older selves are no wiser than we are in youth.
This appeared to work, except for the scrolling/updating windows. For some reason, even though there was a Clear() call before the font rendering, the windows would never clear. If I destroyed and recreated the bitmap every time, it worked fine but was very slow. If I cleared after drawing the text, the clear worked. If I cleared before drawing the text, the clear did not work.
Eventually I figured out the reason:
Under wxGTK, wxDC drawing and rendering are done to a separate bitmap/bitmap layer that is permanently attached to the real bitmap. When font data is drawn using wxDC::DrawText(), the text is drawn to the hidden layer, then the hidden layer is blitted in its entirety on top of the real bitmap. The end result is that anything you do prior to constructing the DC and rendering text with that DC is overwritten/deleted when the DC destructs.
Just how the hell does this make any sense? Nevermind, forget I asked. On the plus side, this explains why full screen font rendering is so slow in wxGTK. I never could figure that part of it out.
For roughly a day, I was utterly at a loss when faced with this problem. Switch back to the old code and lose the MacOS X platform; stay with the new code and lose wxGTK (and possibly other platforms, I only ever tested it on GTK.) I couldn't even think of a way to work around it.
Eventually, a possible solution presented itself: add font rendering to my custom bitmap class. I wasn't real clear on how to do this at first, but the key breakthrough came when I realized I could just use a cheap glyph rendering scheme. Use wxDC to draw each of the letters I needed (ascii chars 32 through 126) into tiny, clean bitmaps, then use a modified alpha channel copy routine to draw them to my custom bitmaps.
I'm proud to say that I now have proper text rendering and graphical drawing primitives on all three platforms. And to think that all I needed to do was rewrite the entire wxDC rendering system to do it!
I should have just done it in the first place, as I recommended to myself in a past life. Sometimes our older selves are no wiser than we are in youth.
Labels:
client,
software engineering,
toolkits,
wxwidgets sucks
wxDC DrawPoint broken under wxMAC
To follow up on my previous post, I had written my own routines for handling alpha channel support under wxWidgets, and finally everything seemed to be working properly. Both Win32 and Linux/GTK builds seemed to work exactly as expected using my alpha channel bitmaps where I needed them. For most other places, I still used wxDC primitives, as wxDC direct drawing seemed to be a bit faster than going through a bitmap/blit interface, and I still needed to use wxDC to render fonts.
I figured porting to MacOS X would be a snap, and for the most part it wasn't too bad. There were some issues with Repaint() not working the same, but adding a few explicit paint calls in the right place fixed that up.
However, something was wrong with some of the graphics in the various windows. The sky bar, normally with lots of little stars in it, still had stars in it, but instead of one pixel there were two: one at offset (0, 0), and one at offset (1, 1). I also noticed 'fuzz' on the corners of various windows and buttons, and in a handful of other locations.
Long story short, wxDC::DrawPoint() draws two pixels under wxMAC. Not one, but two. I found a couple bug reports regarding this from a few years ago, where it was basically acknowledged as a "verified bug", and the ticket was never closed. Advice was "these routines are slow and shouldn't be used for high performance drawing". Thanks guys.
I have some mighty fine choice words to say to the developers regarding this, but I'll try to keep this post on topic.
If something as fundamental as DrawPoint() is malfunctioning on a major development platform, I figured it would probably be a good idea to transition away from the classes that implement it in favor of my own drawing routines. So, I started using my bitmap class, which just happens to have a DrawPixel() function that works properly.
As expected, this fixed the drawing problems on all three platforms. But alas, using my bitmap class exposed another set of very nasty wx bugs, which I'll discuss in the next post.
I figured porting to MacOS X would be a snap, and for the most part it wasn't too bad. There were some issues with Repaint() not working the same, but adding a few explicit paint calls in the right place fixed that up.
However, something was wrong with some of the graphics in the various windows. The sky bar, normally with lots of little stars in it, still had stars in it, but instead of one pixel there were two: one at offset (0, 0), and one at offset (1, 1). I also noticed 'fuzz' on the corners of various windows and buttons, and in a handful of other locations.
Long story short, wxDC::DrawPoint() draws two pixels under wxMAC. Not one, but two. I found a couple bug reports regarding this from a few years ago, where it was basically acknowledged as a "verified bug", and the ticket was never closed. Advice was "these routines are slow and shouldn't be used for high performance drawing". Thanks guys.
I have some mighty fine choice words to say to the developers regarding this, but I'll try to keep this post on topic.
If something as fundamental as DrawPoint() is malfunctioning on a major development platform, I figured it would probably be a good idea to transition away from the classes that implement it in favor of my own drawing routines. So, I started using my bitmap class, which just happens to have a DrawPixel() function that works properly.
As expected, this fixed the drawing problems on all three platforms. But alas, using my bitmap class exposed another set of very nasty wx bugs, which I'll discuss in the next post.
Labels:
bugs,
software engineering,
toolkits,
wxwidgets sucks
wxwidgets has no alpha channel
A few months after I ported the Alter Aeon client to the wxWidgets toolkit, I decided I wanted to add alpha overlay support to the automap and main window.
Encouragingly enough, this appeared to be trivially supported: wxColor included an alpha value, bitmaps could be defined as having an alpha channel, etc. Pretty much everything looked good to go, so I started experimenting with it.
Alas, it was not to be. It turns out that there are precisely three places where the alpha channel is used:
1) loading a PNG from PNG data that has an alpha channel,
2) drawing a bitmap containing alpha channel data using wxDC::DrawBitmap, and
3) wxDC::DrawText, which politely draws text on top of the underlying pixels.
For all other locations, there simply should have been this assert:
wxASSERT("Alpha channel is stubbed here and works on precisely zero platforms ever, ha ha, the joke is on you")
After upgrading to wx 2.9 and a pile of scouting around, I came across wx/rawbmp.h, which has some direct access functions that allow access to the alpha channel. With this, I managed to get alpha channel working - but there were other problems with 2.9, so I downgraded back to stable, 2.8.12.
The alpha channel code that worked under 2.9 works properly under wx 2.8.12 in wxMAC and wxGTK, but apparently isn't implemented under Win32, which happens to be my main development platform.
Rather than bash my skull repeatedly against the wall, I did what any sane developer would do: throw out the broken toolkit module, and write one that works. In the end, I ended up with a wxBitmap derived class that has drawing functions that actually work properly and support alpha channel drawing when I need them to.
However, there's a problem with this as well, which I'll detail in a later post.
Encouragingly enough, this appeared to be trivially supported: wxColor included an alpha value, bitmaps could be defined as having an alpha channel, etc. Pretty much everything looked good to go, so I started experimenting with it.
Alas, it was not to be. It turns out that there are precisely three places where the alpha channel is used:
1) loading a PNG from PNG data that has an alpha channel,
2) drawing a bitmap containing alpha channel data using wxDC::DrawBitmap, and
3) wxDC::DrawText, which politely draws text on top of the underlying pixels.
For all other locations, there simply should have been this assert:
wxASSERT("Alpha channel is stubbed here and works on precisely zero platforms ever, ha ha, the joke is on you")
After upgrading to wx 2.9 and a pile of scouting around, I came across wx/rawbmp.h, which has some direct access functions that allow access to the alpha channel. With this, I managed to get alpha channel working - but there were other problems with 2.9, so I downgraded back to stable, 2.8.12.
The alpha channel code that worked under 2.9 works properly under wx 2.8.12 in wxMAC and wxGTK, but apparently isn't implemented under Win32, which happens to be my main development platform.
Rather than bash my skull repeatedly against the wall, I did what any sane developer would do: throw out the broken toolkit module, and write one that works. In the end, I ended up with a wxBitmap derived class that has drawing functions that actually work properly and support alpha channel drawing when I need them to.
However, there's a problem with this as well, which I'll detail in a later post.
Labels:
client,
software engineering,
toolkits,
wxwidgets sucks
Friday, July 1, 2011
Future Plans - Clerics
The cleric class has long languished - not because it was useless, but because until recently there wasn't a lot of reason to have a really high cleric level. Prior to the 2010 christmas expansion, there weren't a lot of cleric spells or skills above level 30; and many cleric spells didn't scale in power as you gained levels, like mage and necromancer spells do.
As a result, cleric has been a useful, powerful class - but not something you want to be your primary. Our future update to cleric aims to change that.
The biggest updates to the class aren't likely to be new spells and skills. Rather, we want to fix existing spells and skills that aren't up to snuff with the rest of the class.
Take for example the 'peace' spell. This could be a very powerful, useful spell - if only it worked differently. We're currently imagining room effects, duration effects, and a handful of other options to improve this.
Another spell that's long been on the todo list is charm. The current version of charm has basically been dented into the ground to prevent charm armies. With this update, we're planning to switch it to a control point system similar to necromancers. This should make charm a lot more useful while at the same time limiting "charmy" problems.
Other things that could use similar kinds of improvement are turn undead, the ward spells, curses, and the monitor skill.
All this said, we do plan to add more spells and skills. So far these hit most of the major groups - character buffs and enhancement, a possible brew skill, some new curses, new damage spells, and a new undead spell.
The schedule for this is some time in august, about a month after the thief updates of the previous post. After this, we still have a ton of things to work on, including elemental channeling for mages, god code, and a couple of new character classes.
As a result, cleric has been a useful, powerful class - but not something you want to be your primary. Our future update to cleric aims to change that.
The biggest updates to the class aren't likely to be new spells and skills. Rather, we want to fix existing spells and skills that aren't up to snuff with the rest of the class.
Take for example the 'peace' spell. This could be a very powerful, useful spell - if only it worked differently. We're currently imagining room effects, duration effects, and a handful of other options to improve this.
Another spell that's long been on the todo list is charm. The current version of charm has basically been dented into the ground to prevent charm armies. With this update, we're planning to switch it to a control point system similar to necromancers. This should make charm a lot more useful while at the same time limiting "charmy" problems.
Other things that could use similar kinds of improvement are turn undead, the ward spells, curses, and the monitor skill.
All this said, we do plan to add more spells and skills. So far these hit most of the major groups - character buffs and enhancement, a possible brew skill, some new curses, new damage spells, and a new undead spell.
The schedule for this is some time in august, about a month after the thief updates of the previous post. After this, we still have a ton of things to work on, including elemental channeling for mages, god code, and a couple of new character classes.
Labels:
classes,
clerics,
design,
future directions,
new features
Subscribe to:
Posts (Atom)