Basic Wave Simulator

Edit: Click the screen to play

Hi all, so I came across this webpage detailing a basic wave simulator in C# and was blown away at all the code, Wave Simulator with C# - CodeProject, figured there had to be an easier way so spent the afternoon playing around with vectors and came up with this instead, thought id share in case anyone wanted to tinker with it and see if you can improve it, mine was under 100 lines of code until the comments to make it easier to understand whats happening.

Would love feedback either way on how you could improve it

int count = 200;
Cell[][] grid = new Cell[count][count];
Cell[][] next = new Cell[count][count];
float w;
boolean paused = true;

void setup() {
  size(1000, 1000);
  colorMode(HSB);
  surface.setVisible(true);
  w = (float)width/count;
  
  //GENERATE CELLS
  for (int y = 0; y < count; y++) {
    for (int x = 0; x < count; x++) {
      grid[x][y] = new Cell(x, y);
      next[x][y] = new Cell(x, y);
    }
  }
  
  //INITIALIZE WALLS
  for (int x = 0; x < count; x++) {
    if (x >= 80 && x <= 90 || x >= 110 && x <= 120) continue;
    grid[x][50].water = false;
  }
}

void draw() {
  surface.setTitle(str(int(frameRate)));
  
  //GENERATE WAVE
  if (!paused) {
    for (int x = 0; x < count; x++) {
      grid[x][2].pos.z = map(sin(frameCount/3f), -1, 1, 0, 255);
    }
  }

  //CALCULATE SHOW FRAME AND CALCULATE NEXT FRAME
  for (int y = 1; y < count; y++) {
    for (int x = 0; x < count; x++) {
      grid[x][y].show();
      if (grid[x][y].water && !paused) {
        grid[x][y].update();
      }
    }
  }
  
  //TRANSFER NEXT FRAME TO CURRENT
  for (int y = 0; y < count; y++) {
    for (int x = 0; x < count; x++) {
      grid[x][y].pos.set(next[x][y].pos);
    }
  }
}

void mousePressed() {
  paused = !paused;
}

//CALCULATE AVERAGE HEIGHT AROUND CELL
float averageHeight(int x, int y) {
  float sum = 0;
  for (int j = -1; j <= 1; j++) {
    for (int i = -1; i <= 1; i++) {
      if (i == 0 && j == 0) continue;
      sum += grid[(x+i+count)%count][(y+j+count)%count].pos.z;
    }
  }
  return sum/8f;
}

class Cell {

  PVector pos, vel, acc;
  PVector force = new PVector();
  PVector neighbor = new PVector();
  int x, y;
  boolean water = true;

  Cell(int _x, int _y) {
    x = _x;
    y = _y;
    pos = new PVector(x*w, y*w, 127);
    vel = new PVector();
    acc = new PVector();
  }

  void update() {
    //SET VECTOR TO AVERAGE HEIGHT OF NEIGHBORS AND APPLY FORCE TO NEXT GRID
    neighbor.set(0, 0, averageHeight(x,y));
    force = PVector.sub(neighbor, pos);
    force.x = 0;
    force.y = 0;
    acc.set(force);
    vel.add(acc);
    vel.mult(0.98);
    next[x][y].pos.add(vel);
  }

  void show() {
    noStroke();
    fill(water ? color(map(pos.z, 50, 150, 130, 160), 200, 255) : 0);
    rect(pos.x, pos.y, w, w);
  }
}
6 Likes