Problem with a Typewriter function

Started by WiseFrog, Sun 25/02/2024 09:27:22

Previous topic - Next topic

WiseFrog

Hello everyone!

It's been a while since I've written on these forums, but I'm back with this wonderful program called AGS.

I'm a little rusty with the scripting part of AGS, so I want to ask for help

I'm trying to write a function to type text like a typewriter.

I have two problems with my current code:
1) I need to press any key (such as the mouse button) to skip the text and appear the next word (character).
2) The function does not work in the global script to be called in any room, but if you write the code in the room script, it works fine.

The code is the following:

Code: ags

function Typewriter(Character* ch, String text, int speed) {
    String textShow = "";
    for (int i = 1; i <= text.Length; i++) {
        textShow = text.Substring(0, i);
        Display(textShow);
        Wait(speed);
    }
}


And when I use the function for example when I look an object:

Code: ags
Typewriter(player, "Wow, Amazing", 10);

The function works fine, but I need to press a key, the text disappears and comes back with the next word, something like:
W
*presses a key*
*text disappears*
*text appears again*
Wo
*text disappears*
*text appears again*
Wow

Someone can help me with this?

Thanks in advance

eri0o

I think the best option would be using the Typewriter module instead

https://www.adventuregamestudio.co.uk/forums/modules-plugins-tools/module-typedtext-0-7-0/

I think someone can eventually come up with some short minimum way of doing it here but in my previous attempts I ended up eventually switching to using this module instead.

I think there are some examples with the module so you can replicate and try it.

I used previously in a few small games I made, here's using it in the Don't Give Up the Cat, along with a lot of customization going on together.

https://github.com/ericoporto/dont-give-up-the-cat/blob/fc2810d9d580f6e1b51742489fa388fbd96cdbd0/dont-give-up-the-cat/CustomSay.asc#L48-L59

Khris

The main problem is the display command, which pauses the game until you press a key or mouse button.
If you use a GUI and a label instead, it'll work as expected.

Crimson Wizard

Yes, what Khris said, Display is for showing blocking text only, for non-blocking display there are several variants:
- GUI with a label;
- textual Overlays;
- drawing over a DrawingSurface (like, on a sprite, or room background);

WiseFrog

Quote from: eri0o on Sun 25/02/2024 12:41:43I think the best option would be using the Typewriter module instead

https://www.adventuregamestudio.co.uk/forums/modules-plugins-tools/module-typedtext-0-7-0/

Hey, thanks for the recommendation!

I tried to use that module before but I don't really understand how to use it correctly.

I will try to give it a second chance

Quote from: Khris on Sun 25/02/2024 13:10:04The main problem is the display command, which pauses the game until you press a key or mouse button.
If you use a GUI and a label instead, it'll work as expected.
Quote from: Crimson Wizard on Sun 25/02/2024 18:17:23Yes, what Khris said, Display is for showing blocking text only, for non-blocking display there are several variants:
- GUI with a label;


This worked like a charm but now I have a problem that I tried to fix it but I can't

My code is the following right now:

Code: ags
bool keyPressed = false;

bool IsAnyKeyPressed() {
    int i = eKeySpace; 
    while (i <= eKeyUnderscore) { 
        if (IsKeyPressed(i)) return true;
        i++;
    }
    return false;
}

function WaitUntilKeyPressed() {
    while (!IsAnyKeyPressed()) {
        Wait(1);
    }
}

function Typewriter(Character* ch, String text, int speed) {
    String textShow = "";
    gText.Visible = true;
    for (int i = 1; i <= text.Length; i++) {
        textShow = text.Substring(0, i);
        lText.Text = textShow;
        Wait(speed);
        
        if (IsAnyKeyPressed()) {
            keyPressed = true;
            break;
        }
    }
    
    if (!keyPressed) {
        lText.Text = textShow;
    }
    
    WaitUntilKeyPressed();
    gText.Visible = false;
}

This works "fine", the typewriter effect is shown in the gui and after pressing a button the GUI disappears, but I want this: if you press a button it overrides the effect and shows the full text. Also, when the full text is displayed, you have to press another button to make the GUI disappear.

eri0o

#5
I did this effect using the tty module in Don't Give up the Cat where I pointed it out.

In your code, just before WaitUntilKeyPressed (line 35 above), put a wait, and wait for something around 300ms, which if it's a 60fps game it would be around 20 game loops (Wait(20)). I think the problem is the debounce of IsKeyPressed which checks if a key is pressed and hold.

The Wait page in the manual has some interesting alternatives too

https://adventuregamestudio.github.io/ags-manual/Globalfunctions_Wait.html

It now returns the why (button press + which button and similar) the wait was skipped.

You can then filter keys if you like (example), but in the manual it goes in more details.

I think the approach you did should work after you add a small wait time, but just in case you need different types of wait for key later, it's an useful information - this was a change in AGS 3.6.0.

WiseFrog

#6
Quote from: eri0o on Sun 25/02/2024 22:33:58In your code, just before WaitUntilKeyPressed (line 35 above), put a wait, and wait for something around 300ms, which if it's a 60fps game it would be around 20 game loops (Wait(20)). I think the problem is the debounce of IsKeyPressed which checks if a key is pressed and hold.
Hey, thanks for the response!
Adding that worked great, but sometimes it recognize the key pressed and sometimes you need to press the key 2 or 3 times. I will check the new wait functions, maybe I can fix it changing my code with that

Quote from: eri0o on Sun 25/02/2024 22:33:58I did this effect using the tty module in Don't Give up the Cat where I pointed it out.
I will try this module, maybe is more easy for me instead of trying my own code

Crimson Wizard

#7
Quote from: WiseFrog on Sun 25/02/2024 20:26:51I tried to use that module before but I don't really understand how to use it correctly.

To be fair, that module's organization and explanation may be complicated, it was not the most successful module design, and I have this problem that I tend to document things in overly technical manner... Maybe it has to be rewritten.

I suggest to skip to TypedTextHelper description, and stick to using its functions.
I think that in your case it might be something like:

Code: ags
int tw_id = lText.Typewriter(text, eNoBlock);
// Wait while typewriter is running and no mouse or key is pressed by player
while (TypewriterRunners.IsActive[tw_id] && WaitMouseKey(1) == 0) { }
// Interrupt typewriter if it was still running
if (TypewriterRunners.IsActive[tw_id])
    TypewriterRunners.Cancel(tw_id);


But then, your own code seems almost working, except you do not have to write your own WaitUntilKeyPressed, and just use existing WaitMouseKey or WaitInput AGS function.

SMF spam blocked by CleanTalk