Spectacle is the use of video and mixed digital media as a vessel for existing ideas.

Speculation is the investigation of this digital form, exploring the nature of software and exposing facets of digital medium itself in a way that's self-aware.

A project I learned about this semester is a YouTube channel called alantutorial. The content on this channel is, above anything else, extremely unsettling. The idea behind the videos is that this bizarre character, alantutorial, is recording a series of random and seemingly pointless tutorials to upload to his channel. These tutorials demonstrate how to do things like making mail into square and how to build a weatherized hole. These aren't things that anyone would need a tutorial for, but that's the idea of the project: a series of tutorials that exhibit not the process of doing something, but the strange behaviors of this deranged character as he tries his best to present an informational video for his fans. This work is definitely more speculative than it is spectacular.

It plays off the style of tutorial/DIY videos popular on YouTube in it's earlier days (before 2012 or so). There are a countless number of these no-budget tutorials online which make up their own genre of online video, all following the same vague structure of every other YouTube tutorial. Alantutorial rejects, while simultaneously parodying, the style of production value seen in these tutorials, where they're usually made by some kid in a garage with a 144p camcorder. He even parodies nuances of these videos like struggling to hold something down with one hand while having to hold the camera in the other.

This work stands closer to speculation because of what it presents at face value. At their surface, these videos are no different from any other tutorial on YouTube. He introduces his channel and what the tutorials about, he goes through the steps of some process, and finally presents the product of his efforts and signing off. By making the viewer question not only why they're watching the video, but why anyone would want to watch it, it begs the question of where it came from why it exists, which is not often asked of the videos we watch online.

The idea that you are watching someone demonstrate how to do something you have no interest in doing is what makes these videos seem to drag on and almost be a waste of time. They're only a few minutes each, but because they're essentially nonsense, the viewer is more skeptical of whether watching it is worth their time.

There are many details hidden in these videos that are not addressed directly, but add a layer of surrealism and nuanced cohesion through each video leaning slightly towards the realm of spectacle. You can tell that there was care put into setting all of these videos in the same universe with the same reoccurring imagery and callbacks. It makes for a confusing, unsettling, uninviting, visual spectacle.

The places where he films these videos is usually disgusting. Paint and dirt everywhere, things leaking, things bleeding, dangerous power tools, etc. Most of the time he's pouring stuff on the floor and making a mess, and at the same time there's a sense of neediness and not-having. For example, he makes a video about getting a dollar one day.  Watching him operate makes you almost empathize with and worry for him while he mindlessly destroys his things.

I would say these videos touch deeper into the art side of experience rather than the commerce side. When taken at face value these videos have very little substance, and most of the time don't even teach the things they claim to. They require a deeper analysis from the context of the YouTube tutorial genre as a whole, and what parts of that formula are being exploited and distorted.


I chose to make a clock that looked like nothing more than an ordinary video. The way it works is the bottle of water is drank over the course of an hour, meaning that the level of the water gives you an idea for how far into the hour it is (the height of the water resets to the bottom of the label). The hours are indicated by the street lights. Reading from the closest stop light as the most significant digit, you can read the hour in binary from the color of each consecutive light. Both of these functions can be manipulated by the user by typing 1-4 to change the color of each respective light, and 5 to take a sip.  The most challenging part of this project was figuring out a way to organize and execute longer animations from a sequence of images. The gif above shows how each layer can be isolated and animated independently . I like that this clock doesn't reveal itself easily. I tried to present it as a single shot, as if it were a live video recording of real events. And although these events seem to be happening over time, time never passes in this scene.

I made these car assets because I originally planned on including them as a component of the clock. I may spend more time in the future to get this working.

These gifs show how the empty road was constructed from pieces of a long video, over time.


1A) Something that exhibits effective complexity is shaving. With the stroke of a razor, a 2 dimensional area of skin is shaved, removing the hair that's growing there. The goal of shaving is to remove enough of these areas around your face so that there's no hair left. The shapes of these areas have to be arranged so that:

-Every point on your face lies in one of the areas

-You don't shave the same place too many times and give yourself razor burn (these areas will have many areas overlapping them)

Most people do this by shaving an area at the edge of the face, and then removing the hair around it until the face is empty of hair or they start working on a different section. These areas are arranged and ordered so that the edge of each stroke  slightly overlaps the edge of the previous stroke. Longer strokes make for more efficient shaving because it reduces the number of strokes and the area of overlapping shapes.

Shaving is pretty chaotic because it depends on the person's abilities and methods of packing shapes into a area. Everyone who shaves is generally going to remove the hair that they want to remove, the most variation lies in the razor strokes that remove that area of hair.

1B) The Problem of Meaning touches on some interesting ideas in terms of finding purpose and meaning in generative art. The idea behind generative art is to create functioning systems where each component interacts with another in a ordered, calculated way. The reasoning and logic behind the systems operations or products is what is interesting about the art. If these systems are based on systems that already exist, the art becomes the study of that system and the ability to simulate it in a different medium (like simulating the way clouds form in code).

These systems are designed by artists with a product in mind. Despite the fact that a generative work may be based off of an existing natural system, the artist has to understand that system in order to exploit or reproduce it. It's a study of how humans reason over dynamic processes.


My original goal in making this gif was to familiarize myself with loading animating picture files in p5.js. I started with a simple animation sequence that I processed in photoshop to isolate each element.


The hardest part was getting different cells to animate the frames at a different offset interval. The solution I used wasn't very elegant but in the future I think I'll set up some sort of data structure for frames that are being animated.

I used the PennerEaseInOutBack easing function to shift the entire frame of cells down smoothly. I think the smooth sweeping motion of the frame looks nice against the choppier, hand-drawn animation. The way it stretches slightly past the end point also makes the motion look like waves crashing. What I like about the gif is the way that the hand-drawn animations works with the perfect grid layout and smooth sweeping animation. The combination of those two qualities makes it satisfying for me to watch.

If I were to spend more time on it I would get more creative with the way that the animations are triggered. There are probably more interesting patterns and different ways activate the animation sequences of the folding papers.


// This is a template for creating a looping animation in p5.js (JavaScript). 
// This is a template for creating a looping animation in p5.js (JavaScript). 
// When you press the 'F' key, this program will export a series of images into
// your default Downloads folder. These can then be made into an animated gif. 
// This code is known to work with p5.js version 0.6.0
// Prof. Golan Levin, 28 January 2018
// 1. Run a local server, using instructions from here:
// 2. Set the bEnableExport variable to true.
// 3. Set the myNickname variable to your name.
// 4. Run the program from Chrome, press 'f'. 
//    Look in your 'Downloads' folder for the generated frames.
// 5. Note: Retina screens may export frames at twice the resolution.
// User-modifiable global variables. 
var myNickname = "nickname";
var nFramesInLoop = 120;
var bEnableExport = true;
// Other global variables you don't need to touch.
var nElapsedFrames;
var bRecording;
var theCanvas;
var frames = [];
var frameN = 0;
var unit;
var activeFrames = [];
var framesToDeact = [];
var levels = [[[4,4],[4,5],[5,4],[4,3],[3,4]],
var levels1 = [[[4,4],[4,5],[5,4],[5,5]],
function setup() {
  theCanvas = createCanvas(1920, 1920);
  bRecording = false;
  nElapsedFrames = 0;
  unit = width/9;
function keyTyped() {
  if (bEnableExport) {
    if ((key === 'f') || (key === 'F')) {
      bRecording = true;
      nElapsedFrames = 0;
      frameN = 0;
function draw() {
  // Compute a percentage (0...1) representing where we are in the loop.
  var percentCompleteFraction = 0;
  if (bRecording) {
    percentCompleteFraction = float(nElapsedFrames) / float(nFramesInLoop);
  } else {
    percentCompleteFraction = float(frameCount % nFramesInLoop) / float(nFramesInLoop);
  // Render the design, based on that percentage. 
  // This function renderMyDesign() is the one for you to change. 
  renderMyDesign (percentCompleteFraction);
  // If we're recording the output, save the frame to a file. 
  // Note that the output images may be 2x large if you have a Retina mac. 
  // You can compile these frames into an animated GIF using a tool like: 
  if (bRecording && bEnableExport) {
    var frameOutputFilename = myNickname + "_frame_" + nf(nElapsedFrames, 4) + ".png";
    print("Saving output image: " + frameOutputFilename);
    saveCanvas(theCanvas, frameOutputFilename, 'png');
    frameN ++;
    if (nElapsedFrames >= nFramesInLoop) {
      bRecording = false;
function renderMyDesign (percent) {
  if (percent >0.95) activeFrames = [];
  // This is an example of a function that renders a temporally looping design. 
  // It takes a "percent", between 0 and 1, indicating where we are in the loop. 
  // Use, modify, or delete whatever you prefer from this example. 
  // This example uses several different graphical techniques. 
  // Remember to SKETCH FIRST!
  // here, I set the background and some other graphical properties
  stroke(0, 0, 0);
  var inc = nElapsedFrames%6;
  var offset = height*function_PennerEaseInOutBack (percent);
  for (var row=0; row<9; row++) {
    for (var col=0; col<9; col++) {
  if (inc==0&&nElapsedFrames<30) {
    //start next tier of animation
  for (var i=0; i<activeFrames.length; i++){//animate the active frames;
    activeFrames[i][2] = (activeFrames[i][2]+1)%frames.length;
    //if (activeFrames[i][2]>frames.length) framesToDeact.push(activeFrames[i]);
// symmetric double-element sigmoid function (a is slope)
// See
// From:
function loadFrames() {
  var fileName;
  for (var i=0; i<12; i++) {
    fileName = join(["frames/sqr_",str(i+1),".png"],"");
  for (i=11; i>-1; i--) {
    fileName = join(["frames/sqr_",str(i+1),".png"],"");
function animateTier(x) {
  var tier = levels[x];
  var xyt;
  var start = 0;
  for (var i=0; i<tier.length; i++) {
    xyt = [tier[i][0], tier[i][1], 0];
function removeXYT(xyt, l) {
  for (var i=0; i<l.length; i++) {
    if (xyt[0]==l[i][0] && xyt[1]==l[i][1]) {
function drawActiveFrames(offset) {
  var af;
  for (var i=0; i<activeFrames.length; i++) {
    af = activeFrames[i];
    image(frames[af[2]%frames.length], unit*af[1], unit*af[0]+offset, unit, unit);
//The following function was taken from pattern_master - 
function function_PennerEaseInOutBack (x) {
  var s = 1.70158 * 1.525;
  x /= 0.5;
  var y = 0; 
  if (x < 1) {
    y = 1.0/2.0* (x*x*((s+1.0)*x - s));
  else {
    x -= 2.0;
    y = 1.0/2.0* (x*x*((s+1.0)*x + s) + 2.0);
  return y;

High-Res Gif (1920x1920):



  1. The artwork is in the shape of a square
  2. The artwork has a white background featuring many black lines.
  3. The center of each line seems to fall on the coordinates of a 56x56 unit grid
  4. The length of each line is equal to the lines spacing on the grid so that some of the lines intersect.
  5. Each line is set at a random angle. The angle of each line seems independent from the angles of the lines around it.
  6. Some spaces on the grid that you would expect to see a line are missing a line.
  7. The lines' angles seem to tend toward vertical.
  8. Theres an empty border around the lines.
  9. The randomness of the rotation of the lines seems independent from where lines are missing.
  10. The missing lines seem to be related to each other; there are "areas" on the grid where lines are missing or appear to be blown away.
  11. Even in places where there isn't a large area of lines missing, there are a few lines missing here and there.

The most challenging part about this piece was having to figure out the logic behind what seems like a chaotic image. While it looks very busy, the most defining features of this piece for me where the grid layout of the lines, the vertical-tending angled lines, and the large spaces where lines were missing. The large spaces of empty lines was the most difficult aspect to reproduce, followed by the angles of the lines. I chose to generate probability coefficients for each line using the noise() function. Because the noise() function used the row/column of each line, there were specific areas where lines were much  less likely to occur. T0 randomize the angle of the lines I first generated a random x-coordinate within the line's cell and made the end fall on that coordinate. This way there would be a higher probability of the line tending vertical. I enjoyed recreating this piece because it made me think about how to distinguish patterns and key characteristics of a seemingly random system. Having to break down the each element into basic properties to recreate was a fun exercise .




// Starter Code for "Embedded Iteration + Randomness"
var boolDoRefresh;
var lines = [];
var intersections = [];
var lineLength = 300;
var circWidth = 30;
var numLines = 12;
var numIntersections = 0;
function setup() {
  createCanvas(720, 480);
  boolDoRefresh = true;
function draw() {
  if (boolDoRefresh) {
    lines = [];
    intersections = [];
    numIntersections = 0;
    for (var i = 0; i < numLines; i++) {
      lines.push(new Line());
      for (var j = 0; j < i; j++) {
        intersects(lines[i], lines[j]);
    for (i = 0; i < numLines; i++) {
    for (i = 0; i < numIntersections; i++) {
    boolDoRefresh = false;
function mousePressed() {
  boolDoRefresh = true;
function Line() {
  this.x1 = int(random(width));
  this.y1 = int(random(height));
  this.angle = int(random(360));
  this.radians = 0;
  this.display = function() {
    line(this.x1, this.y1, this.x2, this.y2);
  this.updateRad = function() {
    this.radians = radians(this.angle);
  this.angle = modAngle(this.angle);
  this.x2 = this.x1 + lineLength * cos(this.radians);
  this.y2 = this.y1 + lineLength * sin(this.radians);
function Intersection(x, y) {
  this.x = x;
  this.y = y;
  this.display = function() {
    ellipse(this.x, this.y, circWidth, circWidth);
function linePointAngle(line1, px, py) {
  var lx = line1.x1;
  var ly = line1.y1;
  //this first angle is between universal and two points
  var angle = degrees(atan((py-ly)/(px-lx)));
  if (px<lx) angle+=180;
  //angle -= line1.angle;
  angle = modAngle(angle);
  //then find the difference of the line angle and this
  //angle to get the relative angle of the point to the line
  return angle;
function modAngle(angle) {
  while(angle<0) angle += 360;
  while(angle>=360) angle -=360;
  return angle;
function splits(line1, line2) {
  var angle1 = linePointAngle(line1, line2.x1, line2.y1);
  var angle2 = linePointAngle(line1, line2.x2, line2.y2);
  if (angle1>angle2) {
		var temp = angle1;
    angle1 = angle2;
    angle2 = temp; //ang1<=ang2
  if (angle2-angle1>=180) {
    return(line1.angle<=angle1 || line1.angle>=angle2);
  return(line1.angle<=angle2 && line1.angle>=angle1);
function intersects(line1, line2) {
  var res = splits(line1,line2) && splits(line2,line1);
  if (res) intersection(line1, line2);
  return res;
function intersection(line1, line2) {
  var x1 = line1.x1;
  var x2 = line2.x1;
  var y1 = line1.y1;
  var y2 = line2.y1;
  var m1 = (line1.y2-y1)/(line1.x2-x1);
  var m2 = (line2.y2-y2)/(line2.x2-x2);
  var X = ((x1*m1)-y1-(x2*m2)+y2)/(m1-m2);
  var Y = m1*(X-x1)+y1;
  var res = new Intersection(X, Y);
  numIntersections += 1;


// Starter Code for "Embedded Iteration + Randomness"
var boolDoRefresh;
var rand;
var margin;
var side;
function setup() {
  createCanvas(400, 400);
  boolDoRefresh = true;
  margin = 10;
  side = (width-margin*9)/8
function draw() {
  if (boolDoRefresh) {
    for (var row = 0; row&lt;8; row++) {
			for (var col = 0; col&lt;8; col++) {
        drawElem(row, col);
    boolDoRefresh = false;
function mousePressed() {
  boolDoRefresh = true;
function drawElem(row, col) {
  var left = col*(side+margin)+margin;
  var top = row*(side+margin) + margin;
  rand = int(random(20));
  if (rand == 0) {
  	left += int(side/2);
    top += int(side/2);
    ellipse(left, top, side/2, side/2);
  else rect(left, top, side, side);



"9. The Critical Engineer notes that written code expands into social and psychological realms, regulating behaviour between people and the machines they interact with. By understanding this, the Critical Engineer seeks to reconstruct user-constraints and social action through means of digital excavation."

This tenet observes that the code we write and the way it's expressed to users exist only in a theoretical space, but the experiences and ideas they create for their users have a very concrete impact on physical reality and our mind's perception of it. These are technologies that express how a person constructs an understanding of their reality. In this way, the technologies themselves have a significant impact on the way we understand reality and the decisions we make based on that understanding.

We design technologies that operate within our physical reality, consisting of 3 spacial dimensions along a single-dimensional timeline that we experience linearly. The mechanisms in our brains however, provide an understanding of reality where information is transmitted through space independent of mass or energy. In my personal reality I can make someone laugh, start a club, gain respect, or transcend the laws of physics by only touching a piece of glass with my body, all without having to exist at any specific point in physical space.


ARCADE SCAM SCIENCE (not clickbait) - Mark Rober

Mark Rober is a YouTube creator who uses a range of scientific and creative methods to solve curious problems. This project is a robot designed to cheat a specific arcade game where you have to press a button at just the right time. What I love about this project is that it's a perfect example of how the curious mind can discover the hidden order of chaotic events. When he doesn't get the result he expects, Mark tests each system of his device independently to narrow down where the problem is arising . From here he discovers how the arcade game he's testing is actually programmed to only allow a certain percent of plays to result in a win.

Mark Rober designed the concept and built the prototype with a friend (only referred to in the video as "John") over the course of a few weeks in his home studio.The device was made with 3D-printed parts and includes an Arduino programmed to depress a plunger when a flashing light is detected. This connects via WiFi to an app developed to give the user fine control of the delay between when a light flashes and when the plunger is activated.

Mark's whimsical and flashy style of projects can be seen in many YouTube creators' works. Channels like kipkay, Household Hacker, and G3AR are a few examples of makers who use engineering and critical thinking to produce the gadgets and technology they imagine. Videos like these are a fantastic way to introduce audiences to the creative and scientific process because they present it in a way that's fun and easy to relate to, not one that's confusing and alienating.

I would like to see an entire portfolio of different mechanisms to cheat arcade games. With all of the different mechanisms and goals/incentives of arcade games, it would be interesting to see a range of machines designed to give players the advantage over their master.