Two of my artistic hobbies are doodling and creating art from code. As I was doodling city skylines (see image to the right), I wondered whether I could do the same using code. This is a typical approach to creativity, combine two different subjects to create something new. And, I love a challenge.
With this in mind, I began developing the code which would create something similar using p5.js, a javascript library designed for creating art. The result is the featured image you see in this post. A side benefit of using p5.js and not python is that I can also share via the web and allow you to try it for yourself.
Click here to see cities being built in real-time. if using from your computer, you can also pause the looping and save images.
- Hit the ‘L’ key to turn looping on or off
- Hit the ‘S’ key to save a screenshot of the current image.
Design Concept
- Create a function to create squiggly lines to simulate an ink pen
- Create a function to create rectangles using those squiggly lines
- Add the same building with transparency flipped vertically to create a reflection
- Create a function to create windows within the rectangles based on the size of the buildings
- Draw 3 overlapping taller rows of buildings from low saturation to normal to simulate buildings in the distance
- Add grain texture to the entire image
Click here to learn more about p5.js
Do you have other ideas? Please share in the comments.
function squigLine (point1, point2, sw) {
strokeWeight(sw);
//stroke(color('White'));
distance = dist(point1.x,point1.y,point2.x,point2.y);
jaggyFactor = .05; // .1 is default and influences number of points - jagginess
noiseFactor = 1; //1 is default and indicates smoothness, greater = less smooth
numpoints = int(distance * jaggyFactor);
if (numpoints < 3) {
numpoints = 3;
}
prevX = point1.x;
prevY = point1.y;
// Add some noise to the line
for (let i = 0; i <= numpoints; i++) {
let x = lerp(point1.x, point2.x, i / numpoints);
let y = lerp(point1.y, point2.y, i / numpoints);
x += random(-noiseFactor, noiseFactor);
y += random(-noiseFactor, noiseFactor);
//point(x, y);
if (random() > .01) {
line(prevX,prevY,x,y);
}
prevX=x;
prevY=y;
}
}
2 thoughts on “Creating Realistic Cities with p5.js”
This is so cool!! Have you looked into making non-rectangular buildings as well?
Hey Mitch. Not yet. The next two enhancements are likely to be painting the buildings with a watercolor effect and stacking extra sections (possibly other shapes) so there’s even more variability. But, as is normal with me, I will likely end up working on something entirely different first.