Newbie advice... stop a blinking cursor

I’m totally new to processing and to coding in general.

At the moment I’m really not sure if my brain is capable of learning code… have been trying to understand some of the reference section with limited success.

I’ve downloaded a bit of code from github that does something (mildly) interesting with text and am hoping to learn enough to modify it a bit to do some other things I have in mind. (see here for a more comprehensive explanation: Newbie seeking a bit of guidance... vertically falling text manipulation)

Referenced in the code is the following “Cursor” class (essentially a moving blinking cursor):

class Cursor
{
  int x, y;
  int blinkTime;
  int previous;
  boolean bLight = true;
  PImage r;
  
  int fontW;
  int fontH;
  
  Cursor(int _x, int _y, int _fW, int _fH, int _blinkTime) {
    fontW = _fW;
    fontH = _fH;
    x = _x * fontW;
    y = _y * fontH;
    blinkTime = _blinkTime;
    r = createImage(fontW, fontH, RGB);
    r.loadPixels();
    for (int i = 0; i < r.pixels.length; i++) {
      r.pixels[i] = color( MONOCHROME ); 
    }
    r.updatePixels();
    previous = millis();
  }
   
  void move(int _x, int _y) {
    x = _x * fontW;
    y = _y * fontH; 
    bLight = true;
  }
  
  void update(int time) {
    if(time - previous> blinkTime){
      bLight = !bLight;
      previous = time;
    }
  }
 
  void display() {
    if(bLight){
      pushStyle();
      noStroke();
      //fill(0, 255, 0);
      blend(r, 0, 0, fontW, fontH, x, y, fontW, fontH, DIFFERENCE);
      popStyle();
    }
  }
}`Preformatted text`

This Cursor is used in another script that “writes” text on screen (from a txt file: “script.txt”) in the style of the old terminal command prompt computers.

Can anyone tell me how I might write a command in the main script to “turn off” the cursor once it’s written something, i.e. to stop blinking and go blank?

At the moment, it just sits there blinking at the end of the written line.

Here’s the part of the main script that seems to deal mostly with the cursor class:

void scriptLoad() {
  lineIdx = 0;
  lineChar = 0;
  script = loadStrings("script.txt");
  if( script == null ) {
    println("\nloadString returned NULL");
    exit();
  } else {
    println("Script loaded!");
    println("Script contains " + script.length + " lines");
    
    for (int i = 0 ; i < script.length; i++) {
      print("line "+i+" has "+ script[i].length() + " characters");
      if( script[i].isEmpty() ) {
        // empty line
        println(";");
        continue;
      } else if( scriptIsCommand(i) ) {
        if( whatCommand(i) == -1) {
          print(" - INVALID COMMAND!");
          exit();
        } else {
          print(" - line "+i+" is a command! ( ");
          print( script[i] +" )");
        }
      } else {
        print(";");
      }
      println();      
    }
  }
}

void scriptRead( int time ) {
  if( bWaiting ) {
    menageWaiting( time );
  } else if( lineIdx < script.length ) { 
    if( script[ lineIdx ].isEmpty() ) {
      // empty line
      lineIdx++;
    } else if( scriptIsCommand( lineIdx )) {
      //debugA("found a command:");
      // Any commands in the script have already been 
      // evaluated during the script loading
      int opCode = whatCommand( lineIdx );
      // command execution
      switch( opCode ) {
        case 0: // #WAIT
          //debugA("WAIT command");
          bWaiting = true;
          waitTime = idleWaitTime;
          previousTime = time;
          //previousWaitTime = time;
          break;
        case 1: //#CLEAR
          //debugA("CLEAR command");
          waitTime = charWaitTime;
          waitValue = 1;
          bWaiting = true;
          previousTime = time;
          screenClear();
          cursor.move(colIdx, rowIdx);
          break;
        case 2: //#LINEFEED
          //debugA("LINEFEED command");
          rowIdx++;
          colIdx = 0;
          insertPrompt();
          cursor.move(colIdx, rowIdx);
          break;
        case 3: //#RESTART
          //debugA("RESTART command");
          screenClear();
          lineIdx = 0;
          lineChar = 0;
          break;
        case 4: //#CLEARLINE
          //debugA("CLEARLINE command");
          screenClearLine();
          cursor.move(colIdx, rowIdx);
        default:
          break;
      }    
      lineIdx ++;
    } else {
      // characters
      if(lineChar < script[ lineIdx ].length() ) {
        waitTime = charWaitTime;
        waitValue = 1;
        bWaiting = true;
        previousTime = time;
        copyCharacter( time );
        cursor.move(colIdx, rowIdx);
        emitSound("char");
      } else {
        lineChar = 0;
        lineIdx++;
        scriptRead( millis() );
              }    
    }
  } 
  

  
  else {
    //debugA("End of the script");
  }
}

NOTE: the code is written for Processing 2.0

Before starting, I suggest you check out The coding train youtube channel. It is a really good way to learn coding. It introduced me to coding and problem solving. The videos are not scripted, so you can see some issues popping up solutions for them. I believe that anyone willing to learn coding can learn and progress. The only issue is the lack of appropriate challenges to advance your skill.

Now about the code;
The simplest solution would be to add a way to tell the curser not to blink. This can be done with variables and since there are only 2 states; blinking and not blinking, a boolean in perfect for it.

Just add a boolean variable inside of the class and set it to true by default. When displaying the blinking, check if blinking == true, otherwise, don’t show the animation.

So how to turn it on/off?
Either add methods inside of the class to change blinking (boolean) or directly modify it with this:

Cursor c = new Cursor(...);
c.blinking = false; //turn it off
c.blinking = true, //turn if on
c.blinking = !c.blinking; //change state

I hope this helps!

2 Likes

Thank you, that does help me understand a little bit more. Will definitely check out the youtube channel.

If I understand you correctly, I’d put:
boolean blinking = true;
in the Cursor class code, which is basically saying “what this code is doing is blinking”
so in the main script if I tell it blinking is false regarding the cursor, it’s like saying “don’t run that code” - therefore the cursor disappears?

I can see how the code example you gave would achieve that… I think!

So I’ve added:
boolean blinking = true;
to the Cursor class code ad saved the file…
then added:

Cursor c = new Cursor(c.blinking = false);

to the main script.
However, I get an error saying “the constructor monichromitor.Cursor (boolean) is undefined”

[monichromitor is the name of the main script]

This seems to be suggesting I need to define something in the main script as well?

1 Like

I am not familiar with processing 2.0. But in 3.5.4 this would be it:

Cursor c = new Cursor(false);

class Cursor {
   //random stuff
   boolean blinking;
   Cursor(boolean blinking) { //use this one or the next one. Only one can be present. 
      this.blinking = blinking; //`this.blinking` just reffers to the boolean created before, even though there is a input with the same name.
   }
   //Cursor(boolean blink) { //USE THIS ONE IF NOT USING THE FIRST WAY
   //   blinking = blink;
   //}
}

Thank you. For some reason, that didn’t work - maybe because it’s 2.0.

Anyway I found an easier solution. I realized there’s an if/else argument going on in the script, which is governing essentially whether or not the cursor sits there blinking waiting for more input or moves along with the text as it’s typed. So I just inserted a new else argument at the end and told it to draw a new cursor with no width or height!

void scriptRead( int time ) {
  if( bWaiting ) {
    menageWaiting( time );
  } else if( lineIdx < script.length ) { 
    if( script[ lineIdx ].isEmpty() ) {
      // empty line
      lineIdx++;
    } else if( scriptIsCommand( lineIdx )) {
      //debugA("found a command:");
      // Any commands in the script have already been 
      // evaluated during the script loading
      int opCode = whatCommand( lineIdx );
      // command execution
      switch( opCode ) {
        case 0: // #WAIT
          //debugA("WAIT command");
          bWaiting = true;
          waitTime = idleWaitTime;
          previousTime = time;
          //previousWaitTime = time;
          break;
        case 1: //#CLEAR
          //debugA("CLEAR command");
          waitTime = charWaitTime;
          waitValue = 1;
          bWaiting = true;
          previousTime = time;
          screenClear();
          cursor.move(colIdx, rowIdx);
          break;
        case 2: //#LINEFEED
          //debugA("LINEFEED command");
          rowIdx++;
          colIdx = 0;
          insertPrompt();
          cursor.move(colIdx, rowIdx);
          break;
        case 3: //#RESTART
          //debugA("RESTART command");
          screenClear();
          lineIdx = 0;
          lineChar = 0;
          break;
        case 4: //#CLEARLINE
          //debugA("CLEARLINE command");
          screenClearLine();
          cursor.move(colIdx, rowIdx);
        default:
          break;
      }    
      lineIdx ++;
    } else {
      // characters
      if(lineChar < script[ lineIdx ].length() ) {
        waitTime = charWaitTime;
        waitValue = 1;
        bWaiting = true;
        previousTime = time;
        copyCharacter( time );
        cursor.move(colIdx, rowIdx);
        emitSound("char");
      } else {
        lineChar = 0;
        lineIdx++;
        scriptRead( millis() );
      }    
    }
  } else {
        cursor = new Cursor(colIdx, rowIdx, 0, 0, 0);
  }
}