Table of Contents
Oktober 2013 blog archive
This page contains all the blog posts from oktober 2013. To read the most recent blog posts, click here.
27/10 - Deck editor continued
The deck editor is starting to come together : right now it is capable of calculating the layout of the deck panel and then render the cards. This step took a bit longer to complete as i ran into a few more quality issues with font rendering that had to be looked at first.
Here is a screenshot of the deck editor at full resolution (1600x1000 pixels). I'm using a simple 40-card deck for now, just so i can test the functionality. All cards have the Vector image, as that is the only card image i've added to the game thus far. The final size of card images hasn't been decided yet (for that i would need to finish the full card popup), so i'm not going to spend any time yet making new renders for cards.
The top bar starts off with the deck name. This is also a button that can be clicked, which will generate a popup where the deck name can be edited - i'll probably add the deckstring in this popup as well. Next is the base energy type for this deck - this can be clicked to bring up a small popup with 9 energy choices. Then comes a short description of the deck's contents. The next button allows to change a number of things in the deck panel : you can choose to show cards as singles or have indentical card stacked, there are three size options to choose from (the screenshot is taken with the largest card size option), there are 3 sorting options : cardcost (as in screenshot), card subtype or alphabetical, then there are options to change the size of the font used to show the name of the card, or to turn off the cardname field or to turn off the attack/defense and cardcost fields. The skills button allows to switch to a similar screen where the skills, connected to this deck, can be edited. The save button saves any changes to deck.
The bottom panel shows the card stock and will look very similar to the top panel. This panel hasn't been implemented yet, but the code will be very similar to that of the top panel, so i don't think this will take much additional time.
A deck is always displayed as 3 blocks of cards, seperating them in the 3 card types in HD : ships, structures and actions. Within each block, the cards of that type are then sorted based on the active sort option. For the time being, the editor is only performing one sort at once, so either by cost, name or subtype. I plan to update this so that two sorts are performed at all times. This means if you were to pick the cost sort option, the game will first sort cards by subtype, and then by cost to make sure that smaller ships go first even if they have the same cardcost as larger ships. It's a small thing, but it will make the contents of the panel seem less random. The number of rows depends on the active scalemode : the largest card images (as in the screenshot) will be shown in max 2 rows and 7 columns at once, the next scalemode will place cards in 3 rows and 10 columns and the smallest scalemode will have 4 rows and max 14 columns.
The font render quality looks good in the above screenshot, but at lower game resolutions, the quality starts to drop a bit. At the smallest supported resolution (800x500) the next is near unreadable. To address this i've added the option to increase the fontsize and by default, the game will switch to this larger fontsize when it detects small resolutions. This greatly improved the readability as the smallest resolution. The image below shows the contents of the deck panel when the game is at 800x500 pixels. The top half of the image shows the small font, the bottom half shows the larger font.
There's still room for improvement - i can redesign the font so it's a bit sharper at smaller resolutions. This will take a bit of work, but i expect it'll be worth it.
Another quality problem has to do with the card images themselves. It's not as apparent as the text, but if you're used to seeing the card images in other versions of HD and then see them in HD3 i'm sure you'll notice some artifacts.
Card images in-game may appear in various sizes, instead of exporting each card image in each size and adding all those versions to the game, i only include the largest version that the game would need, and scale all other versions down in-game, whenever needed. This saves a lot of work and keeps the filesize of the game relatively low. This is how i've been doing it since HD1 and the results have been good. The largest version (i.e. the one that gets included with the game) is the one that will be used for the full card popup (esimated to be 292x292 pixels for HD3). The sizes needed for the deck editor depend on the active scalemode : 178x178 or 118x118 or 88x88 pixels, so scaling is needed in all 3 cases.
In a previous blogpost about the development of the text renderer, i talked about filters and how pixel-scaling reduced the quality of texted scaled using that method. It's this same method i'm using to scale images as there's no alternative, except for real-time scaling, which would complicate the deck editor rendering code even more. For the time being i'll leave things as they are and i'll continue working on the editor. Once more card images are in, i'll get a better idea of whether or not this scaling method is acceptable. If it isn't, i'll either have to use realtime scaling, which i'm trying to avoid or i'll look into writing my own pixel-scaling filter. I might postpone the decision until i get started on the combat screen layout, which will features card images in 3 additional sizes (cards in hand, cards in play and cards in the scrapyard).
In general, realtime scaling is faster, but it complicates render code as cards would now have to be rendered in 3 steps instead of just one : first the background, then the card image with realtime scaling, and then the attack/defense and cardcost fields. Pixelscaling is slower, but i could prepare a bunch of scaled images beforehand so that the game doesn't need to scale anything while a battle is in progress for instance. Writing a filter myself will be an interesting excercise in any case, so i might just go ahead with that route and see if it can produce higher quality images.
20/10 - Deck editing
The deck editor screen is slowly coming together. The UI that surrounds the two panels where the cards in the deck being edited and those in the player's cardstock are shown is complete. Right now i'm working on the code that sorts and prepares a set of cards for displaying. This code will produce data that the renderer can use to generate the correct card images and place them in the correct spots on the screen. The same data then also gets used in combination with player input, which in turn will allow cards to be moved or card popups to be generated.
Before i could start on the deck editor, the game needed at least some cards and a deck, so i've added 10 different cards and one deck with 40 cards. This should be enough to perform basic tests for all the functions that the editor should provide.
Cards inside the game are each represented by a relatively large set of data, containing every detail about a card (race, cost, rarity, abilities, etc). But a deck, which is a collection of cards, is very simple. Each card has a number that serves as a unique identifier (ID for short). If you know the ID of a card, you can use it to look up all its stats. A deck can be reduced to a set of those IDs.
For a player, these IDs are of no importance, but players might want to store their deck ideas outside of the game or share them with others. Giving a player a set of up to 60 numbers to store or share isn't very user friendly. HD Spectrum introduced deckstrings to make this easier. A deckstring is a set of characters that represents a single deck. A fairly simple process takes the IDs of cards in a deck and turns each of those in two characters. A single character in the deckstring can represent a value between 0 and 63 (64 different values in other words), two such characters next to each can represent 64x64 values, or 4096 different values. Since the game has more than 64 but less than 4096 different cards, two characters are needed per card. For a deck of 40 cards, the resulting deckstring will never be larger than 80 characters (plus several control characters). Deckstrings do take into account how many times a card is present in a deck which allows them to be a lot smaller for decks that use few different cards. A deck with 40 cards, which uses only 10 different cards, will have a deckstring of about 25 characters (of which 5 control characters).
Besides allowing to easily store decks in a text file or put them in emails, deckstrings also provide benefits for the game itself when it comes to storage. It's almost always more interesting to store a single string of characters versus storing 40 to 60 numbers.
IDs aren't just there to distinguish cards, i've set them up such that they contain a fair bit of info about the card they represent all by themselves.
Example : Vector (Hu ship) has ID 1, Nagato has ID 2, Solar Harvester has ID 51 and Cruise Missile has ID 75. Here are some CA cards : Dorgan (101), Antimatter Plant (151), Antimatter bomb (175). Have a look at the card album inside HD Xyth - the cards are sorted by ID there.
Often when the game handles or processes a deck, the game doesn't need to know the names or abilities of the cards in the deck at that point, but the game might want to know the number of ships, structures and actions and sometimes even the races of cards. This information is all stored in the extensive datastructure that each card has, so the game can take the card ID (which it got from the deckstring) and use it to look up the details of the card. But, like i said, the card ID itself reveals some info about the card it represents. Now the game only needs to look at these IDs and perform some simple math instead of looking up data. It makes things a bit more efficient.
The examples of card IDs above might already reveal whats happening. Here's how it works : every race has a block of 99 IDs, ranging from 1 to 99 for Human cards, 101 to 199 for Ca'anian cards, all the way up to 801 to 899 for Artifact cards. If you take any ID and divide it by 100 and round the result down, you'll get a number from 0 to 8, which represent the IDs of the races.
There's more : each block of 99 IDs is split up in the 3 card types : 1 to 50 are ships, 51 to 74 are structures, 75 to 99 are actions. Let's take a random number : 484. Divide by 100 and rounding down gives 4, which means this would be a Rivi'i card. 84 lies between 75 and 99, so this is a Rivi'i action. At this point we don't know which action, but if we're currently in the deck manager, where decks tell you how much of each card type they have, we don't need to know that information.
HD1 was slightly different in that the races only had 49 IDs each. So the game could support a maximum of 49 cards per race or max 441 cards in total. For HD Spectrum i moved to the system i explained above, allowing for up to 99 cards per race or 891 max total. HD Xyth at first looked like it would need a new system, because of the card upgrading mechanic. Each card had 4 versions it could exist as, with almost 500 cards in total, this results in almost 2000 when you take into account the upgraded versions. With only 891 available IDs, there was a problem. In the end, the solution was rather simple : for each upgrade level, a card simply received +1000 for its ID. A Dorgan (ID 101) has IDs 1101, 2101, 3101 for its upgraded versions. Inside the game, not much needed to be changed to support this and it became very easy to calculate the ID for a card that had to be upgraded (add 1000) or to figure out what the basic version was of any card (ID % 1000), which is what the game does when it must make a non-PvP deck compatible with ranked PvP.
Luckily i didn't have to change the deckstring format too much, either. Every two characters can represent an ID between 0 and 4095, the highest ID the game can produce is 899 + 3000, which would be an AR action that has been upgraded 3 times (ID 3899).
HD3 will need some larger changes again however. HD Xyth can support 99 cards max per race - if i add another 200 cards to the game, we're getting close to that limit. For HD3 i'll up the limit to 400 cards per race - this should make sure the game can receive updates and new cards for a long time. Since HD3 doesn't have the upgrade system that HD Xyth had, there's also not going to be any problems for the deckstring format. 400 cards per race is a maximum of 9 x 400 = 3600 cards, which is still less than the 4095 that the deckstring format supports.
A system like this does put a limit to the number of ships, structures and actions each race can have and migth seem inflexible. I could definately make a flexible system, but there are many advantages to having a certain structure - the deck processing example above being just one. And the limits have been set high enough so that they can support the game for a long long time.
This system has been in effect since HD1 and a fair bit of theorizing with different systems happened before i decided to implement it like that. The versions of HD that followed took the same system and improved and expanded it. This is also not the only mechanic that still survives from HD1, even though most mechanics have been improved a lot, the basic idea remains the same.
13/10 - Deck manager
The text renderer has been finished and is producing good results in most cases. On the smallest screen resolution (800x500), the readability is a bit affected for the smallest fonts. I'll have keep monitoring this to see if it's acceptable or not.
I've moved on to the deck management screen, which is the first screen that uses the UI i've designed for HD3 (both the preloader and the menu screens don't use UI elements as such). This first screen will allow me to set up small bits of utility code that can generate sub elements of the UI (such as complete buttons, or text labels, panels, etc). Having these sub elements as seperate bits of code allows me to describe a screen rather easily. If i need a screen with a certain number of buttons for instance, instead of drawing each of these buttons seperately and manually through code, this screen simply calls upon the utility function for buttons a number of times which then generates complete buttons. The same information that is used to generate buttons and place them at a certain position on the screen is then also used by the part of the game that checks mouse input to see if a player clicked a certain button.
Here is the sketch of the deck manager i posted a couple weeks ago :
The only difference of the one in-game is that it's 1600x1000 pixels, while the sketch is 800x500 pixels.
The deck manager's purpose is straightforward : it shows you a list of the decks you've made and lets you browse, sort, delete or edit these decks. Each deck shows its name, its base energy type, the number of cards it has and the number of skills that are tied to it.
The manager can technically handle any number of decks, but there will be a limit to the number of decks you can store. This has to do with the fact that the game is planned to have a backup function that stores your progress (including your decks) in a database. There has to a be a reasonable cap to the amount of decks one can store to make sure the database size doesn't grow too large. HD Spectrum only stored a few decks into the database and had a 'deck vault' system, where you could have any number of decks, but these were stored on your PC. While this is still a valid option, the whole idea of having two storage locations that need to interact with each other is a bit cumbersome. I haven't decided yet on the number of decks that can be stored since i don't have an estimate yet of how much data will be stored in savegames.
The manager provides access to the deck and skill editor, which are both similar in function. One lets you change the cards in the deck and the other lets you select which skills you want to affect the deck.
Since the game in its current state doesn't have any cards yet, i'm testing the functionality of this screen with simulated deck data. This works since the manager screen doesn't really care which cards or skills are in a deck, it only shows the number of cards and skills. This will change when i start on the deck editor, where cards must obviously be present.
I've talked a bit about the changes regarding card abilities before. For players this means that abilities will be split up in groups that make more sense (entry, automatic, activated, passive, exit, aura). For me it makes processing and handling skills in code easier, but it also makes the datastructure that represents a card a bit more complex. This datastructure was set up for the first time in HD1 and it hasn't changed all that much since then. For HD3, however, i'll have to come up with a new structure to support the fact that cards are no longer limited to just one of each ability type. This won't affect the way the game is played, but it will greatly affect the code that manages abilities as well as the code that manages the structure and progress of a duel. In the long term this is a good thing, as it will increase the number of abilities the game can support and it should make it easier to add new abilities, even after release. But for the short term (the next few weeks i estimate) it means i'll have to come up with a new data structure.
There's a lot involved in setting up the deck editor screen : the UI layout and rendering, accepting and processing input (some of it complex as i want to support drag and drop mechanics), being able to read card data (which requires the card data structure, and of course several cards to be present in-game), being able to read deck data (which is the dataformat that stores all info about a deck), being able to edit and store deck data, being able to read the card stock of the player…
There's some things still left to do on the deck manager screen, but it should be complete soon. The deck edit screen will clearly take a fair bit more work, but once it's in, the game will have some of the most important support mechanics : deck and card datastructures, a mechanic that can turn carddata into actual cards, and a mechanic that can process card data to generate the card popup.
06/10 - Text renderer... continued
Last week i talked about the text renderer i'm building for HD3. The core of this tool was finished, but there were quality problems when the renderer had to produce scaled text.
For most of the past week i did tests with a number of things that could improve the quality. I ended up giving the textrenderer two master fontsets : one of size 32 and one of size 24. This makes sure that no scaling needs to happen when the renderer is making texts to be used in the UI or the cardpopup.
Next to size 24 and 32, the game still needs texts at various (and some currently unknown) font sizes. However, these texts can be broken up into two types : card names and card costs + attack/defense values. These two types are to be used on the cards you'll see in the deck editor, in your hand and in play.
The addition of the size 24 font allows me to render cardnames in all caps, instead of only capitalizing the first letter of the name. This may seem like a minor thing, but it solves a problem i was having with the look of card images. The image below shows a sketch of a card image as it will appear in the deck editor. The size of the font relative to the size of the entire card image might still change however, or there might be different versions based on player preference.
Nothing looks wrong with the first card, but if this were a 'Nagato', the lower part of the letter 'g' spills out of the reserved field for the card's name, which doesn't look nice. The solution is to make this field larger, and thus the card image itself gets smaller as shown in the 3rd image. I want to maximize the amount of space for the card image so i don't really like this solution, on top of this, as the 4th image shows, the larger name field doesn't look good in case this was a 'Vector' again. The 5th image shows the name in all-caps, using fontsize 32 for the first letter and size 24 for the rest, and the name field can be made smaller again. Now all card names are guaranteed to fit in this field and the field is evenly filled. I also think that all-caps improves readability, especially for cards that will be much smaller than those in the example.
The name will be rendered seperately from the rest of the image and it will be scaled in realtime, this means i won't have to make a dedicated fontsize for each size of card image.
The other type of text is very simple : it only needs numbers, the energy icons and a '/' symbol for the attack/defense value. Instead of rendering these things at either size 32 or 24 and then scaling them in realtime, i'll make a dedicated, but simple renderer for each fontsize. A renderer like this doesn't need to deal with linebreaks, wordwrap, etc, it just needs to be able to combine numbers and icons. That way i can ensure that card costs and attack/defense values get renderered in the highest quality available.
Of course there are still some issues, which explains why i'm still working on this. Realtime scaling produces good results, but as the game window gets smaller, there is a loss of quality again.
In Flash, what you see on the screen is an exact representation of the scene i set up through code. In Java (and basically all games that use the graphics card instead of the CPU), what you see in the game window is a projection of the scene. I've mentioned in a past blogpost that the game runs on a resolution of 1600x1000 pixels internally. If the game window is also 1600x1000 pixels, you'll get a near perfect view of this screen as there's no scaling, but there's still projection. Think of the gamescreen in this case being what you see through a camera, looking at the scene that was set up. Things work this way as it's essentially a (simplified in this case) 3D setup, even though HD3 is a 2D game.
The major advantage of this projection is that you can scale the game window down and you'll still be able to see the 1600x1000 internal resolution, it will just be scaled down. This happens with high precision, but it isn't perfect (which wouldn't be possible). Everything gets projected regardless of the window size, so even at 1600x1000, which means that graphics pass through filters.
If i perform realtime scaling, another filter is applied to whatever images were scaled. The smaller the screen gets, the more noticable the projection becomes (but not so that it affects quality that much), but on images that are scaled, there can be a drop in quality at smaller window sizes. For card images, UI and just pictures in general, this is no problem. For text, it is, especially at the smallest resolution that the game supports (800x500). While it's unlikely that many players will use this resolution, the game supports it, thus it must at least be able to offer a good experience on this resolution.
One solution is to change the internal resolution of the game so it matches the window resolution. So if the game ends up being resized to 800x500, so must the internal resolution. This removes one layer of scaling from the projection. However this means i need to set up dedicated layouts for each resolution the game supports. This includes fullscreen, which technically mean every possibly resolution of 800x500 and larger. So that's not going to work out, especially since it would mean i'd have to create dedicated fontsizes for each resolution.
Right now i'm testing several ways of setting up the in-game scenes. In Flash it's pretty simple, since it's all about pixels that never change size. In Java i tend to make images while the game runs, in the same i do it in the Flash version of the game, but whereas the Flash version can draw this image straight to the screen, in Java i have to upload that image to the GFX card. The code to do this is very simple, the process that happens behind the scenes however isn't instant.
For instance i make a red square, place a card image on it, place a darkened header and a card name on it to produce a card image for the deck editor. These images then get uploaded to the GFX card's memory, which turns this image into a texture and is then able to show it on the screen. Uploading to the GFX card is a slow process, so it must be avoided as much as possible. One way to do so is to predict which images you need, make them whenever it wouldn't affect the game speed (many games prerender stuff at the start of the game for instance or everytime a new map or level is loaded). Not everything can be predicted or prerendered. HDx had about 500 card abilities, most of these with changing values, so there's no point in prerendering all possible text combinations for card images (it would take up too much memory anyways), so the card popup will have to be rendered and uploaded to the GFX card in realtime. If this is the only realtime element, it won't affect performance, but during a duel, there are many things that change all the time and can't be predicated, such as energy stocks, HP bars, the attack/defense values on ships.
The trick is to find a balance between prediction, real-time image generation and memory usage. The text renderer must be optimized to make sure it doesn't slow down the game whenever it needs to render a new value for an energy stock that gained or lost energy. I could prerender all values from 0 to 99 and simply pick the number i need from the list of prerendered values. This won't take up too much memory and it will surely provide a performance boost. The problem here is that text now becomes seperated from the energy stock panel, and is thus scaled and filtered seperately from the image of the energy stock panel. If the game is sized at different resolutions, each resolution will have its own set of rounding errors. With images that need to be as clear as possible for readability purposes, this can affect the way text looks if the game is played on different resolutions. Some quick tests i've done show that this has the potential to produce text that doesn't look nice enough in very rare cases.
Even though it only happens with specific images rendered in a certain order, i'm trying to get to the bottom of this. It might be a rare occurence now, in a testing setup, but it might be common in a certain screen that gets added to the game later on. So i rather fix this or figure out when the problem occurs now than having to review the renderer everytime a new screen gets added to the game.
This is not something that can be fixed as such, it's inherent to the way 3D graphics work. Projecting something that is 1600x1000 pixels onto an area that's not 1600x1000 pixels will always produce some form of graphical rounding errors. I'll have to find a balance between performance and quality. So far i found that rendering text on a fully transparant background is faster, but it produces extra artifacts when scaled and placed against backgrounds of various colors. If i render the text on an area that has the same color as the background and then perform the scaling, the text blends in much nicer, but this requires an extra step in generating an area with a certain color first. So if i make card images such as those in the sketch above, instead of rendering the card name seperately and scaling it to fit in the name field, i'd have to render the name and the darkly colored name field as one image and scale it as one image, then render it on top of the rest of the card. This takes an extra (small) step, but results in better looking text.
It may seem like a trivial thing, but it means moving from a rendering setup where image and text rendering are seperated to one where some images and texts are seperated from other images. If i know what rendering setup is best, i can start implementing it right away, instead of having to change the way things are rendered after i've already implemented several screens and UIs into the game.
This is a minor thing, something that is present in TS2 and the Ultranought follow-up as well, but those games don't have the very high quality demands that i've set up for HD3. It's not like this is visible in those games anyway, as i managed to fix (or rather, work around) it (by chance) in the way the master fontset is set up : the font comes with a darkened glow/shadow around it, to help seperate it from the background - the HD3 font won't have this.
It has taken up a fair bit of time thus far, but it will be worth the trouble in the end, i'm sure.