Does the program draw only at the end of the draw() function ?

edited August 2014 in Questions about Code

Hello, I try to create a piano on processing and i want to put a demo button. It need to show the key corresponding to the music note

(this is not my program, just an example what happen)

import arb.soundcipher.*;
SoundCipher sc = new SoundCipher(this);

void setup()
{
  noStroke();
  size(130, 130);
  background(0);
}

void draw()
{
    sc.playNote(60, 100, 2.0); //play a note
    fill(255, 0, 0);
    rect(100, 100, 10, 10);
    delay(2000);
    sc.playNote(40, 100, 2.0); //play a note
    fill(0, 255, 0);
    rect(120, 120, 10, 10);
    delay(2000);
}

when i run the program, first there is a white square and after the two notes were played all graphics sudenly appear. I test without importing the SoundCipher library and the same thing happen just without sound.

(Please excuse my english, it is not my native language so not sure of all the terms)

Tagged:

Answers

  • The draw method contains all the code to draw the next frame which only appears at the end of the draw method.

    The code below shows how you can do something similar using the keyboard.

    BTW the call to size() must be the first statement inside setup.

    char c = ' ';
    
    void setup() {
      size(130, 130); // must be first statement here
      noStroke();
      textSize(36);
    }
    
    void keyPressed() {
      c = key;
    }
    
    void keyReleased() {
      c = ' ';
    }
    
    void draw() {
      background(0);
      fill(255);
      text(""+c, 40, 40);
    }
    
  • edited August 2014

    Technical FAQ: I display images in sequence but I see only the last one. Why?

    Don't use delay(). Most of the time, it is wrongly used...

  • edited August 2014

    delay() is an undocumented Processing function! Its main use is to slowdown other threads.
    Processing's already has its own internal slowdown engine that controls canvas rendering speed.

    Instead of delay(), use frameRate() in order to set draw()'s FPS:
    http://processing.org/reference/frameRate_.html

  • edited August 2014 Answer ✓

    Without the delay:

    void draw()
    {
      if (frameCount == 1)
      {
        sc.playNote(60, 100, 2.0); //play a note
        fill(255, 0, 0);
        rect(100, 100, 10, 10);
      }
      if (frameCount == 120)
      {
        sc.playNote(40, 100, 2.0); //play a note
        fill(0, 255, 0);
        rect(120, 120, 10, 10);
      }
    }
    

    frameCount is a variable which increments after each draw(). This draw method gets called about 60 times a second by Processing (by default), so after one second, frameCount equals 60. Of course, this assumes the draw method takes less than 1/60th of a second to finish.

    If you want the program to loop, use frameCount%240 instead, this "resets" the frameCount variable once it reaches 240. The % sign is called the modulo operator which is explained in the documentation.

  • Other people have already answered you and gave you some alternatives, but I will also add that this is a result of Processing (and Swing in general) using double buffering to draw the frames. The entire frame is drawn to an off-screen buffer, and then that buffer is drawn to the screen all at once.

    More info here, and google is your friend: http://en.wikipedia.org/wiki/Multiple_buffering#Double_buffering_in_computer_graphics

  • @KevinWorkman: If I wanted to draw directly to the screen, possible in processing? Possible in eclipse? Thank you! ;-)

  • edited August 2014

    Thanks a lot for all the solutions tou give me. I finally solve the problem by add a counter:

     if (Demo == true)
      {
        delay(500);
        reset();
        if (turn == 0) {
          play(46, 1);
        }
        if (turn == 1) {
          play(45, 1);
        }
        if (turn == 2) {
          play(46, 1);
        }
        if (turn == 3) {
          play(45, 1);
        }
        if (turn == 4) {
          play(46, 1);
        }
        if (turn == 5) {
          play(40, 1);
        }
        if (turn == 6) {
          play(44, 1);
        }
        if (turn == 7) {
          play(42, 1);
        }
        if (turn == 8) {
          play(38, 0);
          play(10, 1);
        }
    
        if (turn == 9) {
          play(18, 1);
        }
        if (turn == 10) {
          play(24, 1);
        }
        if (turn == 11) {
          play(28, 1);
        }
        if (turn == 12) {
          play(32, 1);
        }
        if (turn == 13) {
          play(38, 1);
        }
        if (turn == 14) {
          play(40, 0);
          play(4, 1);
        }
        if (turn == 15) {
          play(18, 1);
        }
        if (turn == 16) {
          play(23, 1);
        }
        if (turn == 17) {
          play(32, 1);
        }
        if (turn == 18) {
          play(37, 1);
        }
        if (turn == 19) {
          play(40, 1);
        }
        if (turn == 20) {
          play(42, 0);
          play(10, 1);
        }
        if (turn == 21) {
          play(18, 1);
        }
        if (turn == 22) {
          play(24, 1);
        }
        if (turn == 23) {
          play(32, 1);
          Demo = false;
        }
        turn++;
    }
    

    The play function play the note and diplay the key and the reset function reset the keyboard of the piano.

  • Answer ✓

    Thats an awful lot of if statements - in this scenario it is common to use the swith statement like this

    if (Demo == true) {
      delay(500);
      reset();
      switch(turn) {
      case 0:
        play(46, 1);
        break;
      case 1:
        play(45, 1);
        break;
      case 2:
        play(46, 1);
        break;
      case 3:
        play(45, 1);
        break;
      case 4:
        play(46, 1);
        break;
      case 5:
        play(40, 1);
        break;
      case 6:
        play(44, 1);
        break;
      case 7:
        play(42, 1);
        break;
      case 8:
        play(38, 0);
        play(10, 1);
        break;
      case 9:
        play(18, 1);
        break;
      case 10:
        play(24, 1);
        break;
      case 11:
        play(28, 1);
        break;
      case 12:
        play(32, 1);
        break;
      case 13:
        play(38, 1);
        break;
      case 14:
        play(40, 0);
        play(4, 1);
        break;
      case 15:
        play(18, 1);
        break;
      case 16:
        play(23, 1);
        break;
      case 17:
        play(32, 1);
        break;
      case 18:
        play(37, 1);
        break;
      case 19:
        play(40, 1);
        break;
      case 20:
        play(42, 0);
        play(10, 1);
        break;
      case 21:
        play(18, 1);
        break;
      case 22:
        play(24, 1);
        break;
      case 23:
        play(32, 1);
        Demo = false;
        break;
      }
      turn++;
    }
    
  • edited August 2014

    @tigri:

    is it correct that sometimes there are 2 plays at once?

    play(42, 0);
    play(10, 1);
    
  • @quark: Thanks for the switch trick, I do not use much the switch statement, so I don't have the reflex use.

    @Chrisir: Yes it's correct, it's when the right hand and the left hand play together. For information, this demo is a part the opening of Beethoven's Für Elise :

  • I see, thank you!

Sign In or Register to comment.