1 – Never Before Seen

The first entry in a 100 day of generative art and creative code project. My goal is to learn a few new things each project, document them to help clarify my understand and move on. By the end, I hope to be creating some cool things and learn a ton.

Click on the image below to re-arrange, refresh for new color palette. Full screen here.

Playing with the excellent GreenSock tween library and CSS shapes. And setting up with parcel for a journey back into creative code.

CSS Triangles?

Making shapes with css is fun. Boxes are easy, of course. Circles and ellipses are the same boxes with border radius tweaks. But triangles compelled some research on how the border properties actually work.

Here’s how to make a triangle in css (from Chris Coyier)

<div style="
      width: 0;
      height: 0;
      border-left: 50px solid transparent;
      border-right: 50px solid transparent;
      border-bottom: 100px solid red;">
</div>

Border sizes are outside of the content size, setting height and width to 0 applies to the content and doesn’t affect borders. If we assume borders are straight rectangles it is hard to imagine how this tapers into a triangle The secret is that borders join other borders at 45 degree miter type joint rather than overlapping square. If there’s no top border the two sides will join each other at the top. Detailed discussion here.

Colors

The project generates a color palette using color-scheme-js

var scheme = new ColorScheme;
scheme.from_hue(randomIntFromInterval(0,100))         // Start the scheme 
    .scheme('analogic')     // Use the 'triade' scheme, that is, colors
    // selected from 3 points equidistant around
    // the color wheel.
    .distance(0.1)
    .add_complement(false)
    .variation('hard');  
var colors = scheme.colors();

Then a number of divs are generated with random sizes, shapes (circle, rectangle or triangle), assigned colors and inserted into the dom.

Tweens

Results are then rearranged by tweening to random coordinates and rotating using TweenMax

function shuffle() {
    let divs = document.getElementsByTagName("div");
    for (let i = 0; i < divs.length; i++) {
        TweenMax.set(divs[i], { xPercent: -50, yPercent: -50, left: 0, top: 0 })
        TweenMax.to(divs[i], 1.5, {
            rotation: "+=" + randomIntFromInterval(20, 270),
            x: randomIntFromInterval(Math.floor(maxW * 0.15), Math.floor(maxW * 0.75)),
            y: randomIntFromInterval(Math.floor(maxH * 0.15), Math.floor(maxH * 0.75))
        })
    }

}

with every mouse click and/or touch

document.addEventListener("touchstart", (e) => {
    e.preventDefault();
    shuffle();
});

document.addEventListener("click", (e) => {
    e.preventDefault();
    shuffle();
})

The number of objects created and their sizes depends on the size of the screen and these constraints are regenerated with each resize after clearing the dom of its previous divs

document.body.innerHTML = '';

Building Electron Applications with Multiple Pages

If you don’t want to dive into webpack/framework build frame, but need an easy way to use multiple pages in electron with simple navigation, this might work for you.

There are a few approaches to handling multiple pages in an electron app. Since chromium comes bundled with electron, essentially a web browser, and electron runs a node application, one approach is just to serve multiple pages as external html files. The same way you might on a web server. You can load these external pages, locally or remotely, into the current BrowserWindow via links or api calls. But results aren’t as seamless as an application. There’s a notorious screen flash that happens sometimes when the external page loads. Though mitigated somewhat with tweaks, electron is really designed for single page/cached content applications.

Multiple pages can be implemented through views, available in various frameworks with architectures for routing and templating, like Vue, React and Angular. These assemble pages by building custom objects loaded into memory. But if we don’t want to use a framework with their attendant complexities, and don’t want janky window flashing from hard links, there’s a third alternative.

Deep in the source for https://github.com/electron/electron-api-demos lies a useful approach. I decided to simplify, deconstruct and generalize it here. I’ll also integrate Bootstrap 4 to leverage its tab components to do the actual navigation. Because, lazy.

To build from scratch:

1. git clone https://github.com/electron/electron-quick-start
2. cd electron-quick-start
3. npm install bootstrap
4. npm install jquery
5. npm install popper.js
6. npm install

Now, in the head of index.html add:

<link rel="stylesheet" href="node_modules/bootstrap/dist/css/bootstrap.min.css">

In the script section of the same index.html add:

<script>
window.$ = window.jquery = require("jquery");
window.popper = require("popper.js");
require("bootstrap");
require('./renderer.js'); 
</script>

Now the electron app is fully wired for bootstrap. Next we’ll create external templates for each of our pages. Here’s an example of a template for the main page created in an external file called main.html:

<template>
<div class="container template" id="main-template" data-tab="main">
<!-- all the stuff for the main page goes here... -->
</div>
</template>

Create one of these files for each page in the application. Ensure that each has its own unique id and data-tab value. Next let’s go back and tweak the index.html to reference the templates. In the head section of the html:

<link rel="import" href="main.html">
<link rel="import" href="settings.html">
<link rel="import" href="help.html">
<link rel="import" href="contact.html">

for as many template pages as we created.

Next add the following to the script block in the same index.html file:

const links = document.querySelectorAll('link[rel="import"]');
links.forEach((link) => {
    let template = link.import.querySelector('template');
    let clone = document.importNode(template.content, true);
    let target = clone.querySelector(".template").dataset.tab;
    document.getElementById(target).appendChild(clone);
});

What this script fragment does is look for every import link in the head section, which it then loads and caches in memory as a document fragment and appends to an html element in the dom with an id that matches the id referenced by the data-tab in the template. Templates are a very cool, seldom utilized, feature baked into HTML5.

So all that’s left is replacing the body of index.html with the following to provide navigation and some slots and scaffolding for the pages.

<div class="container my-4"><div class="row"><div class="col-2">
<div class="nav flex-column nav-pills" id="v-pills-tab" role="tablist" aria-orientation="vertical">

<a class="nav-link active" id="home-tab" data-toggle="pill" href="#home" role="tab" aria-controls="home" aria-selected="true">Home</a>
<a class="nav-link" id="about-tab" data-toggle="pill" href="#about" role="tab" aria-controls="about" aria-selected="false">About</a>
<a class="nav-link" id="contact-tab" data-toggle="pill" href="#contact" role="tab" aria-controls="contact" aria-selected="false">Contact</a>
<a class="nav-link" id="settings-tab" data-toggle="pill" href="#settings" role="tab" aria-controls="settings" aria-selected="false">Settings</a>

</div></div>

<div class="col-10"><div class="tab-content" id="v-pills-tabContent">

<div class="tab-pane fade show active" id="home" role="tabpanel" aria-labelledby="home-tab"></div>
<div class="tab-pane fade" id="about" role="tabpanel" aria-labelledby="about-tab"></div>
<div class="tab-pane fade" id="contact" role="tabpanel" aria-labelledby="contact-tab"></div>
<div class="tab-pane fade" id="settings" role="tabpanel" aria-labelledby="settings-tab"></div>

</div></div>
</div>
</div>

Now run:

npm start

and voila. A multipage electron application using HTML5 templates and bootstrap for easy styling and navigation.

Complete source code available on https://github.com/kentskyo/spa-electron-bootstrap

(For a quickstart on electron in general, along with a solid discussion of options for packaging, updating and software certificates, I found this concise resource very well put together: https://www.learnelectron.com)

Equations of Form

Some people like zoos or art exhibits, I like to explore abstract species of thought. Yesterday I spent the afternoon roaming around L-systems.

L-systems are little self-contained universes of alphabets, axioms, and rules. The alphabets are building blocks and may be any symbols or letters imaginable. The axiom is an initial combination of those letters and the rules change the axiom, morphing it into something else generation by generation. This simple trifecta creates an infinity of forms.

L-systems are deterministic and linear. This means given a certain starting point and a certain set of rules, they will always produce the same results. They don’t have the ability of chaotic systems to veer off in unexpected directions, although there may be ways of coaxing them to do so depending on how their results are interpreted. Part of their algorithmic DNA is recursion. A fractal reflexiveness that applies rules to the results of rules in an infinite spiral.

We can map L-systems graphically and they can produce intricate patterns with an affinity to the natural world: leaves, trees, clouds, terrain. But they don’t have to be interpreted graphically. They could be mapped to poetry, music, rhythm, dance.

Here’s the relevant Processing code that interpreted the L-system for the graphic above:

// Symbols: F+-[]
// Axiom: F
// Rules F->FF+[+F-F-F]-[-F+F+F]

var axiom = "F";
var sentence = axiom;
var rules = [];

rules.push({l:"F",r:"FF+[+F-F-F]-[-F+F+F]"});

// This is the entire l-system processor
function generate() {
  var newSentence = "";
  for (var i = 0; i < sentence.length; i++) {
    var ch = sentence.charAt(i);
    var nl = newSentence.length;
    for (var j = 0; j < rules.length; j++) {
      // look for one rune that matches this symbol, apply it and bail
  			if (ch == rules[j].l) { 
  				newSentence += rules[j].r;
  				break;
  			}
    }
    // if no rules matched, return symbol unchanged
    if (nl === newSentence.length) newSentence += ch; 
  }
  sentence = newSentence;
  console.log(sentence);
  interpret();
}


// Interpret l-system generated string using old logo method
// ...as if moving a turtle around to draw lines
var len = 60
var angle = 20

function interpret() {
  len *= 0.5;
  resetMatrix();
  translate(width/2, height);
  background(0);
  stroke(255,0,0);
  for (var i = 0; i < sentence.length; i++) {
    var ch = sentence.charAt(i);
    if (ch == "F") {
      line(0,0,0,-len);
      translate(0, -len);
    } else if (ch == "+") {
      rotate(radians(angle));
    } else if (ch == "-") {
      rotate(-radians(angle));
    } else if (ch == "[") {
      push();
    } else if (ch == "]") {
      pop();
    }
  }	
}

Inspiration for this came from Dan’s. always entertaining and educational, Coding Challenges; an even deeper dive can be found here.

The Art of Particles

Particle systems first appeared in 1982. A special effect artist, Bill Reeves, used them in Star Trek II: The Wrath of Kahn for a scene called the “genesis effect.”

In essence a particle system is just an algorithm controlling particle creation and interaction. In practice this normally consists of an emitter, usually invisible, positioned somewhere in the world and tiny graphic elements (particles) the emitter spits out from its hidden position, all at once or in intervals.

By varying how, when and where of particle creation and what forces act upon them, we can simulate a variety of real-world effects like fire, smoke and rain. In theory any physical phenomenon could be simulated by a particle system since all matter is basically made up of particles (atoms.) However, the computational cost of juggling even a few thousand particles rapidly becomes a bottleneck. But with a modest number of particles, and clever coding, one can still produce cool effects, even in a lowly web browser.

For code geeks, particle systems are great projects to make from scratch, but this post is focused on their use in generative art. We will leverage Phaser, an engine used to create HTML5 games, primarily because it comes with a built in particle system and physics engine (useful for applying forces to the particles, like gravity and acceleration.) You could also experiment with these systems in Processing and Daniel Shiffman has some great tutorials on a simple prototype.

Here’s a self-contained Phaser scaffold to kick off experiments:

<!DOCTYPE html>
<html>
<head>
<meta charset='UTF-8'>
<meta name='viewport' content='initial-scale=1 maximum-scale=1 user-scalable=0'> 
<title>Phaser Scaffold</title>
<style>
 body {
 background-color: #000000;
 border: 0;
 margin: 0; 
 overflow: hidden:
 }
</style>
</head>
<body>
<script src='https://cdnjs.cloudflare.com/ajax/libs/phaser/2.6.1/phaser.min.js'></script>
<script type="text/javascript">
var game = new Phaser.Game('100%', '100%', 
 Phaser.AUTO, 'scratchpad', 
 {preload:preload, create:create}
 );

function preload() {
}

function create() {
}


</script>
</body>

Phaser looks for function names to call at specific times. The function preload() is called for loading images and assets, create() is then called after all assets are loaded. After that, if update() and render() are defined, they are called in the standard game loop pattern at the maximum browser framerate.

Creating particles with this scaffold is easy. We’ll just load a small image to serve as the particle and define an emitter with some parameters to shoot copies onto the scene:

var emitter;
var maxParticles = 1000;
var explode=false;
var lifespan=5000;
var frequency=5;
var quantity=0;    // if 0 and explode false then continuous

function preload() {
  game.load.image('particle', 'p1.png');
}

function create() {
  emitter = game.add.emitter(game.world.centerX, game.world.centerY, maxParticles);  
  emitter.makeParticles('particle');
  emitter.start(explode, lifespan, frequency, quantity);
}

Particles will either explode from the emitter all at once, like a firework, in which case:

  • explode = true
  • lifespan = how long the particles “live” in milliseconds, after which they dissappear from screen
  • frequency has no effect if explode = true
  • quantity is how many particles are created during the explosion, up to amount in maxParticles

For stream from the emitter in a continuous flow of particles:

  • explode = false
  • frequency = interval in milliseconds between firing particles
  • quantity = 0 means keep firing particles indefinitely at the frequency specified, if maxParticles are reached, wait until one dies before firing another to take its place; if quantity = n just fire n particles total and then stop

Emitters have many additional properties to tweak besides what’s set in the start parameter. For example:

  • minParticleScale, maxParticleScale sets the range between the particle is randomly scaled when created
  • setAlpha(0.1, 0.9); as an example, sets the range of the transparency applied to the particle
  • width and height set the the area in which particles emerge, by default this is a single point, like a cannon, but it can be expanded to any size and the particle will emerge from a random location within this area
  • minParticleSpeed, maxParticleSpeed control a range of velocities each particle is assigned

Here’s a quick technique for masking images in Phaser:

  var mask = game.add.graphics(0, 0);
  mask.beginFill(0xffffff);
  mask.drawCircle(game.world.centerX, game.world.centerY, 645);

Which creates a mask that be applied to any image, essentially “clipping” what’s displayed of the image to just the size and shape of the mask. That’s all the elements needed to create the following project:

See the Pen There’s Bugs in My Code by Kentskyo (@kentskyo) on CodePen.0