Having trouble with a code and its structure

Ok so this is the updated sketch :

import processing.sound.*;
SoundFile Son;
PImage portrait;
PImage telephone;
PImage mail;
PImage arme;
int rand;
int action;
int savedTimeSon;
int savedTimeImage;
int soundTime = 500;
int imageTime = 500;
int state = 0;

void setup() {
  size(640, 640);
  telephone = loadImage("Calls.jpg");
  mail = loadImage("Emails.jpg");
  arme = loadImage("Kills.jpg");
  rand = int(random(1, 155));
}

void draw() {
  
if (state == 0) {
  takerandomimage("portrait" + nf(rand, 3) + ".jpg");
  action = int (random (1, 4));
  if(action==1) {
    image (telephone, 0, 0);
    Son = new SoundFile(this, "Son_calls.mp3");
    Son.play();
  } else if(action==2) {
    image (mail, 0, 0);
    Son = new SoundFile(this, "Son_emails.mp3");
    Son.play();
  } else if(action==3) {
    image (arme, 0, 0);
    Son = new SoundFile(this, "Son_kills.mp3");
    Son.play();
  }
  state ++;
}

else if (state == 1) {
  if (!Son.isPlaying()){
    state = 2;
    }
  }
  
else if (state == 2) {  
  if (!Son.isPlaying()){
    state = 3;
    }
  }
  
else if (state == 3) {  
  if (!Son.isPlaying()){
    state = 4;
    }
  }
}

void takerandomimage(String fn) {
  portrait = loadImage(fn);
  image(portrait, 0, 0);
}

This time :

  • Only one “action” image appears
  • But the sound is synced and has no glitches, which has never happened before, so this is good !

But the portrait images never seem to show up, and the program only runs once.
I guess that it has to do with this part of the sketch that I don’t fully understand :

 } else if (state == 1) {
    if (!Son.isPlaying()) {
      state = 2;
    }
  } else if (state == 2) {  
    if (!Son.isPlaying()) {
      state = 3;
    }
  } else if (state == 3) {  
    if (!Son.isPlaying()) {
      state = 4;
    }

not necessary

instead

else if (state == 1) {
  if (!Son.isPlaying()){
    rand = int(random(1, 155)); // !!!!!!
    state = 0;
    }
  }

are you using background anywhere

better if you don’t

are you place the image for the action ABOVE the image for the portrait

both are at 0,0

move the image for the action to the right

image (telephone, 0, 0);

same for mail and telephone and so on

I am not using background.
When moving the images for the action, I can see that the image for the portrait is underneath the image for the action.
So the issue is only about the length of display of the images.
I am going to try to implement the timer function in the example that you have showed me before
This one :

int state=0; 
int timer; 

void setup() {
  size(640, 640);

  timer = millis();
  background(0);
}

void draw() {
  background(0); 
  if (state == 0) {
    text("state is 0", 111, 111);
    if (millis()- timer > 3000) {
      state = 1;
    }
  } else if (state == 1) {
    text("state is 1", 111, 111);
  }
}
1 Like

New version with an attempt to implement a timer :

import processing.sound.*;
SoundFile Son;
PImage portrait;
PImage telephone;
PImage mail;
PImage arme;
int rand;
int action;
int actionAllowed = 0;
int timer;
int state = 0;

void setup() {
  size(640, 640);
  telephone = loadImage("Calls.jpg");
  mail = loadImage("Emails.jpg");
  arme = loadImage("Kills.jpg");
  rand = int(random(1, 155));
  timer = millis();
}

void draw() {

  if (state == 0) {
    takerandomimage("portrait" + nf(rand, 3) + ".jpg");
    image (portrait, 0, 0);
    if (actionAllowed == 0) {
      if (millis()- timer > 5) {
        actionAllowed = 1;
      }
    } else if (actionAllowed == 1) {
      action = int (random (1, 4));
      if (action==1) {
        image (telephone, 0, 0);
        Son = new SoundFile(this, "Son_calls.mp3");
        Son.play();
      } else if (action==2) {
        image (mail, 0, 0);
        Son = new SoundFile(this, "Son_emails.mp3");
        Son.play();
      } else if (action==3) {
        image (arme, 0, 0);
        Son = new SoundFile(this, "Son_kills.mp3");
        Son.play();
      }
    }
    state ++;
  } else if (state == 1) {
    if (!Son.isPlaying()) {
      state = 2;
    }
  } else if (state == 2) {  
    if (!Son.isPlaying()) {
      state = 3;
    }
  } else if (state == 3) {  
    if (!Son.isPlaying()) {
      state = 4;
    }
  }
}

void takerandomimage(String fn) {
  portrait = loadImage(fn);
  image(portrait, 0, 0);
}

Here, the program only shows one portrait before indicating “NullPointerException”.
I felt like my attempt made sense (logic wise), I’m kind of lost right now.

1 Like

Where does the nullpointer occur?

It occurs at :

    if (!Son.isPlaying()) {

When actionAllowed == 0 the code is executed but Son is not defined

You can say if(Son!=null) right before the if with the isPlaying…

The last case clauses are not needed as I wrote

Yes but I cannot define Son this early in the program because the random choice has to be done before defining which SoundFile it is.

When you say :

Do you mean like this ?

} else if (state == 1) {
    if (Son!=null) {
      if (!Son.isPlaying()) {
        state = 2;
      }
    }

And what do you mean by :

Yes - that’s correct

This is what I have :

import processing.sound.*;
SoundFile Son;
PImage portrait;
PImage telephone;
PImage mail;
PImage arme;
int rand;
int action;
int actionAllowed = 0;
int timer;
int state = 0;

void setup() {
  size(640, 640);
  telephone = loadImage("Calls.jpg");
  mail = loadImage("Emails.jpg");
  arme = loadImage("Kills.jpg");
  rand = int(random(1, 155));
  timer = millis();
}

void draw() {

  if (state == 0) {
    takerandomimage("portrait" + nf(rand, 3) + ".jpg");
    image (portrait, 0, 0);
    if (actionAllowed == 0) {
      if (millis()- timer > 500) {
        actionAllowed = 1;
      }
    } else if (actionAllowed == 1) {
      action = int (random (1, 4));
      if (action==1) {
        image (telephone, 0, 0);
        Son = new SoundFile(this, "Son_calls.mp3");
        Son.play();
      } else if (action==2) {
        image (mail, 0, 0);
        Son = new SoundFile(this, "Son_emails.mp3");
        Son.play();
      } else if (action==3) {
        image (arme, 0, 0);
        Son = new SoundFile(this, "Son_kills.mp3");
        Son.play();
      }
    }
    state ++;
  } else if (state == 1) {
    if (Son!=null) {
      if (!Son.isPlaying()) {
        rand = int(random(1, 155));
        state = 0;
      }
    }
  }
}

void takerandomimage(String fn) {
  portrait = loadImage(fn);
  image(portrait, 0, 0);
}

When I run the code, only one portrait appears

Hello,

You can use println() statements in your code to help debug; print a meaningful string or variable to help you know where you are in the code.

This is always true 500ms after the start of the program:
millis()- timer > 500

In this case 500ms after you initialized timer in setup():
timer = millis();

Is this what you intended for the timer?

There are many examples of timers out there.

:)

1 Like

Thank you for your reply !
I will try to use println() in the future.

Yes, I have read multiple threads and have seen multiple examples, but I feel like I am missing the logic of the timer.

I think that I understand how my timer is currently understanding my orders. But I don’t think that it corresponds to what I intend for the timer.

What I would like to tell the program to do is :

  • Display a random portrait
  • Wait 0.5 seconds
  • Display a random “action” image and play its sound
  • Wait 0.5 seconds
  • Repeat

But I don’t know how to change the timer so that it does what I want it to do.
Thanks again !

1 Like