Concept
While watching Casey Reas’s talk, I realized that using looping to create grids is one powerful way to create generative art. I started off by generating a grid of points using loops and thinking about what I could do with it. I remembered the dots and boxes game from childhood-
I remember making patterns on these grids alone by drawing lines in a random fashion , I wanted to see whether I could use a program to do something similar with different colors that would look appealing to the audience .
I started by programming what I call a “seeker” . The seeker joins the points in a path such that :
- No point is visited more than once
- the points that can be chosen are either horizontally or vertically adjacent points (diagonals can’t be drawn)
- The seeker stops when all the points around it are joined
However, I found that to create something visually appealing , I would need multiple seekers of different colors . So, I used loops to create teams of seekers . The interaction of these seekers over time fill the grid and give a visually appealing effect as these grid paths are drawn .
Because the seekers can draw over each other, I wanted to mix the colors where this happens . Thus I defined colors in RGBA format and defined alpha value to be 150 so that the colors can be mixed to some extent when one is drawn over the other
Sketch
The sketch is embedded below :
Running the sketch again gives a different output every time that is based on the random properties of the Seeker object . (namely the random point at which the seeker starts from + the random selection of the path).
Code that I am proud of
I am proud of the code for the seeker class and especially the code for the getAdjacentPoints(points) function in this class :
getAdjacentPoints(point) { //gets adjacent points in 4 directions
let adjacent = [];
//the following 3 lines are to make sure the argument point is a point on an extended form of the grid (if the grid is extended forever)
let currentIndex = grid.indexOf(point);
let x = currentIndex % cols; // cols is initialized in setup()
let y = floor(currentIndex / cols);
// Define the four cardinal directions
const directions = [
{ dx: 0, dy: -1 }, // Up
{ dx: 0, dy: 1 }, // Down
{ dx: -1, dy: 0 }, // Left
{ dx: 1, dy: 0 } // Right
];
// Check each direction for valid adjacent points
for (let dir of directions) {
let newX = x + dir.dx;
let newY = y + dir.dy;
if (newX >= 0 && newX < cols && newY >= 0 && newY < rows) { //Check if this is withing the bounds of the grid
let index = newY * cols + newX; // finds index in the array grid
let adjacentPoint = grid[index]; //keep in mind grid is an array of coordinates (array of vectors))
adjacent.push(adjacentPoint);//pushes the adjacent point to adjacent
}
}
return adjacent; //returns an arry of possible adjacent points
}
Although I thought this would be simple , I had problems implementing this class in the beginning (especially about looking at the edge cases such as a point on the edge ) .
I am also proud of the idea of thinking about the seeker objects as ‘teams’ and realizing that the array containing each seeker had to be shuffled to display colors in equal proportion .
Challenges
The order in which the seekers are initiated matters because they can draw over each other. Thus, if we create a team of yellow seekers for example, and all of the team is appended at the end of the seekers array, the output will have a grid dominated by the yellow seekers (since yellow is drawn on top) . To fix this, I have implemented a method to shuffle the array called shuffleArray (which is an algorithm called Fisher-Yates Algorithm). This is applied to the array to shuffle all the teams of ‘seekers’, so the final output has the colors uniformly distributed.
Reflection and Scope for Future improvements
Since we had already learnt about classes in p5 when I created this project, I decided to use classes to simplify the code. However, loops remain a big part of the code both in generating the grid and in describing how the lines are chosen. I am happy with the overall result of what I got. There is some scope of improving it – especially in exploring how seekers that consider joining points diagonally too would look like (I tried doing it, but it looked very messy – maybe it’s possible to figure out a way to make it cleaner). In addition, in my drawing the points are arranged in a grid (rectangular). However, it would be interesting to exploring different kinds of grids such as a circular grid of points and modify the seeker accordingly.