Raindrop Simulator with Wind

For my project this week I knew I wanted to do something related to water. I decided to pick rain, something I miss when in this country. Below you can see the program I created, and you can view the full code on my GitHub here.

The program is simple, it generates raindrops that will fall down the screen. There are sliders to modify the rain’s density and the wind’s speed “blowing” the rain either left or right. To do this, there is an array containing a Drop object that stores a position, velocity, and acceleration vector, that will update itself when step() is called. In the draw() function, there is a loop to iterate through the rain array to update the position of each raindrop. To simulate wind, the acceleration vector is given an x-value based on the current value of the wind slider. This makes the vector move along the x-axis to emulate wind blowing the rain particles. After updating the position, it will draw a line based on the length of the raindrop and its previous x position. The Drop class can be seen here:

class Drop {
  constructor(vel, acc, angle) {
    this.len = random(10, 15);
    this.pos = createVector(random(width), -this.len);
    //slightly varying velocity so they all dont fall at the same exact speed
    this.vel = createVector(0, random(0.5, vel));
    this.acc = createVector(angle, acc);
  }
  step() {
    this.vel.add(this.acc);
    this.pos.add(this.vel);
    //make sure the drops stay in bounds of screen
    if (this.pos.x > width) {
      this.pos.x = -this.len;
    }
    if (this.pos.x < -this.len) {
      this.pos.x = width;
    }
  }
  show() {
    //draw raindrop
    stroke(209, 255, 251);
    line(
      this.pos.x,
      this.pos.y,
      this.pos.x - this.vel.x,
      this.pos.y - this.len
    );
  }
}

Overall, I don’t think there is much else I can do to improve this program. One idea I had was to try to have an effect such as a ripple when the drop would hit the ground. Perhaps it would also be interesting to try to emulate the rain in three dimensions, which would allow for wind to blow in two different dimensions.

Self-Avoiding Walker navigating through RGB space

The two components I decided to choose were to make a self-avoiding walker and have it navigate through an RGB space. The program is below:

The code for my program can be found on my GitHub here. EDIT: I really quickly added a reset function so you don’t need to constantly refresh the page to restart the walker.

Essentially, the program creates an invisible grid for the walker to travel on and then checks what adjacent points have been unvisited. It will then randomly choose one of the valid directions and travels there. The points are colored and are made so the RGB values are mapped based on the current coordinates of the walker. Red is mapped to x, and green is mapped to y. Blue is simply given a random value from 0-255 since the space is only two-dimensional. The program will continue until the walker gets stuck, meaning there are no unvisited nodes adjacent to it that can be visited. The code is a heavily modified version of the barebones walker we used in class.

Originally, it was going to be much closer to what the original walker code was like, but I opted to use the grid because I thought it would be much easier to track the coordinates that have been visited. Also, the original walker is small and hard to see, so I decided to use a more visually appealing and visible pathing. When I first tried to tackle the checking adjacent points problem, the code I had was using the original random 1-4 picker, and keeping the walker in a while loop if the chosen coordinate was within an array of coordinates to avoid. However, this was really inefficient, since the walker would have to iterate through an array of coordinates that go progressively larger over time every time it tried to move, and it made the program slow down if the program was able to go long enough.  After doing some research into other walker programs, I realized there was a much easier way to do the checking. This is how I came to develop the grid instead. Each coordinate in the array is given a value of false, which is then changed to true if the walker chooses that coordinate. You can then have a simple function that will return the boolean value of the coordinates adjacent to the walker.

//checks to make sure the point is unvisited and in bounds
function isValid(i, j) {
  if (i < 0 || i >= cols || j < 0 || j >= rows) {
    return false;
  }
  return !grid[i][j];
}

 

If there are visited nodes adjacent to the walker, it will not add it to the array of options it will randomly choose from to make its next move.

//all adjacent points on grid
let allOptions = [
  { dx: 1, dy: 0 },
  { dx: -1, dy: 0 },
  { dx: 0, dy: 1 },
  { dx: 0, dy: -1 },
];

...

let options = [];
    for (let option of allOptions) {
      let newX = this.x + option.dx;
      let newY = this.y + option.dy;
      if (isValid(newX, newY)) {
        options.push(option);
      }
    }
    //chose a random direction to move in
    if (options.length > 0) {
      let step = random(options);
...

    } else {
      //ends program if theres nowhere to go
      console.log(`I'm stuck!`);
      this.stuck = true;
    }

Honestly, there was a lot more I wanted to do with this program that I did not get to achieve. The main issue stemmed from the fact that during the development process of my program. I made a mistake debugging a loop, which caused the IDE to get stuck and crash the page. In a stroke of genius, I had completely forgotten to save the program I was writing at any point, meaning I had lost all the code I had done, and I was now back to square one. This severely demotivated me for a while and I did not try to tackle the program again until the end of the weekend.

Another aspect of this program I intended to develop was making the walker not get stuck. It annoyed me how quickly the walker usually got itself stuck. It made it hard to see the color changes at times when the walker was occupying about 10% of the grid. Had I given myself more time after my entire program ceased to exist I probably would’ve figured out how to make this work, but unfortunately, I was unable to do so.

Originally, I had also intended to make this program a 3D self-avoiding walker that would navigate through an RGB space, because it meant I could map the z coordinate to blue. I had found some programs that would allow me to do this, but I had a hard time understanding the code and was doing a lot of trial-and-error to really understand what each part of the program was doing and how I could translate it into code of my own. I just decided to go with 2D instead because it was easier to understand, code, and debug. I think I want to try to tackle this again at some point in the future because the walker looked really nice and it would be a good opportunity to work with processing in three dimensions rather than two.

 

EDIT 9/4: After completing the two-dimensional program, I went back to attempt the three-dimensional walk again, and I managed to do so. The link to it can be found here.

The program is functionally similar to the two-dimensional program, there were extra parts that had to be added in order to make the program work in three dimensions. Also, I added some buttons that could be interacted with so that there are some options for the user to play around with. The main difference is in how the program renders the 3D path, where there is an array storing each coordinate point the walker has visited, and renders lines between each point. This means the program has to iterate through the entire array every time to render it, which does lag the program when the path gets very large. There is also a function that tries to center the camera around the path and will shift when it reaches a new min/max to account for this. You can also use the mouse to move the camera, lmb to rotate, rmb to pan, and scroll to zoom.