Hi!
I want to display a string, not at once but like a typewriter, so character by character.
I have the following procedure that works okay but it displays the whole string because there is no delay between the typing.
How can I get this to work by using a Timer so the procedure will be called every 2 seconds to add a new character of the string?
procedure TViewMain.DisplayStringByChar(TextToDisplay: string);
var
i: Integer;
begin
TextLabel.Caption := '';
for i := 1 to Length(TextToDisplay) do
begin
TextLabel.Caption := TextLabel.Caption + TextToDisplay[i];
end;
end;
Note that you don’t need a special timer (TypingTimer) in @eugeneloza example, at least in such simple case Instead you get the SecondsPassed in Update. So something like this may be easier:
type
TTypingLabel = class(TCastleLabel)
strict private
// float type, increased each frame
DisplayChars: TFloatTime;
public
procedure Update(const SecondsPassed: Single); override;
end;
procedure TTypingLabel .Update(const SecondsPassed: Single); override;
const
TypingSpeed = 40; // symbols per second
begin
inherited;
DisplayChars := TypingSpeed * SecondsPassed;
MaxDisplayChars := Trunc(DisplayChars);
end;
Alternatively, you can use regular TCastleLabel (advantage: you can easily place it at design-time, and no need CGE “custom components”) and modify it from outside in your view. Like
type
TViewMain = ...
published
MyLabel: TCastleLabel;
strict private
// float type, increased each frame
DisplayChars: TFloatTime;
....
public
procedure Update(const SecondsPassed: Single; var HandleInput: Boolean); override;
end;
procedure TViewMain.Update(const SecondsPassed: Single; var HandleInput: Boolean);
const
TypingSpeed = 40; // symbols per second
begin
inherited;
DisplayChars := TypingSpeed * SecondsPassed;
MyLabel.MaxDisplayChars := Trunc(DisplayChars);
end;
Note: Above code was untested, but it will hopefully be enough to get you started
I did not get it to work, maybe because of the other stuff I already had put in the label and using Trunc was way too fast, the string was gone in a flash.
Then I remembered an old topic where eugeneloza gave me a tip about timed events and disappearing label after showing text.
I used this and expanded it and with a little additional help by ChatGPT I finally got this:
TAdvancedLabel = class(TCastleLabel)
public
Timeout: Single;
DisplayCharacters: Integer;
CurrentIndex: Integer;
procedure Update(const SecondsPassed: Single;
var HandleInput: boolean); override;
end;
TViewMain = class(TCastleView)
published
TextLabel: TAdvancedlabel;
private
message: String;
end;
procedure TAdvancedLabel.Update(const SecondsPassed: Single;
var HandleInput: boolean);
begin
Timeout -= SecondsPassed;
if CurrentIndex < Length(ViewMain.Message) then
begin
Inc(CurrentIndex);
ViewMain.TextLabel.Caption := Copy(ViewMain.Message, 1, CurrentIndex);
end;
if Timeout < 0 then
begin
Text.Clear;
CurrentIndex:= 1;
end;
end;
And now the text is scrolling from first to last character allright and also disappears after a few seconds.
I am now expanding this with an up and down moving textbar as long as there is a “conversation”.
When it is finished I will put it here in a Youtube video.