Change object direction when reaching edges

How can I change the direction of my image?

As you know, a fish has a head, unlike a ball, each side could be its head, so when my fish reach the right side, I want to let them turn around, and now they are just moving backward.

PImage fishpic;

Fish [] groupers = new Fish[5];

void setup() {
size(800, 800);
stroke(10);
strokeWeight(6);
line(0, 600, 800, 600);
fishpic = loadImage(“grouper.png”);
fishpic.resize(0, 80);
for (int i = 0; i<groupers.length; i++) {
groupers[i] = new Fish(50);
}
}

void draw() {
background(255);
//image(fishpic,150,0300);
for (int i = 0; i<groupers.length; i++) {
groupers[i].display();
groupers[i].fishmoving();
groupers[i].turn();
stroke(10);
strokeWeight(6);
line(0, 300, 800, 300);
}
}


class Fish {
float x;
float y;
float xSpeed;
float diameter;
Fish(float Medium) {
x=random(500);
y=random(300,750);
xSpeed = 2;
diameter = Medium;
}

void display() {
image(fishpic,x,y);
}

void fishmoving() {
x = x + xSpeed;

}

void turn() {
if (x+160 >width || x < 0 ) {
xSpeed = xSpeed * -1;
}
}
}

1 Like

for your image load it in a image sofware like irfanview and mirror it and save as a new name.

in processing load both images

have a variable that indicates whether a fish goes left or right.

When it goes left, display image 1, otherwise 2

Thank you @Chrisir I think it’s good advice. However, after I mirrored the fish pic, then somehow every two fish are sticking together, instead of going in different directions. They are swimming like this…

class Fish {
  float x;
  float y;
  float xSpeed;
  float diameter; 
  float t = 0;
  float tSpeed = 3;
  Fish(float Medium) {
    x=random(500);
    y=random(300, 950);
    xSpeed =random(1, 2.5);
    diameter = Medium;
  }

  void display() {
    image(fishpic, x, y);
    image(fishpic2, x, y);
 
  }

  void fishmoving() {
    x = x + xSpeed;
  }

  void turn() {
    if (x+140 >width || x < 0 ) {
      xSpeed = xSpeed * -1;
    }
  }
  void timing() {
    strokeWeight(1);
    rect(t, 0, 1, 60);
    t = t + tSpeed;
  }
  void newyear() {
    if (t > width) {
      t = 0;
    }
  }
  void catching() {
  }
}

PImage fishpic;
PImage fishpsa;
PImage fishpic2;

Fish [] groupers = new Fish[5];

void setup() {
  size(1000, 1000);
  stroke(10);
  strokeWeight(6);
  line(0, 600, 800, 600);
  fishpic = loadImage("grouper.png");
  fishpic.resize(0, 70);
  fishpic2 = loadImage("grouper2.png");
   fishpic2.resize(0, 70);
  fishpsa = loadImage("fishpsa.jpg");
  fishpsa.resize(0, 240);
  for (int i = 0; i<groupers.length; i++) {
    groupers[i] = new Fish(50);
  }
}

void draw() {
  background(255);
  strokeWeight(0);
  line(0, 300, 1000, 300);
  rect(0, 300, 1000, 700);
  fill(67, 42, 0);
  rect(0, 60, 800, 240);
  fill(55, 122, 216);
  image(fishpsa, 683, 60);
  for (int i = 0; i<groupers.length; i++) {
    groupers[i].display();
    groupers[i].fishmoving();
    groupers[i].turn();
    groupers[i].timing();
    groupers[i].newyear();
  }
}
void mousePressed() {
  for (int i = 0; i<groupers.length; i++)
    groupers[i].catching();
}

Here

    image(fishpic, x, y);
    image(fishpic2, x, y);

you just draw both fishs!!! No wonder they are on top.

Read again what I wrote:

Can you do this?

Warm regards,

Chrisir

Thank you @Chrisir, so after a while, finally I figured how to divided my two fishs into two single fish, I felt its kinda a progress, even though it’s still not what I wanted. By making this happen, I added another three new variables “m” “n” “mSpeed”, the problem is that I still don’t know how to do it as you said, have one variable indicates the directions of my fish.

class Fish {
  float x;
  float y;
  float m;
  float n;
  float xSpeed;
  float mSpeed;
  float diameter; 
  float t = 0;
  float tSpeed = 3;
  Fish(float Medium) {
    x=random(500);
    y=random(300, 950);
    m=random(500);
    n=random(300, 950);
    xSpeed =random(1, 2.5);
    mSpeed =random(1, 2.5);
    diameter = Medium;
  }

  void display() {
    image(fishpic, x, y);
    image(fishpic2, m, n); 
  }

  void fishmoving() {
    x = x + xSpeed;
  }

  void turn() {
    if (x+140 >width || x < 0 ) {
      xSpeed = xSpeed * -1;
    }
  }
   void fish2moving() {
    m = m + mSpeed;
  }
    void turn2() {
    if (m+140 >width || m < 0 ) {
      mSpeed = mSpeed * -1;
    }
  }
  void timing() {
    strokeWeight(1);
    rect(t, 0, 1, 60);
    t = t + tSpeed;
  }
  void newyear() {
    if (t > width) {
      t = 0;
    }
  }
  void catching() {
  }
}
 PImage fishpic;
PImage fishpsa;
PImage fishpic2;
PImage catching;

Fish [] groupers = new Fish[5];

void setup() {
  size(1000, 1000);
  stroke(10);
  strokeWeight(6);
  line(0, 600, 800, 600);
  fishpic = loadImage("grouper.png");
  fishpic.resize(0, 70);
  fishpic2 = loadImage("grouper2.png");
  fishpic2.resize(0, 70);
  fishpsa = loadImage("fishpsa.jpg");
  fishpsa.resize(0, 240);
  catching = loadImage("catchingfish.png");
  catching.resize(0, 240);
  for (int i = 0; i<groupers.length; i++) {
    groupers[i] = new Fish(50);
  }
}

void draw() {
  background(255);
  strokeWeight(0);
  line(0, 300, 1000, 300);
  rect(0, 300, 1000, 700);
  fill(67, 42, 0);
  rect(0, 60, 800, 240);
  fill(55, 122, 216);
  image(fishpsa, 683, 60);
  image(catching,0,60);
  for (int i = 0; i<groupers.length; i++) {
    groupers[i].display();
    groupers[i].fishmoving();
    groupers[i].turn();
    groupers[i].fish2moving();
    groupers[i].turn2();
    groupers[i].timing();
    groupers[i].newyear();
  }
}

void mousePressed() {
  for (int i = 0; i<groupers.length; i++)
    groupers[i].catching();
}

Hello,

Setting the marker indicating the direction

your code:

better

  void turn() {
    if (x+140 > width  ) { // right border 
      xSpeed = abs(xSpeed) * -1;  // always neg! 
      fishIsMovingLeft = true;  // set our marker for direction 
    }

   if ( x < 30 ) {  // left 
      xSpeed = abs(xSpeed);  // always pos! 
      fishIsMovingLeft = false;  // set our marker for direction 
   }
  }//func 

Displaying the Fish

  void display() {
    if(fishIsMovingLeft)  // evaluate the marker for direction
       image(fishpic, x, y);
    else 
      image(fishpic2, x, y); 
  }

Remark

  • I don’t know why you have m,n and fish2moving() and turn2()

Chrisir

Thank you @Chrisir

I never realized that the function “abs()” could be used here, in fact, it’s the first time I use “abs()”, such a lesson for me.

To remark: I guess I was trying to let the two fish moving individually first and then find some way to let them swim in the correct direction. But you just made the program instantly display a correct picture, compare with you, I was too stupid.

I don’t know if it’s ok to ask another question under the same topic, but my program just run into a new error.

So I am trying to let users catch the fish, and every time they catch one, I created a scoreboard to count. But somehow the number on my score doesn’t add when they catch a new fish, but I feel like there is no flaw in my syntax.

PImage fishpic;
PImage fishpsa;
PImage fishpic2;
PImage user;
PImage calendar;

Fish [] groupers = new Fish[20];

void setup() {
  size(1000, 1000);
  stroke(10);
  strokeWeight(6);
  line(0, 600, 800, 600);
  fishpic = loadImage("grouper.png");
  imageMode(CENTER);
  fishpic.resize(0, 70);
  fishpic2 = loadImage("grouper2.png");
  fishpic2.resize(0, 70);
  fishpsa = loadImage("public service announcement.jpg");
  fishpsa.resize(0, 240);
  user = loadImage("user.png");
  user.resize(0, 240);
  calendar = loadImage("calendar.png");
  calendar.resize(1000, 70);
  for (int i = 0; i<groupers.length; i++) {
    groupers[i] = new Fish(50);
  }
}

void draw() {
  background(255);
  strokeWeight(0);
  rect(0, 300, 1000, 700);  
  fill(67, 42, 0);
  rect(0, 60, 800, 240);
  fill(232, 176, 146); 
  image(fishpsa, 840, 180);
  image(user, 90, 180);
  fill(55, 122, 216); 
  image(calendar, 500, 25);
  line(350, 0, 350, 59);
  line(835, 0, 835, 59);
  for (int i = 0; i<groupers.length; i++) {
    groupers[i].display();
    groupers[i].fishmoving();
    groupers[i].turn();
    groupers[i].timing();
    groupers[i].remonth();
    groupers[i].numberOFfish();
  }
}

void mousePressed() {
  for (int i = 0; i<groupers.length; i++) {
    groupers[i].catching();
  }
}
class Fish {
  float x;
  float y;
  float xSpeed;
  float diameter; 
  boolean fishMovingLeft = false;
  float t = 0;
  float tSpeed = 2;
  int fishnumber = 0;
  Fish(float Medium) {
    x=random(500);
    y=random(350, 920);
    xSpeed =random(1, 10);
    diameter = Medium;
  }

  void display() {
    if (fishMovingLeft)  
      image(fishpic, x, y);
    else 
    image(fishpic2, x, y);
  }

  void fishmoving() {
    x = x + xSpeed;
  }

  void turn() {
    if (x+70 > width  ) { 
      xSpeed = abs(xSpeed) * -1;  
      fishMovingLeft = true;
    }

    if ( x-65 < 0 ) {  
      xSpeed = abs(xSpeed);  
      fishMovingLeft = false;
    }
  }

  void timing() {
    strokeWeight(1);
    rect(t, 0, 1, 60);
    t = t + tSpeed;
  }
  void remonth (){
    if (t > width) {
      t = 0;
    }
  }
  void numberOFfish() {
    fill(55, 122, 216);
    text("Can you catch 20 fish?", 250, 150);
    textSize(30);
    text("Fish: " + fishnumber, 250, 200);
  }
  void catching() {
    float distance = sqrt((x-mouseX)*(x-mouseX)+(y-mouseY)*(y-mouseY));
    if (distance<=20 && ((t > 350)&&(t<835))) {
      x = -50;
      y = -50;
      fishnumber = fishnumber +1;
    }
  }
}

I just wanted to mention that when you initially let the fishes swim in different direction randomly (I haven’t checked) our direction marker is not yet set correctly. This happens only when a reflection occurs. You could correct/add this.

Regarding score

Please check the dist() command to get the distance

I think t could be a problem, it’s increased every frame so the condition for t is only met a few seconds (in catching ())

Distance 20 is also very small, try 66

Sorry, I don’t really get it, the reason I set “t” to allow the user only can catch fish during certain months(the calendar on the top of the program), so basically I think “t” itself is a condition for the function catching.

  void catching() {
    float distance = dist(x,y,mouseX,mouseY);
    if (distance<=66 && ((t > 350)&&(t<835))) {
      x = -50;
      y = -50;
      fishnumber = fishnumber +1;
    }
  }

Ok

But did you try without checking t?

I just tried run it without checking t

  void catching() {
    float distance = dist(x,y,mouseX,mouseY);
    if (distance<=66) {
      x = -50;
      y = -50;
      fishnumber = fishnumber +1;
    }
  }

I found an interesting thing, so at the beginning, before I click any fish, the scoreboard shows 0

then after I catch one fish, the board shows a number like 0 and 1 overlapped, and it shows like this while I catching other fish.

Then when I finish catching all fish, the scoreboard

shows the number 1

And then I added " checking t " back, it shows the same thing, so I feel like its not because of t

1 Like

Sorry for being late.

This is part of the class, which is wrong. Instead it must be a global variable, so before setup().

// score 
int fishnumber = 0;

fishnumber / score is not a property of one fish but of the Game Logic as a whole therefore it must be a global variable, so before setup().

Remark

a line command in setup makes no sense.

Thank you @Chrisir

Now its working :slight_smile:

And how about this new code in setup()

void setup() {                               
  size(1000, 1000);
  imageMode(CENTER);
  fishpic = loadImage("grouper.png");              
  fishpic.resize(0, 70);
  fishpic2 = loadImage("grouper2.png");
  fishpic2.resize(0, 70);
  fishpsa = loadImage("public service announcement.jpg");
  fishpsa.resize(0, 240);
  user = loadImage("user.png");
  user.resize(0, 240);
  calendar = loadImage("calendar.png");
  calendar.resize(1000, 70);
  for (int i = 0; i<groupers.length; i++) {  
    groupers[i] = new Fish(50);
  }
}
1 Like

To chime in on this subject, I’d would invert the grouper image by multiplying the image width by -1 and resizing it

we tried scale(-1,1); but it didn’t really work…

that’s why we work with 2 different images