Build (or combine) and tint sprites (or change its colours)

I’ve finally learned how to use sprites (2D game objects, you know). Now I’m wondering how to do two different effects or techniques for a game idea I have.

  • Is there a way to “build” a sprite? I mean, I have a sprite sheet for each of the character part (body, hair, cloth/armour, weapon) and I can render it by staging them, but is there a way to combine different sprite sheets in a single one (or different bitmaps in a single one)?
  • Also is there a way to change a colour or tint a sprite? For example, let the player select the colour of the hair, or change the cloth colour depending on the team.

I know I can accomplish this by building different assets for different cases, but it may be a LOT of combinations…

1 Like

Depends on how exactly you want to handle sprites. 2D sprites built in Spine (to my limited knowledge) have a property of “skin” where the skin is one or more textures which is chopped into parts and can be attached to the sprite skeleton. I don’t have an example of this, but I’m 93% sure I saw it somewhere.

If you have a sprite as an image or a set of images - then you’ll need to handle bodyparts differently to colorize them.

One of the options is just to render them one on top of other (e.g. eyes on top of the head). This is quite efficient. You just draw a stack of a few TDrawableImage or TShape with a proper TImageTextureNode. You can use TDrawableImage.Color to tint it, just be careful - in case of batching or reusing the image all instances will share the same Color value.

If you want to go “even further”, you can merge them into a single texture/spritesheet. This is how I do this in my game: code/actors/inventory/gamepaperdollsprite.pas · grandmaster · EugeneLoza / Vinculike · GitLab where DrawFromColorized is a TRGBAlphaImage helper implemented in code/utils/gamedrawfromcolorized.pas · grandmaster · EugeneLoza / Vinculike · GitLab ---- this is a very inefficient way of doing that, but ok for my goals (changes only once when the player changes equipment). This solution is executed on CPU. As the name suggests, it’s just a tweaked TCastleImage.DrawFrom (see Castle Game Engine: CastleImages: Class TCastleImage) and if you don’t need colorization then you can just use that one.

1 Like

I plan to use TCastleScene referencing the spritesheet using its url property.

Maybe I should learn and test TDrawableImage and use it the way you do. But then I should manage animations and maybe collisions in a different way…

No, TCastleScene is a good solution. I just don’t have a spritesheet :smiley: So I’m re-inventing the wheel.

However, it’s a bit more complicated to work with TCastleScene for this specific task (have a designed sprite sheet + modify colors of its components). Overall, you can load your spritesheet as TX3DRootNode through LoadNode (was Load3D). Then scan this node for TPixelTextureNode (see Castle Game Engine: X3DNodes: Class TPixelTextureNode) and manipulate the texture inside as you see fit. E.g. you can adjust its TextureProperties, see Castle Game Engine: X3DNodes: Class TTexturePropertiesNode), however, I can’t find Color property of it, maybe I’m looking at the wrong place.

However, as a very generic solution I don’t know how exactly to detect the bodyparts (like hat or eye color) inside there, and I don’t think I’ve ever used this approach myself successfully, so someone smarter than me could help here more :slight_smile: - I have a good idea how to construct this thing myself, but not how to modify an existing instance.

Ok, I see. Thanks. I’ll take a look in the documentation you linked.

[Edit]
I think that isn’t the solution. As you said there’s no Color nor Tint properties.

Something like Allegro’s al_draw_tinted_bimap should work.

Yes, TDrawableImage has Color property, and I’m almost sure TImageTextureNode also had something like that, I just couldn’t find it.

Finally you can attach a shader there which can do a lot of additional processing (not just change tint). See Castle Game Engine: X3DNodes: Class TEffectNode — again, I know how to do that when constructing the node by code - when working with an existing sprite it may become tricky. You can find an example here examples\viewport_and_scenes\shader_effects

Update: I see the example has a good explanation how to inject the effect properly to affect the whole scene. But you’ll need to inject the effect “deeper” in the node structure to apply different tints to different textures.

Use TDrawableImage to draw by yourself,no restraint, unlimited possibility

1 Like

If it is a pixel-art game, it is very simple. You can add multiple child controls (sprites) to TCastleScene (sprite), such as hair, clothes, pants. The only requirement is that the animation of these sprites must be synchronized.

1 Like

I will first answer this question, as it’s easier :slight_smile:

To change the color of the sprite sheet loaded to TCastleScene:

Find the TUnlitMaterialNode within the scene RootNode, and change the TUnlitMaterialNode.EmissiveColor property. This exactly does simple multiplication of the texture, much like tint or TDrawableImage.Color.

In the general case, you can have multiple materials, with varying types (TUnlitMaterialNode, TPhysicalMaterialNode, TMaterialNode) but when loading a sprite sheet, you can assume you have exactly 1 node of TUnlitMaterialNode, so it’s simple.

This is fast, there’s no need to deal with shader effects and explicit GLSL code, and no need to go with lower-level TDrawableImage :slight_smile:

This is an example code to do this, it even checks that there’s indeed exactly 1 node of TUnlitMaterialNode:

var
  Mat: TUnlitMaterialNode;
begin
  if Scene1.RootNode.NodesCount(TUnlitMaterialNode, false) <> 1 then
    raise Exception.Create('A loaded sprite sheet should have exactly 1 instance of TUnlitMaterialNode');
  Mat := Scene1.RootNode.FindNode(TUnlitMaterialNode, '') as TUnlitMaterialNode;
  Mat.EmissiveColor := Vector3(1, 1, 0); // yellow
end;

I just tested it with CGE “examples/sprite_sheets/sprite_sheets_demo/code/”. Use the attached code for “examples/sprite_sheets/sprite_sheets_demo/code/gameviewmain.pas”, run the example, press C to see the left scene changing color to yellow-ish.

gameviewmain.pas (2.9 KB)

One of our important planned features for engine 7.0 release is to make such material management easier – see some of my plans attached to this comment [Feature request] Images receiving lights · Issue #431 · castle-engine/castle-engine · GitHub , I’ll also post a short video (“post DelphiCon 2023 notes”) where I’ll talk about engine 7.0 plans a bit around this weekend. Underneath, the new material components will be able to do same thing as above (just modify EmissiveColor of unlit material) and much more, they will also be more “discoverable” with easier API, you will not need to deal with X3D nodes and you will be able to test it in CGE editor.

Hm, depending on what you mean here.

You can of course build a hierarchy of TCastleScene, with one TCastleScene being a child of another and another. And each TCastleScene can be a different sprite sheet. But I guess this isn’t what you need – as it means you don’t have any bones that control the animation of child sprite sheets.

In general, what you describe sounds like something done by 2D sprite animation authoring tool – and indeed Spine can do this ( Spine - 2D Animations | Creating Game Data | Castle Game Engine ) and much more. It allows to design a skeletal animation, and to each bone you can attach an image or a series of images. It also supports skins. You can export “Spine JSON” from it, which CGE can read and animate. Note that Spine is a commercial software, though there is a free alternative ( Exporting from Dragon Bones | Castle Game Engine ) but I’m not sure if it’s equally capable.

Also each bone is a transformation – which means you could even export from Spine a “naked” model and use TCastleScene.ExposeTransforms (se Castle Game Engine: CastleSceneCore: Class TCastleSceneCore , Attach objects to (animated) bones, like weapon in character’s hand, by ExposeTransforms – Castle Game Engine ) to attach TCastleScene with a sprite sheet to each animated bone. So there are at least 2 ways to utilize Spine for this task: either create your animation in Spine completely, or use Spine only to create and export your animated bones (and attach their visual look in CGE, as child scenes).

This may be or may not be what you need, I guess you need to experiment :slight_smile: There are more manual approaches possible – in particular you can even draw with CGE the sprite sheets yourself (using TCastleImage drawing routines) and construct sprite sheet by code yourself using CastleInternalSpriteSheet . But this admittedly gets more and more involved :slight_smile: We do not have a ready solution to “bake” multiple sprite sheets into one, as you describe – I would say that, from a general sprite sheet, CGE doesn’t even have enough information to make such baking.

Hopefully these answers help :slight_smile:

2 Likes

I tried to use it 2-3 times and it was a total failure. First time I just ended up editing the JSON file manually, because I couldn’t figure out how to simply move a point/line in their editor - it was simpler to figure it out in a messy JSON. I figured out how to import an SVG file into Blender (what is technically not exactly supposed to), fix z-fighting and make a simple animation, so it’s not that I’m all that dumb :slight_smile: but Dragon Bones has a very steep learning curve.

And the final dot was when they denied of service as their website was down to validate the “free license” with all error messages in Chinese. You just randomly get locked out, not something you’d want in production. I have no idea why nobody would fork it to remove this spyware/bloatware (like vscodium). May also speak about it’s usefulness, though.

Last commit to Dragon Bones repository on GitHub is in 2020… Which also isn’t good.

I have on my to-do list to try https://www.synfig.org/ but didn’t get to it so far. Ok… so today is the day :smiley: Outcome of quick testing - it’s only a tool for vector animation, it has “Loliette” plugin to export for web which produces JSON among other stuff, but it crashes even on simple projects and there doesn’t seem to be any plans for a good official rasterizer & exporter.

And just for completeness: Enve. Doesn’t seem to support boned animation, doesn’t export into JSON.

Thanks everybody for the answers, I’m learning a lot. :slight_smile:

That’s just what I was looking for. I knew it was possible without using GLSL. I think I’ll be able to get the effect I’m looking for with some experimentation.

I’ve found almost everything except CastleInternalSpriteSheet. Is it a function, a class or a tool? Where is its documentation?

Thanks for testing Dragon Bones. I tested it a while (few years) ago, and I was able to do basic skeletal animation in 2D similar to Spine, so it seemed like a viable alternative at least for some uses. Now, the website seems so broken I cannot even download it anymore. Hm, in light of this → I cannot really recommend using Dragon Bones anymore (I removed some links to them from our website).

I guess in this light, I would recommend to do 2D skeletal animation in

  • Spine.

  • or just in Blender.

    While Blender is directed at 3D, you can just design 2D skeletal animation and export to glTF.

It’s a unit in Castle Game Engine. There is no official documentation, just the source code – because, as the name says, it is “internal”, which means it is only supposed to be used by other engine units and not really by your own code. We may remove / change the API of that unit at any point. This is an alternative I placed here as “a last resort” – you can use the Castle Game Engine code to construct sprite sheets, even though we don’t recommend it, we cannot guarantee that this API will stay stable.

2 Likes

I see. So it is “Use it at your own risk” kind. Anyway since Castle is able to load sprite sheets I would assume that such thing should be quite stable or it will be as long the functionality exists in the engine, so I think I’ll take the risk.

Thankyou very much.

I also encountered this problem.I deeply understand the design requirements of NiunioMartinez

Michael’s approach does not solve the problem.

TUnlitMaterialNode.EmissiveColor seems that the function of replacing colors cannot be achieved

This exactly does simple multiplication of the texture, but I need the function of replacing colors, not mixing

2D games are really extraordinary in using replacement colors, and the engine should provide this common feature

94
95
96
93

Unless you go with color palette like good old pixel games, color multiplication is the way to go for games that provide you the way to change colors. You usually provide your models with grayscale textures so that they take the exact color you want when you multiply it with emissive color.

Take a look at PSO2: https://www.youtube.com/watch?v=8KVJ7xpV1qk, which is well know for it’s character creation feature, and how the character’s textures look like:

Thank you for your idea. Change the original color of the material to avoid the shortcomings of CGE functionality

Changing the TUnlitMaterialNode.EmissiveColor indeed multiplies the color. This is the standard operation to influence something with color, and I’d say the simplest approach to “tint a sprite” as asked in this thread some time ago :slight_smile:

If you want to apply a different color effect, you can – use the Effect nodes to implement any sort of effect using GLSL. This way you can mix the colors with any equation you want – multiply, max, sum, implement any GIMP/Photoshop layer equation (https://printtechnologies.org/wp-content/uploads/2020/03/pdf-reference-1.6-addendum-blend-modes.pdf ) etc. See examples\viewport_and_scenes\shader_effects\ for an example, see Shader Effects (Compositing Shaders) | Castle Game Engine for reference.

Thank you, michalis

I have found a solution for cge

Add shaders to each TDrawableImage object to perfectly control the desired color


1 Like