X3d sprite as TCastleScene

Using the 2d_dragon_spine demo as an example I created a new application under Lazarus with the CasteControlBase component.
Instead of the dragon I loaded a sprite converted to x3d.
I have two questions:
I use the OnPress event to detect the mouse click and OnUpdate to check when the sprite has reached the target (like dragon spine does).
Randomly in the transition from walking to idle I get a flash and I can see the rectangular frame of the sprite for a moment. This does not happen from idle to walk.
Is it maybe needed to do some operations before the transition?
Note that I load the animation at that moment. I have a sprite sheet for each of them and I don’t know yet if it is possible to preload them all in the initialization phase.

Is there a demo application to use as a hint that shows a possible way to change the animations according to the direction of the character?

Thanks

Randomly in the transition from walking to idle I get a flash and I can see the rectangular frame of the sprite for a moment. This does not happen from idle to walk.

If you load the scene right before calling PlayAnimation, then heed the PlayAnimation warning in docs: https://castle-engine.io/apidoc-unstable/html/CastleSceneCore.TCastleSceneCore.html#PlayAnimation :

Calling this method does not change the scene immediately . There may be a delay between calling PlayAnimation and actually changing the scene to reflect the state at the beginning of the indicated animation. This delay is usually 1 frame (that is, the scene is updated at the next Update call), but it may be larger if you use the optimization AnimateSkipTicks.

This is often a desirable optimization. There’s often no “rush” to visually change the animation right now , and doing it at the nearest Update call is acceptable. It also means that calling PlayAnimation multiple times before a single Update call is not expensive.

If you really need to change the scene immediately (for example, because you don’t want to show user the initial scene state), simply call ForceInitialAnimationPose right after PlayAnimation.

So call ForceInitialAnimationPose after PlayAnimation.

If this is not your case, then I don’t know what is the cause. Please submit a testcase (compileable simple project to reproduce the problem).

Note that I load the animation at that moment. I have a sprite sheet for each of them and I don’t know yet if it is possible to preload them all in the initialization phase.

A sprite sheet is just an X3D file after being converted by sprite-sheet-to-x3d. You can just create and load the scenes at loading. If you need to have multiple instances of the sprite, you can create one “template” scene and copy it using TCastleScene.Clone.

Is there a demo application to use as a hint that shows a possible way to change the animations according to the direction of the character?

There isn’t really much to show :slight_smile: You just use PlayAnimation with any parameter you want :slight_smile: Everything in the manual about TCastleScene is applicable in this case, https://castle-engine.io/manual_scene.php .

1 Like

yes, this call was required

I meant how to detect the direction of the character immediately after the mouse click to assign the correct animation to it (e.g. upright … downleft … etc).
I already use my own algorithm, just wanted to see if it was possible to optimize it by comparing other methods …

I use e.g. Player.Load (‘castle-data: /sprite/DownLeft.x3d’);
then Player.PlayAnimation(‘DownLeft’, true);
Maybe I didn’t understand but if I load all the animations at the same time (left, right, up ecc.), only the last one loaded will be available?
In this case I should have all the animations in the same spritesheet.

I already use my own algorithm, just wanted to see if it was possible to optimize it by comparing other methods …

Oh OK. We don’t have anything special to help with this in CGE.

You usually just have a “target” position (which can be TVector2 in case of 2D games), and “current” position. You can simply subtract them and check, e.g. you know it’s a “move to the right” if Target.X - Current.X > 0.

I use e.g. Player.Load (‘castle-data: /sprite/DownLeft.x3d’);
then Player.PlayAnimation(‘DownLeft’, true);
Maybe I didn’t understand but if I load all the animations at the same time (left, right, up ecc.), only the last one loaded will be available?

I’m not sure what do you mean by “last one loaded will be available” :slight_smile: A single TCastleScene may contain multiple animations (like “move left”, “move right”). At a given moment it plays one animation (the one indicated by PlayAnimation call).

( It is in fact possible to play multiple animations, see simultaneous_animations_one_scene example. But I only mention this for completeness, if is usually not needed, and it requires care when setting up scene information for it to make sense. )

A single scene may even be visible multiple times in the viewport. The simple way to do this is to just add the scene instance multiple times using Viewport.Items.Add(MyScene), although this is also limiting — all instances of MyScene then play the same animation, see https://castle-engine.io/manual_scene.php#section_many_instances . If it is necessary to instead see the same object multiple times, but with different animation, then you can load it once to TCastleScene (MyScene.Load(...)), and then create more scenes using NewScene := MyScene.Clone(Application);

In this case I should have all the animations in the same spritesheet.

It is indeed usually more comfortable to have one larger scene with multiple animations. It’s easier to manage it this way, as you load it once, and then just use PlayAnimation.

P.S. The approach to use TCastleScene.Clone is used e.g. by https://github.com/castle-engine/wyrd-forest .

Sorry but it is this part that I cannot understand.
Let’s say I only have two animations, one for the right and one for the left in two different spritesheets.
For example, if I load both animations in initialization phase with Player.Load (Left.x3d) and immediately after Player.Load (Right.x3d) the spritesheet with the Left animation has not been overwritten by the second one? Or am I misunderstanding?

Got it. The misunderstanding comes from the fact that we think about a little different usage :slight_smile: So we probably visualize the scenes a bit differently in our heads :slight_smile: Sorry, and let me try to clarify:

  1. In your case you think about PlayerLeft.x3d with just one animation "Left", and then PlayerRight.x3d with just one animation "Right".

  2. While I think instead of Player.x3d with 2 animations "Left" and "Right".

Both approaches make perfect sense. IOW, you can

AD 1. Put each animation in new sprite sheet (so you call sprite-sheet-to-x3d once for each animation)

AD 2. Put multiple animations into one sprite sheet (one file processed by sprite-sheet-to-x3d, and result has multiple animations).

I advise AD 2 (it results in a bit simpler code, as you don’t need to toggle which scene exists, you only control which animation is playing). But in the end, really both approaches work.

My comments about “cloning” scenes (using TCastleScene.Clone), and in general most what we talk about in this thread, I think apply to both cases :slight_smile: Just a little bit differently – in one case you change a scene when you change animation (you can e.g. remove/add scenes at runtime from Viewport.Items, or use MyScene.Exists boolean), in the other case you only call PlayAnimation to change animation. Both approaches work and both are efficient.

This would be the best choice because as mentioned it would not be necessary to load a different spritesheet several times but I don’t think it’s really feasible.
Assuming you have a character like the one from your game THE UNHOLY SOCIETY (not a Pac-Man :slightly_smiling_face: ) with at least 15 frames for eight different directions + idle and obviously some other animation I don’t think it’s a good idea to put all the images together in one sheet.
in your opinion what could be the most correct size to not over-use memory and not to go beyond the capabilities of CGE?
Would it be better to evaluate the size of the spritesheet or the number of frames it contains? Do you have any suggestions based on experience?

As for suggested sprite sheet size, in general CGE supports whatever GPU supports, so even 8192 x 8192 works on desktops with latest GPUs.

But if you think about portability, in my experience it’s better to limit to 2048 x 2048 or (when justified) 4096 x 4096. Of course the smaller the better (less GPU memory consumed) so if you can fit into something even smaller -> that’s better.

Note that CGE will automatically handle the case when GPU doesn’t support a texture as large as you made. E.g. if you made 4096 x 4096 texture, but GPU only supports 2048 x 2048, then CGE will automatically scale it down. Everything will work the same, just the underlying texture will have less resolution.

Note also that you can use “downscaling” of textures, at runtime or pregenerated. This approach allows you to prepare textures in larger size, but then (maybe depending on platform) actually use smaller size in game. There are even 2 approaches for it:

  1. Prepare the smaller textures automatically by setting up proper material_properties.xml and running “castle-engine auto-generate-textures” . See https://castle-engine.io/creating_data_auto_generated_textures.php . Then in code you just set TextureLoadingScale

  2. Scale the textures at runtime by GLTextureScale

In “The Unholy Society” we used the 1st approach (TextureLoadingScale), and I advise it, it is more efficient. In “The Unholy Society” we also made 100% of animations using Spine skeletal animation, there are no sprites used. So we didn’t have to worry about sprite sheet size (although we did worry about Spine atlas size in turn).

1 Like