Help with simple game (moving fish)

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 + 60 * (int) random(5, 11); // 5s to 10s range
}

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.3)
 * 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; // azure
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 + FPS * (int) random(MIN_SEC, MAX_SEC + 1);
  }

  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