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…
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.
No, TCastleScene is a good solution. I just don’t have a spritesheet 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 - I have a good idea how to construct this thing myself, but not how to modify an existing instance.
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.
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.
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
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.
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.
This may be or may not be what you need, I guess you need to experiment 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 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.
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 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 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.
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.
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.
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.
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