Game Development Community

dev|Pro Game Development Curriculum

T2D Tips and Tricks : Sprite Editing

by Simon Love · 08/06/2014 (10:47 am) · 2 comments

The obligatory video



My goal was not to create a pixel art editing program but I think that the obstacles I've faced might also trip up other Torquers. As such, here is the result of hours of head-scratching.

- Color Picker

You might not know this, but T2D ships with a full-featured Color Picker.
To use it, you simply need to create a new GuiColorPickerCtrl and add it to a GuiControl somewhere.

The top ColorPicker uses the DisplayMode = "BlendColor";, the crosshairs appear because ShowSelector = true;.

The main thing to note is that the Gradient is generated off of %ColorPicker.BaseColor while the selected color (the one under the crosshairs) is in %ColorPicker.PickColor.

The bottom ColorPicker is of type HorizColor. I simply use its PickColor to change the first one's BaseColor. Since they are GuiControls, it is easy to hijack their "onMouseUp" and "onMouseDown" methods.

...

%ColorPicker = new GuiColorPickerCtrl(BlendColorPick){
   DisplayMode = "BlendColor";
   BaseColor = "1.0 0.0 0.0";
   ShowSelector = true;
   Position = "0 100";
   Extent = "200 200";
};
%Ctrl.add(%ColorPicker);

%ColorPicker2 = new GuiColorPickerCtrl(BaseColorPick){
   DisplayMode = "HorizColor";
   BaseColor = "1.0 0.0 0.0";
   ShowSelector = true;
   Position = "0 300";
   Extent = "200 20";
};
%Ctrl.add(%ColorPicker2);

Canvas.add(%Ctrl);

Not much else to say about these except that there are several other DisplayModes to choose from so feel free to experiment and share your findings!

- The "Canvas"

The central part of the screen (where the drawing happens) is actually a CompositeSprite! As the mouse is moved across the CompositeSprite, the SpriteBatchItems which are hit are selected and their BlendColor set to whatever is selected as the ColorPicker's PickColor.

While it doesn't show in the video, If you right-click the image, the color of the SpriteBatchItem changes the Base Color of the ColorPicker, allowing a workflow very similar to GraphicsGale, which is my favorite Sprite Editor Program.

- Convert a CompositeSprite to a .PNG

At the touch of a button, I convert the CompositeSprite to a PNG file on disk. How?

I reset the CameraZoom property of the SceneWindow and use another of T2D's hidden functions :

CaptureScreenArea(%min._0, %min._1, mCeil(%width), mCeil(%height), "./nusprite"@$itr@".png", "PNG");

%min._0 and %min._1 represent the upper-left corner of the area which you want to save to a file.

Once the file is saved to disk, we create a new ImageAsset.

%testAsset = new ImageAsset()
{
AssetName = "something";
ImageFile = "nusprite"@$itr@".png";
};
%AssetID = AssetDatabase.addPrivateAsset(%testAsset);

Once the Asset has been created, we use it to create a new Sprite.

%spr = new Sprite(){
   Image = %AssetID;
   Size = "8 8";
   BodyType = "dynamic";
   Position = getRandom(-35,35) SPC "20";
};

While this might be hacky, it works!

- Convert a PNG file to a CompositeSprite

I know this is weird, I know that most people won't have a real use for this particular trick but I think the C++ code to manually read the pixels from a PNG file might be useful.

Here's how to do it. First, we create a new ConsoleFunction
ConsoleMethodWithDocs(CompositeSprite, readImage, ConsoleBool, 3, 3, ())
{
...
}

In this Method, the 1 argument is the AssetID of type "MyModule:spaceship".

We start by getting the Asset and getting the Texture which it points to :
const char* test = argv[2];
ImageAsset *Image_Asset = AssetDatabase.acquireAsset<ImageAsset>(test);
TextureHandle tex = Image_Asset->getImageTexture();

We then load the image file into a GBitmap pointer :
GBitmap* bmp = NULL;
//Ugly piece of code, that...
bmp = bmp->load(tex.getTextureKey());

I shall spare you the for loop. Let's focus instead on how to read a color from the Image file. Variables x and y represent the pixel coordinates in your image file.

We simply set the color of the SpriteBatchItem to the color of the corresponding pixel in our image file.

ColorI col;
ColorF color2;

bmp->getColor(x, y, col);
color2 = col;

object->selectSpriteId(sprite_id);
object->setSpriteBlendColor(color2);

Note that setSpriteBlendColor takes only a ColorF, the elements of which are of type F32. Conversely, bmp->getColor returns a ColorI. Lucky for us, ColorI can be converted to ColorF with a simple "=" sign.

Of course, the saved PNG file is not 32x32, so the images created that way cannot be easily re-submitted for editing via the CompositeSprite.

- Conclusion

There you have it, a relatively easy way to enable Spriting capabilities in your T2D projects.
Normally, this would all be done with Shaders but once again, T2D proves that its flexibility circumvents all obstacles.

About the author

I am here to help. I've worked at every imaginable position in game development, having entered the field originally as an audio guy.


#1
08/06/2014 (10:01 pm)
So when can we pre-order your pixel art editing program? :-) Cool stuff, always neat when you stumble upon this sort of functionality in the source and then come up with a clever way to use it.
#2
08/07/2014 (2:44 am)
Not going to make a full-fledged pixel art program, sorry Mike.

-Fun Fact of the day-
I took inspiration from Castlevania : Portrait of Ruin on the Nintendo DS, where you could design your emblem to identify your save game.