Jump to content

  • Log In with Google      Sign In   
  • Create Account

Pixel → Tile → World

Creating custom class templates for QtCreator

Posted by , in Article, Tool 07 March 2012 - - - - - - · 3,576 views

The QtCreator IDE provides a set of template projects and template classes, but occasionally the need to create your own arises.


Posted Image

QtCreator stores its templates in this directory:
..\QtSDK\QtCreator\share\qtcreator\templates\wizards\

(In that directory is a bunch of pre-existing templates, which you can look at to learn how they work. At least one of them, 'listmodel', is purely for exampling how it's done. This is how I figured it out, a few hours age - however, there is a great lack of documentation about this online, hence this journal entry)

The first step is creating a new folder for your own template under the 'wizards' directory; the name of the folder doesn't matter.

In that folder you'll want to put your template's source and header files.
QtCreator scans the 'wizards' directory looking for XML files named 'wizard.xml'. The file must be called exactly that.

A wizard.xml file looks like this:
<wizard kind="class">
<icon>AdventureFar.png</icon>
<description>Creates an inheritted GameState class for AdventureFar.</description>
<displayname>GameState</displayname>
<displaycategory>Adventure Far</displaycategory>
<files>
<file source="source.cpp" target="%ClassName%.%CppSourceSuffix%" openeditor="true"/>
<file source="header.h" target="%ClassName%.%CppHeaderSuffix%" openeditor="true"/>
</files>
<!-- Create parameter wizard page -->
<fieldpagetitle>GameState parameters</fieldpagetitle>
<fields>
<field name="ClassName">
<fieldcontrol class="QLineEdit" validator="^[a-zA-Z0-9_]+$" defaulttext="MyGameState" />
<fielddescription>Class name:</fielddescription>
</field>
</fields>
</wizard>


Let's walk through it:

<wizard kind="class">

kind is the type of template you are creating. It is either a 'class' template or a 'project' template.

A 'project' template creates a whole new project, with templated default files and settings.
A 'class' template creates a set of templated files for the existing project.

<icon>AdventureFar.png</icon>

This is an (optional) 32x32 pixel icon in the same directory as your custom wizard.xml file.
It appears alongside your template's name in the QtCreator GUI.

<description>Creates an inheritted GameState class for AdventureFar.</description>

This is the description of your template, in the QtCreator GUI.

<displayname>Game state</displayname>

The name of the template, in the GUI.

<displaycategory>Adventure Far</displaycategory>

This is the category which your template appears under, in the QtCreator GUI. (In the image above, you can see all of these)

<files>
<file source="source.cpp" target="%ClassName%.%CppSourceSuffix%" openeditor="true"/>
<file source="header.h" target="%ClassName%.%CppHeaderSuffix%" openeditor="true"/>
</files>

These are the files that will be added to the project by your template.
source is the template file in your template's directory.
target is the new name of the file, as it appears in your project (Ignore the funky "%ClassName%.%CppSourceSuffix%", it'll be explained a bit lower). This is optional. If the 'target' name isn't in the XML file, it'll keep the same name as the source file.
openeditor - I'm not 100% sure, but I believe this opens the newly created file in the editor when the template is used.


Now, QtCreator allows your template wizards to have fairly extensive GUIs, including multiple pages and widgets and customizations. I'm only familiar with a very small subset of it.

<fieldpagetitle>GameState parameters</fieldpagetitle>

This is the title of the GUI wizard page we are on. The wizard.xml file we're using only has a single custom page.

<fields>
...
</fields>

fields holds a list of fields; the template I created only has a need for a single field, but your templates can easily have a half dozen or more depending on what you are wanting to do.

(Within the 'fields' tag:)
<field name="ClassName">
<fieldcontrol class="QLineEdit" validator="^[a-zA-Z0-9_]+$" defaulttext="MyGameState" />
<fielddescription>Class name:</fielddescription>
</field>

Our field's name is specified by name. The one field I needed, was the name of the class I'm having the template create for me, so my field is named 'ClassName'.

<fieldcontrol> is the Qt widget that accepts user input, which will set the value of our field
The widget is specified by class (in this case, QLineEdit), and we use a RegEx validator to make sure our classname is valid. We also give the QLineEdit the default text specified by defaulttext.

<fielddescription> is just the text that appears in the GUI to inform the user what the purpose of the field is.

</wizard>

And that's the end of the wizard.xml file.

Now, returning upwards a bit, we had the line:

<file source="source.cpp" target="%ClassName%.%CppSourceSuffix%"  openeditor="true"/>


We now see that %ClassName% will actually be replaced by the value of our field, named 'ClassName'.
%CppSourceSuffix% is a built-in field specified elsewhere in QtCreator, that lets users determine if they want to use .cpp or .cxx or whatever else they fancy.

What's important to note is that %ClassName% wont just get replaced in our wizard.xml file; it'll also get replaced in any of the files the template is generating.

Our source.cpp has code that looks like this:
%ClassName%::%ClassName%()
{


}

%ClassName%::~%ClassName%()
{


}
...creating a constructor and destructor for a class named '%ClassName%'. (Asside from our special replacement variables, our source.cpp file is just a regular C++ file.
Our header.h file also uses our field variables to create inclusion guards, like this:
#ifndef %ClassName:u%_H
#define %ClassName:u%_H

Except here, because we love uppercase inclusion guards, we use %ClassName:u% where the ':u' specifies to use the uppercase version. Likewise, we could use ':l' to specify lowercase.

I'm using my template to generate empty GameState classes for my project. My game has alot of GameStates, all looking roughly the same being inherited from the same abstract class with virtual functions that need to be defined in the subclasses.

Here's how my source and header templates look.

My templated header file:
#ifndef GAME_STATE_%ClassName:u%_H
#define GAME_STATE_%ClassName:u%_H

#include "Engine/Structure/GameState.h"

#include "Common/System/System.h"

namespace Game {
namespace State {

	/////////////////////////////////////////////////////////////////////////////////////

	class %ClassName% : public Engine::GameState
	{
	public:
		%ClassName%();
		~%ClassName%();

		void Activated();
		void Deactivated();

		void React(PlayerCommand &command);
		void Update(float deltaTime);
		void Think();
		void Draw(sf::RenderTarget &renderTarget);

		std::string GetName() { return "%ClassName%"; }
	};

}} //End of namespaces.


#endif // GAME_STATE_%ClassName:u%_H

My templated source file:
#include "%ClassName%.%CppHeaderSuffix%"

#include "Common/Logger/Log.h"
#include "Common/Types/ConfigFile.h"

#include "Engine/Structure/GameStructure.h"

namespace Game {
namespace State {

/////////////////////////////////////////////////////////////////////////////////////

%ClassName%::%ClassName%()
{

}

%ClassName%::~%ClassName%()
{

}

void %ClassName%::Activated()
{

}

void %ClassName%::Deactivated()
{

}

void %ClassName%::React(PlayerCommand &command)
{

}

void %ClassName%::Update(float deltaTime)
{

}

void %ClassName%::Think()
{

}

void %ClassName%::Draw(sf::RenderTarget &renderTarget)
{

}

void %ClassName%::DrawOver(sf::RenderTarget &renderTarget)
{

}

/////////////////////////////////////////////////////////////////////////////////////

}} //End of namespaces.

Hopefully you'll find this useful if you use QtCreator. I found a great lack of documentation on this otherwise simple feature which is common in most IDEs.


World atmosphere in games, measuring and categorizing

Posted by , in Article, Indie games, Design 09 January 2012 - - - - - - · 1,315 views

Three journal posts in three days, after 30 days of silence. I must be on a roll! Except, uh, none of them are about progress on my RPG project. Posted Image

My brother recently observed over the phone that, "...you seem to be a collector of games, rather than a player".
That's a fairly accurate statement. I don't really have the time to play hours and hours of games, but I greatly enjoy acquiring high quality indie games (and some specific innovative mainstream games) when they go on sale cheap enough. (I'm a casual collector, rather than a focused one).
My tastes in games have definitely shifted over the past few years and now my main focus when playing games, is the artistry and beauty of the world in the game. This same focus will be my focus when designing my own games.

It's the atmosphere of the world that I'm looking for, and that is a sum of multiple things.
The order of importance, for me, when creating atmosphere in a game scene or area goes something like this: (diminishing importance)
Music/Sound > Coloration(color pallets)/Art-style > Freedom of movement/Freedom to explore > Architecture style > Fairness of enemies/Non-irritation > Characters involved > Graphical quality > Level layout

I'm probably missing a few other things that should go in there, like background history of the world/area.

Here's some games I enjoy for the world you are immersed in:
(Loosely and lazily rated in terms of atmosphere and world, not rated in overall game quality or enjoyment - Also, obviously it's my personal opinion and people's opinions vary)

- Quest 64 (N64) Posted ImagePosted ImagePosted ImagePosted ImagePosted Image
- Lost City of Malathedra (PC) Posted ImagePosted ImagePosted ImagePosted Imagehttp://public.gamedev.net//public/style_images/master/star_off.png
- Machinarium (PC) http://public.gamedev.net//public/style_images/master/star.pnghttp://public.gamedev.net//public/style_images/master/star.pnghttp://public.gamedev.net//public/style_images/master/star_off.pnghttp://public.gamedev.net//public/style_images/master/star_off.pnghttp://public.gamedev.net//public/style_images/master/star_off.png
- Myst and Riven (PC) http://public.gamedev.net//public/style_images/master/star.pnghttp://public.gamedev.net//public/style_images/master/star.pnghttp://public.gamedev.net//public/style_images/master/star.pnghttp://public.gamedev.net//public/style_images/master/star_off.pnghttp://public.gamedev.net//public/style_images/master/star_off.png
- Shadowgrounds (PC) http://public.gamedev.net//public/style_images/master/star.pnghttp://public.gamedev.net//public/style_images/master/star.pnghttp://public.gamedev.net//public/style_images/master/star.pnghttp://public.gamedev.net//public/style_images/master/star_off.pnghttp://public.gamedev.net//public/style_images/master/star_off.png
- VVVVV (PC) http://public.gamedev.net//public/style_images/master/star.pnghttp://public.gamedev.net//public/style_images/master/star.pnghttp://public.gamedev.net//public/style_images/master/star.pnghttp://public.gamedev.net//public/style_images/master/star_off.pnghttp://public.gamedev.net//public/style_images/master/star_off.png
- Minecraft (PC) http://public.gamedev.net//public/style_images/master/star.pnghttp://public.gamedev.net//public/style_images/master/star.pnghttp://public.gamedev.net//public/style_images/master/star.pnghttp://public.gamedev.net//public/style_images/master/star_off.pnghttp://public.gamedev.net//public/style_images/master/star_off.png
- Mario 64 (N64) http://public.gamedev.net//public/style_images/master/star.pnghttp://public.gamedev.net//public/style_images/master/star.pnghttp://public.gamedev.net//public/style_images/master/star.pnghttp://public.gamedev.net//public/style_images/master/star_off.pnghttp://public.gamedev.net//public/style_images/master/star_off.png
- Metroid Prime 1 (Wii) http://public.gamedev.net//public/style_images/master/star.pnghttp://public.gamedev.net//public/style_images/master/star.pnghttp://public.gamedev.net//public/style_images/master/star.pnghttp://public.gamedev.net//public/style_images/master/star_off.pnghttp://public.gamedev.net//public/style_images/master/star_off.png
- Halflife 1 (PC) http://public.gamedev.net//public/style_images/master/star.pnghttp://public.gamedev.net//public/style_images/master/star.pnghttp://public.gamedev.net//public/style_images/master/star.pnghttp://public.gamedev.net//public/style_images/master/star.pnghttp://public.gamedev.net//public/style_images/master/star_off.png
- Elderscrolls 3: Morrowind (Xbox or PC) http://public.gamedev.net//public/style_images/master/star.pnghttp://public.gamedev.net//public/style_images/master/star.pnghttp://public.gamedev.net//public/style_images/master/star.pnghttp://public.gamedev.net//public/style_images/master/star.pnghttp://public.gamedev.net//public/style_images/master/star_off.png
- King's Field (Playstation 1) http://public.gamedev.net//public/style_images/master/star.pnghttp://public.gamedev.net//public/style_images/master/star.pnghttp://public.gamedev.net//public/style_images/master/star.pnghttp://public.gamedev.net//public/style_images/master/star.pnghttp://public.gamedev.net//public/style_images/master/star.png

(By the way, I'm greatly looking forward to The Witness - I strongly believe it'll rate at least four stars, possibly 5, when it comes to atmosphere and world)

Yes, that's right. In terms of atmosphere, VVVVVV is equal to Myst in my book. Anything 3 stars or more, I'd replay (and most have already replayed multiple times) solely for the atmosphere and world.

One thing I observe in these games is that the graphical quality of the game comes second to the world design itself. Great atmosphere and great worlds can be created even with poor graphics (See: King's Field, VVVVVV, Halflife 1).
Another observation is that world design and atmosphere is not bound to a specific genre (VVVVVV = 2D sidescroller, Halflife 1 = FPS, King's Field = 3D action RPG).
A third observation, and one that somewhat surprises me is that while 'Freedom of movement/Freedom to explore' is important to immersion and atmosphere, it doesn't depend on it (King's Field = freedom to explore in multiple directions - one big dungeon with chokepoint obstacles, VVVVVV = freedom to explore until you enter a fairly linear dungeon - dungeons can be overcome in any order, Halflife 1 = Infamously linear game moving from room to room, battle to battle, with only the freedom to move around in the last room or two you are currently in).

So going back to my spur-of-the-moment attempt to measure the effect of game attributes on world atmosphere:
Music/Sound > Coloration(color pallets)/Art-style > Freedom of movement/Freedom to explore > Architecture style > Fairness of enemies/Non-irritation > Characters involved > Graphical quality > Level layout

...It does seem to me that while some things contribute greatly to world atmosphere, no one thing on it's own is required. That is, that lack of any one of those attributes can be made up for by strengthening the others, despite some attributes (Like music and art style) carrying much greater weight than others. This is especially good for us as indie developers, because we can (and have been) enhancing some parts of our atmosphere equation (like Music and Art style) to compensate for that infamous and controversial area where we can't compete with the big studios: Graphical quality.

Thoughts?


Pixel blend mode algorithms (including 'Overlay')

Posted by , in AdventureFar, Article 17 March 2011 - - - - - - · 10,355 views
image, blend, pixel, alpha and 2 more...
I didn’t feel like chipping away at my todo list last time I coded, so I decided instead to implement some new graphical features to AdventureFar’s tile engine.Specifically, I wanted to add shadows for any map makers to place on a map. Iended up doing a bit more than that, and added five different ways of blending stuff together, using the same blend modes PaintShopPro or PhotoShop uses.

Previously I had tiles and masks, and I could only apply that mask in one way. Now I can choose how I want the mask to be applied to the tile. I can apply the mask as illumination or as shadow, or I can continue to use it as exclusion to make the tile partially or fully invisible.

Here are pictures of the new blends I added (all images taken from within AdventureFar), as well as the algorithms to implement them. I intend to add additional ones later, just to give map makers more tools to use creatively. Now that I have them in, if I know the proper algorithm it only takes about 5 minutes to add a new blend mode to the game.

Posted Image



Posted Image

In my game, all of this is done only once when the map is loaded, and the blended tile is then cached. There is no run-time cost for these blends except the initial increased load times. If the same mask is blended in the same way to the same tile, then that final image is shared and it doesn’t take any more memory than previously.

I also added the ability to (inside the engine) run the same blend multiple times in a row, as seen here where I am using Multiply blend for five loops:

Posted Image
 
Overlay blend was the hardest to do, because all the articles I read online, including PaintShopPro’s and Gimp’s stated algorithms, weren’t producing the correct result for me. It turns out you have to apply it per color channel, not per color. The big thing with Overlay is that it darkens and brightens the image, depending on the mask. It’s a mix of both Screen blendand Multiply blend.

Here’s an example: (images stolen from elsewhere on the internet and then implemented in my game)

Posted Image

If the pixel is less than 128, you use something similar to Multiply blend. If it’s greater or equal to 128, you use something similar to Screen blend. However, you do it per color channel of the pixel, not per the average of the pixel, like I was doing (which was an obvious mistake on my part). So on a single pixel you might Multiply the red channel but Screen the green channel, or whatever. This is the proper way to do Overlay blend.

Another part of the confusion is all the articles I read online just say, “if less than 128 use Multiply, otherwise use Screen blend”. This isn’t entirely true – the multiply used in Overlay Blend is different than the regular Multiply blend. They multiply it by 2 afterward, to make it not contrast with the Screen blend as jarringly. They do the same thing with Screen as well. Observe:

Posted Image

If you compare Overlay blend with Multiply or Screen in your image editor of choice(or in the table above), you’ll notice that the Multiply will be almost twice as dark as the dark parts of Overlay, and Screen will also be somewhat brighter in the same spots than Overlay. All the articles I read failed to mention that… =)

The proper Overlay blend mode algorithm like in Photoshop, PaintShopPro, or Gimp, is as follows:

Posted Image

(Warning: Gimp mixes up the name of their ‘Overlay’ blend. Their ‘Overlay’ is misnamed ‘Hardlight’, and their ‘Hardlight' is misnamed ‘Overlay’. This is their mistake, not Photoshop’s or PaintShopPro’s, as you can easily deduce when reading Gimp’s documentation. The ‘Overlay’ I show above is called ‘Hardlight’ in Gimp)
 
While doing all this, I also realized I was doing alpha transparency wrong when applying masks to tiles.

Here’s what I used to do:
//Bad:
int alpha = maskColor.GetAverageValue();

Here’s what I’m now doing:
//Good:
int alpha = (tileColor.GetAlpha()* maskColor.GetAverageValue()) / 255;

What was wrong with the previous one? It overwrites the tile’s transparency with the average of the mask. If the tile already has transparency, its transparency is ignored! The new code takes into account the transparency of both the mask and the tile. Observe:

Posted Image

With the bad result, it ignores the tile’s original transparency. If the tile doesn’t have transparency, then the new chunk of code produces the exact same result as the old code.

Posted Image

As an added bonus, mask blending is now stackable just like the other blends. I can run the same mask-blend several times to make the tile increasingly more transparent. (This is actually what led me to discover this mistake in the first place – realizing that consecutive mask blends wouldn’t stack properly,and then further realizing that they wouldn’t even stack on the tile’s original alpha channel).
 
Resources that helped me:






Recent Entries

Recent Comments

Latest Visitors