Thanks. But then I thought it would be easier to load all animations once and then play a range by setting the first animation and last animation, because else I would have to make Runanimation lists of every possible ‘turnaround’ sequence.
I have now made this: it loads all animations and they get a number. Then it searches for the first (which is the current) and last animation and plays all animations between until it reaches the last set animation. This works okay, except it makes the character sprite turn the longest “route.”
For instance ‘standfront’ is the first animation in the list: 0
So if the sprite has to turn from 'standse (facing southeast) to standfront, it should play forward (clockwise).
But it does not because 'standse’ has number 14 in the list, so it plays backward (counterclockwise).
So if the LastAnimation is close to FirstAnimation it should take a ‘short turn’ instead of turning the sprite all around.
So I guess there should be something edited in the SetAnimationRange procedure to achieve this.
Any idea?
type
TStateMain = class(TUIState)
private
Viewport: TCastleViewport;
AnimList: TStrings;
FirstAnim, NextAnim, LastAnim: Integer;
StopAnim: Boolean;
FirstName: string;
FirstAnimationName, LastAnimationName: String;
PlayForward: Boolean;
procedure SetAnimationRange;
procedure StandSW(Sender: TObject);
procedure StandLeft(Sender: TObject);
procedure StandNW(Sender: TObject);
procedure StandBack(Sender: TObject);
procedure StandNE(Sender: TObject);
procedure StandRight(Sender: TObject);
procedure StandSE(Sender: TObject);
procedure StandFront(Sender: TObject);
procedure RunNextAnimation(const Scene: TCastleSceneCore; const Animation: TTimeSensorNode);
public
constructor Create(AOwner: TComponent); override;
procedure Start; override;
procedure RunAllAnimations(const Scene: TCastleSceneCore);
procedure RunAnimationList(const Scene: TCastleSceneCore; const AnimNames: array of String);
end;
var
StateMain: TStateMain;
Button1, Button2, Button3, Button4, Button5, Button6, Button7, Button8: TCastleButton;
Label1, Label2: TCastleLabel;
Scene1: TCastleScene;
implementation
uses SysUtils;
{ TStateMain ----------------------------------------------------------------- }
constructor TStateMain.Create(AOwner: TComponent);
begin
inherited;
DesignUrl := 'castle-data:/gamestatemain.castle-user-interface';
end;
procedure TStateMain.SetAnimationRange;
var A, B: Integer;
List: array[0..20] of string;
begin
AnimList := Scene1.AnimationsList;
For A := 0 to AnimList.Count-1 do
begin
List[A] := AnimList[A];
if List[A] = FirstAnimationName then FirstAnim := A;
end;
For B := 0 to AnimList.Count-1 do
begin
List[B] := AnimList[B];
if List[B] = LastAnimationName then LastAnim := B;
end;
if FirstAnim > LastAnim then PlayForward := False;
if FirstAnim < LastAnim then PlayForward := True;
NextAnim := FirstAnim;
end;
procedure TStateMain.Start;
begin
inherited;
Viewport := DesignedComponent ('Viewport') as TCastleViewport;
Button1 := DesignedComponent('Button1') as TCastleButton;
Button2 := DesignedComponent('Button2') as TCastleButton;
Button3 := DesignedComponent('Button3') as TCastleButton;
Button4 := DesignedComponent('Button4') as TCastleButton;
Button5 := DesignedComponent('Button5') as TCastleButton;
Button6 := DesignedComponent('Button6') as TCastleButton;
Button7 := DesignedComponent('Button7') as TCastleButton;
Button8 := DesignedComponent('Button8') as TCastleButton;
Button1.Caption := 'standsw';
Button2.Caption := 'standleft';
Button3.Caption := 'standnw';
Button4.Caption := 'standback';
Button5.Caption := 'standne';
Button6.Caption := 'standright';
Button7.Caption := 'standse';
Button8.Caption := 'standfront';
Button1.OnClick:= @StandSW;
Button2.OnClick:= @StandLeft;
Button3.OnClick:= @StandNW;
Button4.OnClick:= @StandBack;
Button5.OnClick:= @StandNE;
Button6.OnClick:= @StandRight;
Button7.OnClick:= @StandSE;
Button8.OnClick:= @StandFront;
Scene1 := DesignedComponent('Scene') as TCastleScene;
Viewport.Items.Add(Scene1);
Scene1.Translation:= Vector3(800,300,0);
FirstName := 'john';
Scene1.URL:= 'castle-data:/' + FirstName + '_idle.starling-xml';
FirstAnimationName := FirstName + 'standfront';
FirstAnim := 0;
SetAnimationRange;
end;
procedure TStateMain.StandSW(Sender: TObject);
begin
LastAnimationName := FirstName + Button1.Caption;
SetAnimationRange;
RunAllAnimations(Scene1);
end;
procedure TStateMain.StandLeft(Sender: TObject);
begin
LastAnimationName := FirstName + Button2.Caption;
SetAnimationRange;
RunAllAnimations(Scene1);
end;
procedure TStateMain.StandNW(Sender: TObject);
begin
LastAnimationName := FirstName + Button3.Caption;
SetAnimationRange;
RunAllAnimations(Scene1);
end;
procedure TStateMain.StandBack(Sender: TObject);
begin
LastAnimationName := FirstName + Button4.Caption;
SetAnimationRange;
RunAllAnimations(Scene1);
end;
procedure TStateMain.StandNE(Sender: TObject);
begin
LastAnimationName := FirstName + Button5.Caption;
SetAnimationRange;
RunAllAnimations(Scene1);
end;
procedure TStateMain.StandRight(Sender: TObject);
begin
LastAnimationName := FirstName + Button6.Caption;
SetAnimationRange;
RunAllAnimations(Scene1);
end;
procedure TStateMain.StandSE(Sender: TObject);
begin
LastAnimationName := FirstName + Button7.Caption;
SetAnimationRange;
RunAllAnimations(Scene1);
end;
procedure TStateMain.StandFront(Sender: TObject);
begin
LastAnimationName := FirstName + Button8.Caption;
SetAnimationRange;
RunAllAnimations(Scene1);
end;
procedure TStateMain.RunNextAnimation(const Scene: TCastleSceneCore; const Animation: TTimeSensorNode);
var
NextAnimationName: String;
Params: TPlayAnimationParameters;
begin
if StopAnim then
begin
FirstAnim := NextAnim; // remember the index value of LastAnimationName so next call to RunAnimationList will start from this animation
FirstAnimationName := LastAnimationName; // next call to RunNextAnimation should start with this animation
StopAnim := False; // reset
Exit;
end;
NextAnimationName := AnimList[NextAnim];
if NextAnimationName = LastAnimationName then StopAnim := True else
begin
if PlayForward then Inc(NextAnim);
if PlayForward = False then
begin
if NextAnim = 0 then NextAnim := AnimList.Count;
Dec(NextAnim);
end;
end;
Params := TPlayAnimationParameters.Create;
try
Params.Name := NextAnimationName;
Params.Forward:= PlayForward;
Params.StopNotification := @RunNextAnimation;
Scene.PlayAnimation(Params);
finally FreeAndNil(Params) end;
end;
end.