Art of CodeArt of Code

The Art of Code is a MA/MFA class that I am teaching at Multidisciplinary New Media department in Paris College of Art. The course provides an introduction to coding for artists and designers who are willing to learn and use it as a form of creative expression.

This website documents
the course materials. If you have any questions, you can contact me on Twitter.

Networking

Many of the previous examples are individual sketches with a single user. Utilizing socket.io library, we will build a real-time app that more than one person can interact using multiple browser windows. Then, we will create two node servers that interact with each other. That could be an exciting way to enable collaboration on a single output while numerous people working on separate sketches, and sending each other messages.

Daniel Shiffman has excellent videos explaining the process of creating a server from scratch and making sockets work. If you have no idea about how to start with Node.js they could be beneficial to watch beforehand.

Introduction to Node

Using Express with Node

Connecting Client to Server with Socket.io

Shared Drawing Canvas

Sockets

First, we need a simple node server using express.js and socket.io.


let express = require("express");
let http = require("http");
let socket = require("socket.io");

let app = express();
app.use(express.static("public"));

// Create Server
let port = process.env.PORT || 3000;
let server = http.createServer(app).listen(port, function() {
  console.log("Listening on port " + port + "...");
});

// Create Socket
let io = socket(server);

Socket.IO is event-based. We add event listeners using socket.on("eventName", functionToCall) There are pre-defined events like: "connection", "disconnect" that you can listen to, and there are user-defined events where we decide the event name ourselves. User-defined events are triggered by p5.js.

After we receive the event from p5.js, we trigger socket.broadcast.emit("eventName", eventData) for broadcasting the event to other clients (browsers) that are connected to the server. This way, we close the loop:

  1. One client (browser) triggers an event
  2. Node server receives the event
  3. Node server broadcasts to other clients (browsers that are connected)
  4. p5.js script receives the event and makes something with it

// Listen for new connections
io.sockets.on("connection", newConnection);

function newConnection(socket) {
  console.log("New connection " + socket.id);

  // Listen for incoming data
  socket.on("data", dataMessage);
  
  function dataMessage(data) {
    socket.broadcast.emit("data", data);
  }
}

In HTML, we need to include the socket.io javascript library. It's simple with node.js, as stated in socket.io website: A standalone build of the client is exposed by default by the server at /socket.io/socket.io.js.


<script src="/socket.io/socket.io.js"></script>

In the p5.js sketch, we first establish the connection.


let socket;

function setup() {
  socket = io();
}

Then we trigger an event whenever the mouse is dragged. That is a constant stream of events that are sent to the node server as long as the mouse is being dragged.


function mouseDragged() {
  fill(255, 0, 0);
  circle(mouseX, mouseY, 20);

  let data = {
    x: mouseX,
    y: mouseY
  };
  socket.emit("data", data);
}


function setup() {
  socket.on("data", incomingData);
}
function incomingData(data) {
  fill(255);
  circle(data.x, data.y, 20);
}

Collaborating across two or more sketches

Numerous people working on separate p5.js sketches can send each other messages and collaborate. For example, a sketch might get microphone input level, another sketch might visualize it, while a third one can use the data to synthesize audio. Of course, there are few things to keep in mind: Event names should match on every end (server and clients). To achieve this, we implement a single event and pass the data as an associative array within that single event.


// app.js
socket.on("data", dataMessage);

  function dataMessage(data) {
    socket.broadcast.emit("data", data);
  }
}

// script.js
function setup() {
  socket.on("data", incomingData);
}

function incomingData(data) {
  // do something with data
}

The principle is the same with the previous example. The only difference is that instead of connecting to a local server from p5.js, we connect to a central server that handles all the broadcasting. There is no change in node server code, and there is a minor change in p5.js code. Instead of connecting with socket = io() to the local server, we connect to a remote server specified by address. Each sketch should connect to the same server. You can make this locally. Or, it is also simple with Glitch. You have to use ...glitch.me/ address of the project.


let socket;
let address = "https://address-of-the-sketch.glitch.me/";

function setup() {
  socket = io.connect(address);
}

Code

You can find the full code at GitHub and demo in Glitch. (Open the demo with multiple browser windows).

Read More

Objects as associative arrays

Chat example with socket.io