Play a certain animation from a sprite sheet

I create a spritesheet with different animations and its relative xml file. From the xml I get via code all the necessary data (animation name, frame size, sequence of images for each animation, etc.) and I display the animations found in the sheet in a TComboBox.
I would like to allow the user to choose and view a certain animation or possibly all in succession.

I use:
Player := TSprite.CreateFrameSize(MainImage,
FrameCount,
Columns,
HorzSizeFrame,
VertSizeFrame,
True,
False);

I see that perhaps it would be possible to use SwitchToAnimation but from my code of a previous version of CGE I was using Player.CurrentAnimation.Play which, however, currently seems incorrect.

What could be the right way to view animations by defining the starting and ending frame?

Maybe TCastleScene could also be used but for now my only need is to show an animation in a TCastleControlBase.
Currently then I load the whole spritesheet with TSprite.CreateFrameSize, from the xml file I get the succession of animations and in a for loop I add the animations to the Player with Player.AddAnimation(frames).

When I change animation through TComboBox I use Player.SwitchToAnimation(n) and if I want to show them all in sequence Player.SwitchToAnimation(-1).

Am I on the right way?

Question: I see from the API that it is not possible to assign FramePerSecond to an animation added using AddAnimation. Would it be possible to define its duration?

update:
The only way I’ve found to affect animation speed would be

procedure TMainForm.CastleControlBase1Update(Sender: TObject);
var
SecondsPassed: TFloatTime;
begin
if Assigned(Player) then
begin
// when I change FramePerSec I update the MyNewValue variable := (1 / (FrameCount / FramePerSec))
SecondsPassed := CastleControlBase1.Fps.SecondsPassed * MyNewValue;
Player.Update(SecondsPassed);
end;
end;

It would seem to work but I wonder, isn’t it that I am writing useless code and with a simple function that I cannot find I could achieve all this?

With the current sprite API, that is using TSprite, you are on the right track. Things are a bit manual here indeed.

  • You switch animation with SwitchToAnimation

  • You can scale the time simply by providing a different value to Update(...)

  • Each animation also can have a different FPS at creation. You can add an animation using AddAnimation(const AAnimation: TSpriteAnimation) overload, which takes as argument your own TSpriteAnimation instance, which you can create like this (with explicit FPS specific to this animation):

    MyAnimation := TSpriteAnimation.CreateConstantFps(...);
    Sprite.AddAnimation(MyAnimation);
    

We are working on a new approach to sprites, Andrzej Kilijański is busy doing it. The first part is already a PR since yesterday: https://github.com/castle-engine/castle-engine/pull/218 . This will allow to load sprite sheet into TCastleScene, and use existing TCastleScene API to control animations, and also to put the animations on the scene using CGE visual editor. So it will be
a new workflow for sprites, much better and making the existing TSprite deprecated (but of course it will remain working for a long time, I know it is extensively used). More news about it are coming :slight_smile:

1 Like