Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# Manually stopping an asynchronous for-statement (typewriter effect)

Tags:

c#

.net

winforms

I'm making a retro-style game with C# .NET-Framework, and for dialogue I'm using a for-statement, that prints my text letter by letter (like a typewriter-effect):

enter image description here

I'm working with different scenes, and I have a skip button (bottom right) that skips the current dialogue and passes to the next scene. My typewriter-effect automatically stops when all the text is displayed, but when I click on the skip button, it automatically skips to the next scene.

I would like it, when the typewriter is still active, and if I click on the skip button, that it first shows all the text, instead of skipping to the next scene.

So that it only skips to the next scene when all the text is displayed (automatically or manually).

This is the (working code) that I'm using for my typewriter method (+ variables):

    public string FullTextBottom;     public string CurrentTextBottom = "";     public bool IsActive;          public async void TypeWriterEffectBottom()     {         if(this.BackgroundImage != null) // only runs on backgrounds that arent black         {             for(i=0; i < FullTextBottom.Length + 1; i++)             {                 CurrentTextBottom = FullTextBottom.Substring(0, i); // updating current string with one extra letter                 LblTextBottom.Text = CurrentTextBottom; // "temporarily place string in text box"                 await Task.Delay(30); // wait for next update                                  #region checks for IsActive // for debugging only!                  if(i < FullTextBottom.Length + 1)                 {                     IsActive = true;                     Debug1.Text = "IsActive = " + IsActive.ToString();                 }                 if(CurrentTextBottom.Length == FullTextBottom.Length)                 {                     IsActive = false;                     Debug1.Text = "IsActive = " + IsActive.ToString();                 }                  #endregion             }         }      } 

And this is the code that I want to get for my skip button (named Pb_FastForward):

    private void PbFastForward_Click(object sender, EventArgs e)     {         if( //typewriter is active)         {              //print all text into the textbox         }                  else if( //all text is printed)         {              // skip to the next scene         }     }    

But I don't know how to formulate the 2nd part of code. I've tried many different approaches, like using counters that increase on a buttonclick (and using that to check in an if-statement), and many different types of if-statements to see if the typewriter is still active or not, but I haven't got anything to work yet.

Edit

This is the sequence in which different components need to be loaded (on button click), which is related to the way different variables are updated:

  1. Gamestate_Cycle() --> called for loading new scene.
  2. FullTextBottom = LblTextBottom.Text --> called to refresh variables for typewriter.
  3. TypeWriterEffectBottom() --> called to perform typewriter effect.
like image 340
thim24 Avatar asked Jun 27 '20 13:06

thim24


People also ask

What C is used for?

C programming language is a machine-independent programming language that is mainly used to create many types of applications and operating systems such as Windows, and other complicated programs such as the Oracle database, Git, Python interpreter, and games and is considered a programming foundation in the process of ...

What is C language?

C is an imperative procedural language supporting structured programming, lexical variable scope, and recursion, with a static type system. It was designed to be compiled to provide low-level access to memory and language constructs that map efficiently to machine instructions, all with minimal runtime support.

What is C full form?

Full form of C is “COMPILE”. One thing which was missing in C language was further added to C++ that is 'the concept of CLASSES'.

Is C language easy?

C is a general-purpose language that most programmers learn before moving on to more complex languages. From Unix and Windows to Tic Tac Toe and Photoshop, several of the most commonly used applications today have been built on C. It is easy to learn because: A simple syntax with only 32 keywords.


1 Answers

Avoid async void. Otherwise you can get an Exception that will break your game and you will not able to catch it.

Then use as less global variables in async methods as possible.

I suggest CancellationTokenSource as thread-safe way to stop the Type Writer.

public async Task TypeWriterEffectBottom(string text, CancellationToken token) {     if (this.BackgroundImage != null)     {         Debug1.Text = "TypeWriter is active";         StringBuilder sb = new StringBuilder(text.Length);         try         {             foreach (char c in text)             {                 LblTextBottom.Text = sb.Append(c).ToString();                 await Task.Delay(30, token);             }         }         catch (OperationCanceledException)         {             LblTextBottom.Text = text;         }         Debug1.Text = "TypeWriter is finished";     } } 

Define CTS. It's thread-safe, so it's ok to have it in global scope.

private CancellationTokenSource cts = null; 

Call TypeWriter from async method to be able to await it.

// set button layout as "Skip text" here using (cts = new CancellationTokenSource()) {     await TypeWriterEffectBottom(yourString, cts.Token); } cts = null; // set button layout as "Go to the next scene" here 

And finally

private void PbFastForward_Click(object sender, EventArgs e) {     if (cts != null)     {         cts?.Cancel();     }     else     {         // go to the next scene     } }    
like image 92
aepot Avatar answered Sep 20 '22 12:09

aepot