Help with simple game (moving fish)

Can somebody help me?
I created a simple game where you have to catch fish. at the moment these fish just move from the left side to the right side of the screen.
What I need to do is make them change the direction in which they are swimming into another random direction after a random amount of seconds,
Im really lost so I would be happy if somebody could help me.
Thank u in advance:)

PS: This is the code that I used in a class to move them from left to right:
void move() {
yPos = yPos+1*sin(radians(xPos));
}

1 Like

Normally, ypos is from top to bottom; and xpos is left/right.

So your solution should be

xpos = xpos + xadd;

With int xadd = 3; (speed)

Now when the fish gets close to right side / left side or after a random time say xadd = xadd * -1; to change its direction.

As I said: normally

  • ypos is from top to bottom,
  • xpos left/right

Maybe you named them wrong?

For example in ellipse(x, y); or in nearly all the commands the first parameter is x, the second one is y.

So your statement is a bit confusing; I don’t think that this line moves the fish to the right

Maybe you can post the fish code and how you use xpos there

1 Like

thank you for the answer.
There is more to the code and it does work that the fish move from left to right.
I also get how I can move them to the other side. my problem only is that I do not understand how to make them move in a different direction after a rondom amount of seconds. How do I use time in processing? And how do I make the amount of secondes random? so sometimes they change direction after 5 seconds and sometimes after 10?

1 Like

For time we can use millis() or frameCount:

If you pick frameCount, remember that draw() is called back around 60 FPS.

So, if you wish for your fish to turn around between 5 to 10 seconds you could use this:
nextFrameChange = frameCount + (int) random(5 * 60, 10 * 60);

Then keep polling the value of frameCount until it reaches nextFrameChange:
if (frameCount >= nextFrameChange) swapDirection();

1 Like

Thank you very much :slight_smile:

I´m sorry I have to ask again because im just a beginner and I don´t get it yet.
I tried doing this (just a part of my code) but it doesnt work yet:

float speed = 5;
float xPos;
float yPos;
int nextFrameChange;

void draw(){
image(loadImage(“fish3.png”), xPos, yPos, 100, 80);
xPos = xPos + speed;

  nextFrameChange = frameCount + (int) random(1 * 60, 5 * 60);

if (frameCount >= nextFrameChange) {
speed = random(-7,7);
}

}

Did I do something worng or did I miss something?

I think the problem is, that it does
nextFrameChange = frameCount + (int) random(1 * 60, 5 * 60);
60 times per second so the nextFrameChange will alway be bigger then the frameCount so it never does chose a random speed.
How do I get the nextFrameChange to only do it after a a certain amount of time and not 60 times per second. and also the speed change shoul only happen after an amount of time and not always because it it changes 60 times per second the object is just shaking around.

Consider placing this line in setup () and inside the if-clause where you set the speed

if (frameCount >= nextFrameChange) {
    speed = random(-7,7);
    nextFrameChange = frameCount + (int) random(1 * 60, 5 * 60);
}

(Remove the line where it is now)

Remark 1

Also, please do not load an image in draw()

Instead make a global variable PImage fish;

Load the image in setup and use it in draw()

The function setup() runs only once and is therefore for preparation purposes, whereas draw() runs on and on for animation.

To load an image is time consuming and should therefore only be done in setup() and not throughout.

Remark 2

Also please use image() command with 3 parameters only, since with 5 parameters we have an implicit resize which is also costly.

Instead, use image() with 3 parameters and make a resize() command once and for all in setup() after loading.

Chrisir

Example without image

float xSpeed = 5;
float xPos=31;
float yPos=33;
int nextFrameChange;

void setup() {
  size(1800, 800);
  background(222);

  nextFrameChange = frameCount + (int) random(1 * 60, 5 * 60);
}

void draw() {
  background(222); 

  // display 
  fill(0); 
  text("fish", xPos, yPos);

  // move 
  xPos = xPos + xSpeed;

  // bounce
  if (frameCount >= nextFrameChange || xPos<0 || xPos>width) {
    if (xSpeed < 0) 
      xSpeed = random(2, 7);
    else xSpeed = random(-7, -2);

    if (xPos>width+1)
      xSpeed = random(-7, -2);
    else if (xPos<-10) 
      xSpeed = random(2, 7);

    nextFrameChange = frameCount + (int) random(1 * 60, 5 * 60);
  }
}

Note that I changed the bouncing a bit. We make sure that

  • the speed can’t become 0 and
  • we make sure that the direction must change and
  • we make sure that the fish turns when reaching a border
2 Likes

You pick another value for nextFrameChange only after frameCount reached current nextFrameChange:
if (frameCount >= nextFrameChange) swapDirection();

It’s inside funtion swapDirection() that you change nextFrameChange:

void swapDirection() {
  speed *= -1;
  nextFrameChange = frameCount + (int) random(5 * 60, 10 * 60);
}

Anyways, I did a demo sketch that has a class Fish w/ methods such as display(), update(), bounce(), touchedBoundary(), etc.:


Swimming_Fish.pde

/**
 * Swimming Fish (v1.0.2)
 * GoToLoop (2023/Jan/23)
 *
 * Discourse.Processing.org/t/help-with-simple-game-moving-fish/40679/9
 *
 * OpenProcessing.org/sketch/1805772
 */

static final boolean REMOTE = true;

static final String
  FISH_SITE = "http://" + "www.Clker.com" + "/cliparts/" + "1/f/a/i/g/d/", 
  FISH_FILE = "rainbow-fish-th.png", 
  FISH_PATH = REMOTE? FISH_SITE + FISH_FILE : FISH_FILE;

static final color BG = #0080FF;
static final int FISHES = 4, FPS = 60;

final Fish[] fishes = new Fish[FISHES];

PImage fishLeft, fishRight;
boolean paused;

void setup() {
  size(1000, 500);
  frameRate(FPS);

  populateLake();

  println("File: \"" + FISH_PATH + "\"\n");
  for (final Fish fish : fishes)  println(fish);

  fishLeft = loadImage(FISH_PATH);
  fishLeft.resize(Fish.W, Fish.H);

  fishRight = createMirrorImage(fishLeft);
}

void draw() {
  background(BG);
  for (final Fish fish : fishes)  fish.display().update();
}

void mousePressed() {
  if (paused ^= true)  noLoop();
  else                 loop();
}

Fish.pde

class Fish {
  static final int W = 100, H = 80, VEL = 3, MIN_SEC = 3, MAX_SEC = 6;
  int x, y, v, nextFrameBounce;

  Fish(final int depth) {
    this((int) random(W, width - W * 2), height / FISHES * depth + H / 4 | 0);
  }

  Fish(final int posX, final int posY) {
    x = posX;
    y = posY;
    v = random(1) < .5? -VEL : VEL;
    nextFrameBounce = getNextFrameBounce();
  }

  Fish display() {
    image(v < 0? fishLeft : fishRight, x, y);
    return this;
  }

  Fish update() {
    if (frameCount >= nextFrameBounce || touchedBoundary())  bounce();
    x += v;
    return this;
  }

  Fish bounce() {
    v *= -1;
    nextFrameBounce = getNextFrameBounce();
    return this;
  }

  int getNextFrameBounce() {
    return frameCount + (int) random(FPS * MIN_SEC, FPS * MAX_SEC);
  }

  boolean touchedBoundary() {
    final int nextX = x + v;
    return nextX < 0 || nextX > width - W;
  }

  String toString() {
    return "Fish: { x: " + x + ", y: " + y + ", v: " + v + " }";
  }
}

Functions.pde

void populateLake() {
  for (int i = 0; i < FISHES; fishes[i] = new Fish(i++));
}

PImage createMirrorImage(final PImage img) {
  final PGraphics pg = createGraphics(img.width, img.height);

  pg.beginDraw();
  pg.scale(-1, 1);
  pg.image(img, -img.width, 0);
  pg.endDraw();

  return pg.get();
}

Preload.pde

/* @pjs preload = "
     rainbow-fish-th.png,
     https://OpenProcessing-UserContent.s3.AmazonAWS.com/files/user22279/visual1805772/h836d69cccc2d9f0e47fad8e146c132d0/rainbow-fish-th.png
   "
*/

index.html

<link rel=icon href=rainbow-fish-th.png>

<script defer src=https://Unpkg.com/processing-js></script>

<canvas data-processing-sources=
  "Swimming_Fish.pde Fish.pde Functions.pde Preload.pde">
</canvas>


2 Likes

Thank you both very very much.
I understood it now and it works!
You really helped me a lot :slight_smile:

1 Like