Hi. I want to make an animation with text that types itself out (like on a computer or typewriter) but can’t find a way to do that in Wick. I can make a for loop that iterates through each character, but I cannot get it to pause in between. (I found an example for web, but it won’t work in Wick).
since you say this is for a animation you can animate the text
Not sure what you mean? It’s a couple paragraphs worth, so there’s too much to make a new frame for each character.
Hey @KobatoGames! Sorry I didn’t see this earlier. Idk if you still need help here, but I’ll still break it down in case someone else has a similar question.
A for loop would pause the code until it’s fully executed. Rather, I suggest creating a timer variable and using that instead.
Create a text object, and name it anything. For the purpose of this quick example, I’ll call the text object “text
” but you can use another name.
Then, inside of the frame’s default script, you’ll want to create these default variables:
project.framesCount = 0;
project.textData =
`In here you can write the text that you want to be written...
This is just a string. You can also use "..." and '...' instead
but this way you can write multiple lines more easily like this
:P`
text.setText("");
project.framesCount
is going to be a variable that tracks the number of frames the project ran since it’s start. By default, project.framesCount
is set to zero.
Also project.textData
will be the text that you want to be written. It can be anything, just keep it a string.
The reason why we also add project.[...]
before these two variables is so that we can use them elsewhere in our project this way, even outside the default script where we defined them. Alternatively, you can also use window.[...]
if you want.
You also set the text to “” so that the text starts off empty.
Now… on to the update script – first thing, increase the project.framesCount
by 1 continuously.
// increase frame count
project.framesCount++;
Assuming your project is running at 12 FPS (this is adjustable through project settings), then after 1 second, the frame count will be 12. And it’ll be 24 after 2, and you get the idea. Every second, it’ll increase by 12.
If you want a letter to be written every second, then you’ll want to check every time the frames count goes over 12.
project.framesCount++;
if(project.framesCount >= 12){
// Reset the frames count
project.framesCount = 0;
// Any code you write here will run once every second
// ...
// ...
}
But in our case we’re assuming the FPS is 12. Rather than writing 12, you should use project.framerate
which is a built-in variable equal to the project framerate set in the project settings.
project.framesCount++;
if(project.framesCount >= project.framerate){
project.framesCount = 0;
// Any code you write here will run once every second
// ...
// ...
}
Alternatively, rather than checking everytime the frames count goes over the framerate and resetting it to zero, you can use the module %
operator to have the if
statement run whenever frames count is a multiple of the frame rate. I didn’t do this at first since it might be a bit more complicated to start with, but to put it simply, the %
will return the remainder you’d expect when dividing two numbers.
So 12/12 will return a remainder of 0, therefore 12%12 is zero. Same for 24%12.
I can explain why this works more in depths if you’re interested.
project.framesCount++;
if(project.framesCount%project.framerate === 0){
// Any code you write here will run once every second
// ...
// ...
}
Now we want to write the code that would type the text every second, one letter at a time.
Looking back at the code you shared… here’s a short snippet
if (i < txt.length) {
document.getElementById("demo").innerHTML += txt.charAt(i);
i++;
setTimeout(typeWriter, speed);
}
In our case, i
would correspond to the seconds since we want to increase the count every second, txt.length
is the length of project.textData
, and document.getElementById...
corresponds to the text object we created. We won’t need the setTimeout(...)
function since we already wait every 12 frames to run the code (you can multiple the framerate by the number of seconds you want if you want to increase the delay).
That aside, every time you want to type a character I would suggest to actually add the character to the text object and remove it from the project.textData
, that way we won’t need to keep track what letter we’re at, just how many characters are left in project.textData
.
project.framesCount++;
if(project.framesCount%project.framerate === 0){
// Any code you write here will run once every second
// this checks to see if there are any characters left
if(project.textData.length>0){
// add the first character to the text object
text.setText(text.textContent + project.textData.charAt(0));
// remove the first character in project.textData since we already wrote it
project.textData = project.textData.substring(1);
}
}
If this runs a bit slow, feel free to replace “project.framerate
” with a smaller number like 5
or 7
, or with a 1
if you want to disable the timer.
I advise against using a decimal value with the module % operator.
Funny enough I found that waiting a second actually takes too long, so you’re better off without the whole timer code but it’s still useful to understand.
To make it work without a timer
You’d just need to define project.textData
in the default script, create a text
object and set it to blank in default, and have this code in your update script:
// this checks to see if there are any characters left
if(project.textData.length>0){
// add the first character to the text object
text.setText(text.textContent + project.textData.charAt(0));
// remove the first character in project.textData since we already wrote it
project.textData = project.textData.substring(1);
}
Example file:
example type writer.wick (1.7 KB)
^ Note that this example runs at 60 FPS
Wow! Thank you so much for the detailed explanation. I had given up on finding help with the syntax for telling Wick to wait and managed to make a template where you declare the text string in the first frame and each seceding frame adds the next character. I had been coming back to share my template, though yours is probably much more efficient. I’ll go check it out.