Scale up and down an ellipse doesn't work within a function

The Guidelines—Asking Questions suggest an MCVE:

:)

The whole script would be preferable in this case. I anyway went ahead because it is fun.

What I would implement is what is known as a finite state machine. Your program can be in one of a number of states. What I described in post #19 are the states. You can place those states in an enum to give them sensible names.

// states that our application can be in
enum FSM
{
  WAITTRIGGER,
    GROW,
    HOLD,
    SHRINK,
    COMPLETE
};

// variable to hold the current application state
FSM applicationState = FSM.WAITTRIGGER;

For the understanding of this post, an enum is nothing more than a list of options. The variable applicationState can only have those options.

In the draw() method you can implement the state machine; the framework can look like below making use of a switch/case.

void draw()
{
  background(0xFF404040);
  
  switch(applicationState)
  {
    case WAITTRIGGER:
    break;
    case GROW:
    break;
    case HOLD:
    break;
    case SHRINK:
    break;
    case COMPLETE:
    break;
  }
}

The intention is that once a step is complete, you go to another step. E.g. in WAITTRIGGER you can go to GROW when the mouse is pressed.

  case WAITTRIGGER:
    if(mousePressed == true)
    {
      applicationState = FSM.GROW;
    }
    break;

For the implementation, I have written methods for each state; this keeps draw() quite clean. Below the framework

// states that our application can be in
enum FSM
{
  WAITTRIGGER,
    GROW,
    HOLD,
    SHRINK,
    COMPLETE
};

// variable to hold the current application state
FSM applicationState = FSM.WAITTRIGGER;

// diameter of circle to dislay
int diameter = 0;
// max diameter
int maxDiameter = 750;
// speed at which the circle must grow / shrink
int speed = 14;

// last time that ellipse was updated
int lastCycleTime;
// modify circle every 10 ms
int cycleInterval = 10;

// keep track when circle reached maximum size
int waitStartTime;
// keep circle at maximum size for 5 seconds
int waitDuration = 2000;
// flag
boolean isMax = false;

int clickTime = 0; // Variable to store the time of the click
boolean clicked = false; // Indicator variable to check if a click has occurred

// remember the last state of the mouse
boolean lastMouseState = false;


void setup()
{
  size(900, 900);
}


void draw()
{
  background(0xFF404040);

  switch(applicationState)
  {
  case WAITTRIGGER:
    waitTrigger();
    break;
  case GROW:
    grow();
    break;
  case HOLD:
    hold();
    break;
  case SHRINK:
    shrink();
    break;
  case COMPLETE:
    complete();
    break;
  }
}

void waitTrigger()
{
}

void grow()
{
}

void hold()
{
}

void shrink()
{
}

void complete()
{
}

And we can start implementing those methods. Below is the full code. See if you can follow the approach; if not, ask !

Notes:

  1. When switching state, you set the variables that need changing for the next state. In above, in waitTrigger() we set the clickTime so we can display the lapsed time.
  2. The above methods change the state when needed.
  3. The above (main) methods handle (switching of) the state machine states; except for complete(). they call another method that does the actual work.
  4. You can write a method called e.g. fsm() that contains the below content of draw() and call that method from draw to keep draw() even cleaner. At this stage I don’t consider that necessary; it will become necessary when the size of draw() grows out of hand and/or additional functionality is added to draw().

// states that our application can be in
enum FSM
{
  WAITTRIGGER,
    GROW,
    HOLD,
    SHRINK,
    COMPLETE
};

// variable to hold the current application state
FSM applicationState = FSM.WAITTRIGGER;


// diameter of circle to dislay
int diameter = 0;
// max diameter
int maxDiameter = 750;
// speed at which the circle must grow / shrink
int speed = 14;

// last time that ellipse was updated
int lastCycleTime;
// modify circle every 10 ms
int cycleInterval = 10;

// keep track when circle reached maximum size
int waitStartTime;
// keep circle at maximum size for 5 seconds
int waitDuration = 2000;
// flag
boolean isMax = false;

int clickTime = 0; // Variable to store the time of the click
boolean clicked = false; // Indicator variable to check if a click has occurred

// remember the last state of the mouse
boolean lastMouseState = false;


void setup()
{
  size(900, 900);
}

void draw()
{
  background(0xFF404040);

  switch(applicationState)
  {
  case WAITTRIGGER:
    waitTrigger();
    break;
  case GROW:
    grow();
    break;
  case HOLD:
    hold();
    break;
  case SHRINK:
    shrink();
    break;
  case COMPLETE:
    complete();
    break;
  }
}

//////////////////////////////////////////////////////////////
// Finite state machine main methods
//////////////////////////////////////////////////////////////

/*
Finite state machine: wait for trigger
 */
void waitTrigger()
{
  // wait for a change in state of the mouse
  if (mousePressed != lastMouseState)
  {
    // remember the last mouse state
    lastMouseState = mousePressed;

    // if the state went from not pressed to pressed
    if (mousePressed == true)
    {
      println("[WAITTRIGGER]Mouse pressed: Switching to GROW");
      applicationState = FSM.GROW;

      // setting the variables
      clickTime = millis();
    } //
    else
    {
      println("[WAITTRIGGER]Mouse released");
    }
  }
}

/*
Finite state machine: grow circle
 */
void grow()
{
  // display lapsed time
  zeitangabe();
  // grow the circle till it reached the maximum size
  if (growCircle() == true)
  {
    println("[GROW]Complete: Switching to HOLD");
    applicationState = FSM.HOLD;

    // setting the variables
    waitStartTime = millis();
    println("delay started @ " + str(waitStartTime));
  }
  // if the mouse was released
  if (mousePressed == false)
  {
    println("[GROW]Mouse released: Switching to COMPLETE");
    applicationState = FSM.COMPLETE;
  }
}

/*
Finite state machine: hold circle for a while
 */
void hold()
{
  // display lapsed time
  zeitangabe();
  // draw circle till hold time lapsed
  if (holdCircle() == true)
  {
    println("[HOLD]Complete: Switching to HOLD");
    applicationState = FSM.SHRINK;
  }
  // if the mouse was released
  if (mousePressed == false)
  {
    println("[HOLD]Mouse released: Switching to COMPLETE");
    applicationState = FSM.COMPLETE;
  }
}

/*
Finite state machine: shrink circle
 */
void shrink()
{
  // display lapsed time
  zeitangabe();
  // shrink the circle till it reached the minimum size
  if (shrinkCircle() == true)
  {
    println("[SHRINK]Complete: Switching to COMPLETE");
    applicationState = FSM.COMPLETE;
  }
  // if the mouse was released
  if (mousePressed == false)
  {
    println("[SHRINK]Mouse released: Switching to COMPLETE");
    applicationState = FSM.COMPLETE;
  }
}

/*
Finite state machine: process complete
 */
void complete()
{
  diameter = 0;
  println("[COMPLETE]Process complete: Switching to WAITTRIGGER");
  applicationState = FSM.WAITTRIGGER;
}

//////////////////////////////////////////////////////////////
// Finite state machine helpers
//////////////////////////////////////////////////////////////

/*
Grow circle
 Returns:
 true when circle has reached maximum size, else false
 */
boolean growCircle()
{
  // return value
  boolean rb = false;

  // draw ellipse
  drawCircle();

  // if it's time to update it
  if (millis() - lastCycleTime >= cycleInterval)
  {
    // remember the time that we did update
    lastCycleTime = millis();
    // grow ellipse for the next update
    diameter += speed;
  }

  if (diameter >= maxDiameter)
  {
    rb = true;
  }

  return rb;
}

/*
Shrink circle
 Returns:
 true when circle has reached minimum size, else false
 */
boolean shrinkCircle()
{
  // return value
  boolean rb = false;

  // draw ellipse
  drawCircle();

  // if it's time to update it
  if (millis() - lastCycleTime >= cycleInterval)
  {
    // remember the time that we did update
    lastCycleTime = millis();
    // shrink ellipse for the next update
    diameter -= speed;
  }

  if (diameter < 0)
  {
    rb = true;
  }

  return rb;
}

/*
Hold circle
 Returns:
 true when time to hold circle has lapsed, else false
 */
boolean holdCircle()
{
  boolean rb = false;
  // draw circle with the last diameter
  drawCircle();

  if (millis() - waitStartTime >= waitDuration)
  {
    rb = true;
    println("delay lapsed @ " + str(millis()));
  }

  return rb;
}

/*
Draw the circle
 */
void drawCircle()
{
  fill(0xFF000000);
  ellipse(width / 2, height / 2, diameter, diameter);
}

//////////////////////////////////////////////////////////////
// Other methods
//////////////////////////////////////////////////////////////

/*
Display lapsed time
 */
void zeitangabe()
{
  long elapsedTime = millis() - clickTime;
  fill(255);
  textAlign(CENTER);
  textSize(24);
  text("Time elapsed: " + elapsedTime + " ms", width / 2, 50);
}

:+1: Amen to that :+1:

hi @sterretje
thank you so much for your new idea - it looks quite complicated to me as a beginner and i need some time to check it. in the meantime - here ist my previously whole script within the mask with the growing-hold-shrinking-stop shoud work… with a trigger from the microphone


import processing.video.*;
import processing.sound.*;

Capture cam;
PImage img;
PImage imgMask;

Amplitude amp;
AudioIn in;

// two movie objects
Movie myMovie;
String fileMovie1 = "auge_drehen_25fps_conv.mp4";
Movie yourMovie;
String fileMovie2 = "auge_1080_verzerren_3_conv.mp4";
// movie that is currently playing
Movie currentMovie;

// last time that a frame was read
int lastReadTime = 0;
// timeout for play-once movie; 1 second
int readTimeout = 1000;

//---------- von sterretje
int diameter = 0;
int maxDiameter = 750;
int direction = 1;
int startTime;

// last time that ellipse was updated
int lastCycleTime;
// modify circle every 100 ms
int cycleInterval = 10;
// keep track when circle reached maximum size
int waitStartTime;
// keep circle at maximum size for 5 seconds
int waitDuration = 1500;
// flag
boolean isMax = false;

//---------- von sterretje ende

void setup()
{
 size(900, 900);
  fullScreen();
  background(0,11,51);

  //-------------------------------- webcam
    String[] cameras = Capture.list();
  
  if (cameras.length == 0) {
    println("There are no cameras available for capture.");
    exit();
  } else {
    println("Available cameras:");
    printArray(cameras);//gibt die kameranummer aus
    for (int i = 0; i < cameras.length; i++) {
      //println(cameras[i]);
    }
    
    // The camera can be initialized directly using an 
    // element from the array returned by list():
    cam = new Capture(this, cameras[1]);
    cam.start();     
  }      
  //-------------------------------- webcam
  
  //-------------------------------- microphone
  amp = new Amplitude(this);
  in = new AudioIn(this, 0);
  //start the microphone
  in.start();
  amp.input(in);
//-------------------------------- microphone

  // first movie, will play continously
  myMovie = new Movie(this, fileMovie1);
  // second movie, plays once after clap
  yourMovie = new Movie(this, fileMovie2);

  // set the current movie to myMovie
  currentMovie = myMovie;
  // and loop it
  currentMovie.loop();
  
  //für maske
  img = loadImage("auge4-kl-maske.png"); // Lade das Hintergrundbild (ersetze "background_image.jpg" mit dem Dateinamen deines Bildes)
  img.resize(width, height); // Skaliere das Hintergrundbild auf die Größe der Leinwand
  noStroke(); // Entferne die Konturlinie

}

void draw()
{
   if (cam.available() == true) {
    cam.read();
  }

  imageMode(CENTER);
  image(currentMovie, width/2,height/2,900,900);

  // switch to
  soundDetector();

  // if the current movie is yourMovie which plays only once
  if (currentMovie == yourMovie) {
    
    // check if we did not have data for a specified time
    if (millis() - lastReadTime >= readTimeout) {
         
      println("Switching back to 'myMovie'");

      // stop the current movie (yourMovie) so a new play will start it from the beginning
      currentMovie.stop();
 println(" timestamp mousereleased stop @ " + str(millis()));  
      // switch to the looping movie (myMovie)
      currentMovie = myMovie;
    
      // and (continue) playing
      currentMovie.play();       
    }
    // zeitangabe();
      maske(); 
 }  else {
     diameter = 0;
     direction = 1;
   }      
}


//von sterretje
void maske() {

 PGraphics maskPG = createGraphics(cam.width, cam.height);
  maskPG.beginDraw();
  maskPG.background(0);
  maskPG.fill(255);
  maskPG.noStroke();
  maskPG.ellipse(320,240, 640, 480 );//halbe cameragrösse für x und y und ganze kameragrösse für form = rund
  maskPG.endDraw();   
  cam.mask(maskPG);

  // Überlagerung der Maske mit kamerabild 
  translate(width/2,height/2);
  imageMode(CENTER);
  image(cam,0,0,diameter,diameter);

  // if the ellipse did reach it maximum size, delay a bit
  if (isMax == true)
  {
    if (millis() - waitStartTime >= waitDuration)
    {
      // clear the flag
      isMax = false;
      println("delay lapsed @ " + str(millis()));
    }
  }

  // if the ellipse is not at its maximum size and it's time to update it
  if (isMax == false && millis() - lastCycleTime >= cycleInterval)
  {
    lastCycleTime = millis();
    // grow/shrink ellipse for the next update
    diameter += (18.5 * direction);//geschwindigkeit.... 
    // if ellipse is at maximum size
    if (diameter >= maxDiameter)
    {
      // set flag
      isMax = true;
      // remember the start time
      waitStartTime = millis();
      println("delay started @ " + str(millis()));
    }

    if (diameter < 0 || diameter >= maxDiameter)
    {
      // change from grow to shrink ort vice versa
      direction *= -1;
    }
//should stop the animation with the ellipse after one runthrough
//doesn't work here in this context....
     if (diameter == 0){
       direction = 0;
     }
  }
}

//Sound dection; start other movie if a sound is detected
void soundDetector()
{
  // if a clap was detected
  if (amp.analyze() > 0.015) {
   
      // if we were playing the (looping) myMovie
      if (currentMovie == myMovie) {     
        println("Switching to 'yourMovie'");
        // pause the looping movie (myMovie) so the next time that we play it, it starts where it paused
        currentMovie.pause();
        // change the movie to yourMovie
        currentMovie = yourMovie;  
        // and play it
        currentMovie.play(); 
 println(" timestamp  mousepressed start @ " + str(millis()));
      }   
   }
}

// Called every time a new frame is available to read
void movieEvent(Movie m)
{
  // keep track of the last time that we read a frame
  lastReadTime = millis();

  // read frame depending on movie that provided the frame
  if (m == myMovie)
  {
    myMovie.read();
  } //
  else if (m == yourMovie)
  {
    yourMovie.read();
  }
}

Hello @blindschleiche,

diameter += (18.5 * direction);

Giving consideration to above is this condition below ever met?

if (diameter == 0)

//should stop the animation with the ellipse after one runthrough
//doesn't work here in this context....
    println(diameter);  // Monitor this and adjust condition in if statement
     if (diameter == 0){
       direction = 0;
     }

It seemed to work here once the above logical error was corrected.

Your PGraphic mask does not change and can be moved to setup() unless you plan to modify it dynamically later. Be mindful of variable scope!

:)

hi @glv
diameter = 0 is never reached. with the command diameter <= 0, however, it is. now it works in the simplified script with only 2 states and 2 movies. but in the final project there are 3 states with 3 movies - and there it doesn’t work anymore. the mask is only called after the first trigger - the second time it doesn’t work anymore exactly because of the command «if diameter <= 0», because i set direction to 0. direction must be set to 1 again somehow because direction is set to 1 in the startcommands above void setting.
simply setting direction to 1 at the beginning of the mask funciton does not work. then it only works with the increase but no longer with the decrease.
in the code, where i call the mask, i tried to set direction to 1. but that doesn’t work either. now i am a bit helples…

hi @sterretje
I tried to implement the new script part in my script - since i’m not a programmer, i’m quite overwhelmed because i don’t understand how i have to put the whole thing together now. after all, the ellipse is just a form for the mask for the livecamera that has to run over a film. it’s supposed to be called with a radar sensor that’s connected to processing via arduino. so i’m not clear where which program part goes. calling the different functions is spread all over the script and i’m just confused.
wouldn’t it be easier if i could create a query with “if (isMinimum == true)…” in addition to the query " if (isMax == true)…" in the mask, which then stops the whole thing? or is that the same as if i set direction = 0? the idea of glv would already be impressive, if it wouldn’t work only once… the problem there is, that the direction is set on 1 above setup - after the first click it doesn’t jump out of the void draw to start over. so i need a way to set direction to 1 within the void draw or the mask without starting it in the loop but only with the trigger.

In my latest code (post #22) there is no longer a direction indication. I will try to have a look at your code in post #24 and see if I can integrate; might take a few days though.

hi @sterretje
if you really want to integrate your script in mine, that would be wonderful! but you better don’t take the script from post#24 - that’s the short version with only 2 movies. here ist the long one with 3 movies - for testing this example i replaced the sensor from arduino with amp.analyze() > 0.3 to play the third movie with the mask. but i leave the arduino commands in the script. otherwise it gets to complicated. i only comment out the call of the function void buttonArduino()
thank you so much for your help!

import processing.serial.*;
import processing.video.*;
import processing.sound.*;

long clickTime = 0; // Variable to store the time of the click
boolean clicked = false; // Indicator variable to check if a click has occurred

Capture cam;
PImage img;
PImage imgMask;

Amplitude amp;
AudioIn in;

// two movie objects
Movie myMovie;
String fileMovie1 = "auge_drehen_25fps_conv.mp4";
Movie yourMovie;
String fileMovie2 = "auge_1080_zoom_1_conv.mp4";
Movie hisMovie;
String fileMovie3 = "auge_1080_verzerren_3_conv.mp4";
// movie that is currently playing
Movie currentMovie;

// last time that a frame was read
int lastReadTime = 0;
// timeout for play-once movie; 1 second
int readTimeout = 1000;



//---------- von sterretje damit die ellipse in der mitte stoppt
int diameter = 0;
int maxDiameter = 750;
int direction = 1;
int startTime;

// last time that ellipse was updated
int lastCycleTime;
// modify circle every 100 ms
int cycleInterval = 10;
// keep track when circle reached maximum size
int waitStartTime;
// keep circle at maximum size for 5 seconds
int waitDuration = 1500;
// flag
boolean isMax = false;

//---------- von sterretje ende



// Objekt zur Überwachung eines seriellen Ports fürs arduino erzeugen
Serial myPort;
 
// String für empfangene Daten
String portStream;
 
// Zustände der beiden Buttons
int B1in = 0;
int B2in = 0;

//---------------------------- void setup start .........----------------------------
void setup()
{
 size(900, 900);
  fullScreen();
  background(0,11,51);

  //--------------------------------
    String[] cameras = Capture.list();
  
  if (cameras.length == 0) {
    println("There are no cameras available for capture.");
    exit();
  } else {
    println("Available cameras:");
    printArray(cameras);//gibt die kameranummer aus
    for (int i = 0; i < cameras.length; i++) {
      //println(cameras[i]);
    }
    
    // The camera can be initialized directly using an 
    // element from the array returned by list():
    cam = new Capture(this, cameras[1]);
    cam.start();     
  }      
  //--------------------------------

  amp = new Amplitude(this);
  in = new AudioIn(this, 0);
  //start the microphone
  in.start();
  amp.input(in);

  // first movie, will play continously
  myMovie = new Movie(this, fileMovie1);
  // second movie, plays once after clap
  yourMovie = new Movie(this, fileMovie2);
    // third movie, plays once after clap
  hisMovie = new Movie(this, fileMovie3);

  // set the current movie to myMovie
  currentMovie = myMovie;
  // and loop it
  currentMovie.loop();
  
  
  img = loadImage("auge4-kl-maske.png"); // Lade das Hintergrundbild (ersetze "background_image.jpg" mit dem Dateinamen deines Bildes)
  img.resize(width, height); // Skaliere das Hintergrundbild auf die Größe der Leinwand
  noStroke(); // Entferne die Konturlinie
  
  
  //*****************************
  // Hier muss der Index des Arduino-Ports ausgewählt werden. Notfalls ausprobieren.
  String portName = Serial.list()[3]; 
  // myPort initialisieren, Übertragungsrate wie bei Arduino Sketch einstellen
  myPort = new Serial(this, portName, 9600);
  // Ankommende Zeichen am Port werden solange gebuffert, bis das angebene Zeichen empfangen wird.
  // Damit ist ein Datenblock vollständig übertragen. \n ist das 2. Zeichen eines Zeilenwechsels (\r\n)
  myPort.bufferUntil('\n');
  
//*****************************

//---------------------------- void setup ende .........----------------------------

//--|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||

//---------------------------- void draw start .........----------------------------
}

void draw()
{
   if (cam.available() == true) {
    cam.read();
  }
int  direction = 1;
    //********** Arduino einschalten  
  if(portStream != null) {
    // Entspricht der Datenblock dem Format "SxxE\r\n"? Wenn ja, dann weiter
    if (portStream.length() == 6 && portStream.charAt(0) == 'S' && portStream.charAt(3) == 'E') {
      // 2. und 3. Zeichen auslesen
      B1in = int(portStream.substring(1,2));   // z.B. bei "S10E" = 1
      B2in = int(portStream.substring(2,3));   // z.B. bei "S10E" = 0
     }
   }        
   //*****************************

  imageMode(CENTER);
  image(currentMovie, width/2,height/2,900,900);

  // switch to
  soundDetector();
//  buttonArduino();

  // if the current movie is yourMovie which plays only once
  if (currentMovie == yourMovie) {     // also film 2
    
    // check if we did not have data for a specified time
    if (millis() - lastReadTime >= readTimeout) {
               
      println("Switching back to film 1 'myMovie'");
      // stop the current movie (yourMovie - film 2) so a new play will start it from the beginning
      currentMovie.stop();// film 2
    
 
      // switch to the looping movie (myMovie) - film 1
      currentMovie = myMovie;
      
    
      // and (continue) playing - film 1
      currentMovie.play();  
      
      
    }
  
  }
    
     if (currentMovie == hisMovie) {     // also film 3
                
    // check if we did not have data for a specified time
    if (millis() - lastReadTime >= readTimeout) {
               
      println("Switching back to film 1 'myMovie'");
      // stop the current movie (hisMovie - film 3) so a new play will start it from the beginning
      currentMovie.stop();// film 3
      
 
      // switch to the looping movie (myMovie) - film 1
      currentMovie = myMovie;
    
      // and (continue) playing - film 1
      currentMovie.play();  
            
      myPort.write('L'); // befehl zum arduino - schaltet button und LED aus - LOW
      
   
            
    }

      zeitangabe();
      maske(); 

 }  
}

//---------------------------- void draw ende .........----------------------------

//--|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||

//--------------------------FUNKTIONEN --------------------------------------------
//ist nur für die kontrolle - nicht für den ablauf
void zeitangabe(){
    if (clicked) {
    long elapsedTime = millis() - clickTime;
    textAlign(CENTER);
    textSize(24);
    text("Time elapsed: " + elapsedTime + " ms", width / 2, height / 2);
  } 
}


//von sterretje -- stop in der mitte ---------------------------------|||||||||||||||
void maske() {

//clickTime = millis();

 PGraphics maskPG = createGraphics(cam.width, cam.height);
  maskPG.beginDraw();
  maskPG.background(0);
  maskPG.fill(255);
  maskPG.noStroke();
  maskPG.ellipse(320,240, 640, 480 );//halbe cameragrösse für x und y und ganze kameragrösse für form = rund
// maskPG.filter(BLUR,2); // macht alles ziemlich langsam
  maskPG.endDraw();   
  cam.mask(maskPG);


  // Überlagerung der Maske mit kamerabild 
  translate(width/2,height/2);
//  fill(255, 150); // Setze die Füllfarbe des transparenten Rechtecks (Alpha = 150)
  imageMode(CENTER);
  image(cam,0,0,diameter,diameter);
//  fill(255, 150);
 
  // if the ellipse did reach it maximum size, delay a bit
  if (isMax == true)
  {
    if (millis() - waitStartTime >= waitDuration)
    {
      // clear the flag
      isMax = false;
      println("delay lapsed @ " + str(millis()));
    }
  }

  // if the ellipse is not at its maximum size and it's time to update it
  if (isMax == false && millis() - lastCycleTime >= cycleInterval)
  {
    lastCycleTime = millis();
    
    
    // grow/shrink ellipse for the next update
   // diameter += (30 * direction);//geschwindigkeit....  muss höher als 18.5 sein falls blur gesetzt
    diameter += (18.5 * direction);//geschwindigkeit.... 
    // if ellipse is at maximum size
    if (diameter >= maxDiameter)
    {
      // set flag
      isMax = true;
      // remember the start time
      waitStartTime = millis();
      println("delay started @ " + str(millis()));
    }

    if (diameter < 0 || diameter >= maxDiameter)
    {
      // change from grow to shrink ort vice versa
      direction *= -1;
    }
   
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    
     //sollte die ellipsen-animation nach einem durchlauf stoppen
//funzt hier aber nicht....16.8.23
// jetzt läufts nur beim ersten mal aufrufen richtig, weil diameter == 0 nie erreicht wird, <= 0 aber schon - 20.8.23
//dummerweise bleibt es aber bei direction 0 - die sollte beim aufruf aber auf 1 sein ohne dass es bereits ausgeführt ist.
//println(diameter);
     // if (diameter == 0){
  
       if (diameter <= 0){
       direction = 0;
     }
  

//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
  }
}

//von sterretje ende --------------------------------------|||||||||||||||



//Sound dection; start other movie if a sound is detected
void soundDetector() {
  // if a clap was detected
  if (amp.analyze() > 0.015) {
   
      // if we were playing the (looping) myMovie
      if (currentMovie == myMovie) {    // film 1 
        println("Switching to 'yourMovie'"); // also film 2
        // pause the looping movie (myMovie - film 1) so the next time that we play it, it starts where it paused
        //currentMovie.pause();
          currentMovie.stop();
        // change the movie to yourMovie - film 2
        currentMovie = yourMovie;  //film 2
        // and play it
        currentMovie.play(); // film 2

      }   
   }
  
  if (amp.analyze() > 0.3)
  {
    // if we were playing the (looping) myMovie
    if (currentMovie == yourMovie || currentMovie == myMovie)
    {
      println("Switching to 3 'hisMovie' film3");
      // pause the looping movie (myMovie) so the next time that we play it, it starts where it paused
      currentMovie.stop();
               
      zeitangabe();
      maske(); 
      
      // change the movie to hisMovie
      currentMovie = hisMovie;// film 3
      // and play it
      currentMovie.play();//film 3
      
        clickTime = millis();
        clicked = true;
      
    } 
  
  }

}

void buttonArduino()
{
       
    // Wenn Button - pin 10 - gedrückt dann film ab und led an (Farbe grün einstellen, sonst rot)
    if (B2in == 1) {
    
      // if we were playing the (looping) myMovie film 1 oder film 2
      if (currentMovie == myMovie || currentMovie == yourMovie) {     
        println("Switching to 'hisMovie - film 3'");
        // pause the looping movie (myMovie film 1 oder film 2) so the next time that we play it, it starts where it paused
       // currentMovie.pause();
           currentMovie.stop();
        // change the movie to hisMovie
        currentMovie = hisMovie;// film 3
        // and play it
        currentMovie.play(); // film 3
        
        myPort.write('H'); // befehl zum arduino - button und LED - High
        
      }
      
        clickTime = millis();
        clicked = true;
    }    
}

// Called every time a new frame is available to read
void movieEvent(Movie m)
{
  // keep track of the last time that we read a frame
  lastReadTime = millis();

  // read frame depending on movie that provided the frame
  if (m == myMovie)
  {
    myMovie.read();
  } //
  else if (m == yourMovie)
  {
    yourMovie.read();
  } else if (m == hisMovie)
  {
    hisMovie.read();
  }
}

// serialEvent wird aufgerufen, wenn das weiter oben über bufferUntil definierte Zeichen empfangen wird.
// Dann wird der Inhalt des seriellen Buffers in portStream geschrieben.
void serialEvent(Serial myPort) {
  portStream = myPort.readString();
}

Please be mindful of the guidelines:

This is an achievable project.

I worked through this with some young programmers with very simple state transitions with success.
I may share an example at a later date without integrating your project.

:)

hi @glv
i don’t understand your message. what do you mean?

hi @sterretje
i finally found the mistake - there are two mistakes in the function buttonArduino() (the fist mistake is only in the function buttonArduino()
first: clickTime = millis() and clicked = true are in the wrong place - they have to be inside of the if(currentMovie == …

      if (currentMovie == myMovie || currentMovie == yourMovie) {     
        println("Switching to 'hisMovie - film 3'");
        // pause the looping movie (myMovie film 1 oder film 2) so the next time that we play it, it starts where it paused
       // currentMovie.pause();
           currentMovie.stop();
        // change the movie to hisMovie
        currentMovie = hisMovie;// film 3
        // and play it
        currentMovie.play(); // film 3
        
        myPort.write('H'); // befehl zum arduino - button und LED - High
      
        clickTime = millis();
        clicked = true;
    } 
} 

second: the direction is defined as 0 - when the function buttonArduino() (or the amp.analyze() > 0.3) is called it needs to change the direction from 0 or >= 0 to 1

so the correct code within the function buttonArduino() is as follows

void buttonArduino() //für maske und film 3
{
       
    // Wenn Button 2 - pin 10 - gedrückt oder jetzt radar dann film 3, button 1 als kontrolle resp. vergleich mit radar, obs richtig läuft
    if (B2in == 1 || B1in == 1 ) {
    
      // if we were playing the (looping) myMovie film 1 oder film 2
      if (currentMovie == myMovie || currentMovie == yourMovie) {     
        println("Switching to 'hisMovie - film 3'");
        // pause the looping movie (myMovie film 1 oder film 2) so the next time that we play it, it starts where it paused
       // currentMovie.pause();
           currentMovie.stop();
        // change the movie to hisMovie
        currentMovie = hisMovie;// film 3
        // and play it
        currentMovie.play(); // film 3
        
        myPort.write('H'); // befehl von arduino - löst film 3 mit maske mit livecam aus
              
        clickTime = millis();
        clicked = true;
        
       // damit die maske mit der lievcam neu aufgerufen wird
       if (diameter <= 0){
         direction = 1;
       }                
    } 
  }
}
              

now it works as whished - supercool - thank you so much for your help! i really appreciate it very much
sincerely blindschleiche

2 Likes