twrabetz@andrew.cmu.edu – [OLD FALL 2017] 15-104 • Introduction to Computing for Creative Practice https://courses.ideate.cmu.edu/15-104/f2017 Professor Roger B. Dannenberg • Fall 2017 • Introduction to Computing for Creative Practice Sat, 12 Sep 2020 00:19:01 +0000 en-US hourly 1 https://wordpress.org/?v=4.8.24 Final Project Thomas Wrabetz / Anna Boyle https://courses.ideate.cmu.edu/15-104/f2017/2017/12/08/final-project-thomas-wrabetz-anna-boyle/ https://courses.ideate.cmu.edu/15-104/f2017/2017/12/08/final-project-thomas-wrabetz-anna-boyle/#respond Fri, 08 Dec 2017 22:01:16 +0000 https://courses.ideate.cmu.edu/15-104/f2017/?p=24187 Continue reading "Final Project Thomas Wrabetz / Anna Boyle"]]>

sketch

//Anna Boyle and Thomas Wrabetz
//Main functions

//Thomas' code
function setup() {
    createCanvas(480, 480);
    rectMode( CENTER );
    player = makePlayer( width / 2, height / 2 );
    level = makeLevel();
    var sec=second();
}

function draw() {
    background(200);
    player.draw();
    player.step();
    level.draw();

//Anna's code
    fill(0);
    txt=width/2
    fill(255);
    noStroke();
    if (drawBubble==1){
//triangle for speech bubble
    triangle(width/2-20, txtH+20, bubbleX, bubbleY, width/2+20, txtH+20)
//if the player is on the top half, make the bubble on the bottom half
    if (player.y<height/2){
      txtH=440;
      rect(width/2, 470, width, bubbleHeight);
//adjust the line height when there is only one line
      singleLineHeight=465;
//if the player is on the bottom half, make the bubble on the top half
    }if (player.y>=height/2){
      txtH=30;
      rect(width/2, 20, width, bubbleHeight);
//adjust the line height when there is only one line
      singleLineHeight=30;
  }
    fill(0);
//makes the quote
    textSize(17);
    textAlign(CENTER);
    printQuote( whichQuote );
  }
    rectMode(CORNER);
//draws the inspiration meter red bar
    fill(188, 64, 64);
    rect(width-20, 0, 20, height);
//draws the inspiration meter's variable green bar
    fill(64, 188, 64);
    rect(width-20, height-inspiroMeter, 20, height);
    rectMode(CENTER);
//if the player gets enough quotes, they will win and see this screen
    if (inspiroMeter>480){
      fill(255);
      rect(width/2, height/2, width, height)
      fill(0);
      textSize(32)
      text("CONGRATULATIONS!", width/2, height/2-25);
      text("YOU ARE INSPIRED", width/2, height/2+25);
      noLoop();
    }
}

//Thomas Wrabetz
//Section C
//twrabetz@andrew.cmu.edu
//Player object

//-----PLAYER OBJECT-----//

var PSIZE = 30;
var PCOLOR = [ 25, 150, 25, 255 ];
var PSPEED = 3;
var keyArray = [];

//Updates the player's position based on keyboard input
function stepPlayer()
{
    //Variables to track the player's movement in each direction
    var yStep = 0;
    var xStep = 0;
    if( keyIsPressed )
    {
        for( var i = 0; i < keyArray.length; i++ )
        {
            switch( keyArray[i] )
            {
                case 'W':
                    yStep -= PSPEED;
                    break;
                case 'S':
                    yStep += PSPEED;
                    break;
                case 'A':
                    xStep -= PSPEED;
                    break;
                case 'D':
                    xStep += PSPEED;
                    break;
            }
        }
        //Adjust speed for diagonal movement
        if( xStep != 0 & yStep != 0 )
        {
            xStep *= 0.7071
            yStep *= 0.7071
        }
        //Check if the player will collide with a wall in the x-direction
        //and move the player if not
        if( !level.collisionSearch( this.x + xStep, this.y, PSIZE ) )
        {
            //If the player is too close to the edges of the screen,
            //move the level instead of the player
            if( ( this.x < width * 4/5 || xStep < 0 ) 
                && ( this.x > width * 1/5 || xStep > 0 ) ) this.x += xStep;
            else level.xOffset -= xStep;
        }
        //Check if the player will collide with a wall in the y-direction
        //and move the player if not
        if( !level.collisionSearch( this.x, this.y + yStep, PSIZE ) )
        {
            //If the player is too close to the edges of the screen,
            //move the level instead of the player
            if( ( this.y < height * 4/5 || yStep < 0 ) 
                & ( this.y > height * 1/5 || yStep > 0 ) ) this.y += yStep;
            else level.yOffset -= yStep;
        }
        //If the player collides with a figure, update the bubble
        var figure = level.figureCollisionSearch( this.x + xStep, 
                                                  this.y + yStep, PSIZE );
        if( figure != -1 )
        {
            if( !drawBubble )
            {
                drawBubble = true;
                //Only update to a new quote if this is a different figure
                if( bubbleID != level.figures[ figure ].ID )
                {
                    bubbleID = level.figures[ figure ].ID;
                    updateBubble();
                }
            }
            bubbleX = level.figures[ figure ].x + level.xOffset;
            bubbleY = level.figures[ figure ].y + level.yOffset;
        }
        else if( drawBubble )
            drawBubble = false;
        level.step();
    }
}

//Draw the player
function drawPlayer()
{
    fill( PCOLOR );
    rect( this.x, this.y, PSIZE, PSIZE );
}

function makePlayer( px, py )
{
    player = { x: px, y: py, draw: drawPlayer, step: stepPlayer };
    return player;
}

//-----KEY TRACKING-----//

//Each key pressed is stored in the key array
function keyPressed()
{
    keyArray.push( key );
}

//Keys are removed from the key array when released
function keyReleased()
{
    for( var i = 0; i < keyArray.length; i++ )
    {
        if( keyArray[i] == key ) keyArray.splice( i, 1 );
    }
}

//Thomas Wrabetz
//Section C
//twrabetz@andrew.cmu.edu
//Walls and level and figures

//-----INSPIRATIONAL FIGURE OBJECT-----//

figureColorArray = [ "Red", "Blue", "Green", "Yellow",
                     "Purple", "Orange", "Brown" ];
//Counter to give the figures unique IDs
figureIDCounter = 0;
//Counter that keeps track of how many open spaces have been created
figureCounter = 0;
//Each time figureCounter reaches FIGUREFREQ, a new figure is created
FIGUREFREQ = 10;
//Size of a figure
FIGUREWIDTH = 30;

function makeFigure( xPos, yPos )
{
    figure = { x: xPos, y: yPos, figureColor: random(figureColorArray),
               ID: figureIDCounter };
    figureIDCounter++;
    return figure;
}


//-----WALL OBJECT-----//

//Size of a wall
var WALLWIDTH = 80;
var WALLCOLOR = [ 116, 18, 229, 255 ];
var WALLCOLORDARK = [ 39, 7, 76, 255 ];

function makeWall( wx, wy )
{
    var wall = { x: wx, y: wy, pattern: makePattern() };
    return wall;
}

//-----LEVEL OBJECT-----//

//Add a row to the level. The parameters indicate which side
function levelAddRow( xRef, yRef )
{
    //Variables to track whether the new row is an empty row
    //and whether it has intersected an existing corridor
    var before = false;
    var after = false;
    var passed = false;
    var justPassed = false;
    //Left Side
    if( xRef == 1 ) 
    {
        //Clear out old row on opposite side
        this.walls.unshift( [] );
        this.walls.splice( this.walls.length - 1, 1 );
        //Decide whether the new row is empty or a turning corridor
        if( random() < 0.17 ) before = true;
        else if( random() < 0.204 ) after = true;
        else if( random() < 0.2572 )
        {
            before = true;
            after = true;
        }
        //There can't be two empty rows next to each other
        for( var i = 0; i < this.walls[1].length-2; i++ )
        {
            if( this.walls[1][i] == 0 & this.walls[1][i+1] == 0 )
            {
                before = false;
                after = false;
            }
        }
        //Generate the row
        for( var i = 0; i < this.walls[1].length; i++ )
        {
            //Check if the row intersects a corridor
            if( this.walls[1][i] == 0 )
            {
                passed = true;
                justPassed = true;
            }
            //Generate a wall unless this row is empty or blocking a corridor
            if( ( this.walls[1][i] == 0 & i != 0 && this.walls[1][i-1] != 0 &&
                  i != this.walls[1].length - 1 && this.walls[1][i+1] != 0 ) ||
                ( before && ( !passed || justPassed ) ) || ( after && passed ))
            {
                this.walls[0][i] = 0;
                if( figureCounter == FIGUREFREQ - 1 ) 
                    this.figures.push( makeFigure( -1 * WALLWIDTH,
                                       (i - 1) * WALLWIDTH ) );
                figureCounter = (figureCounter + 1) % FIGUREFREQ;
            }
            else this.walls[0][i] = makeWall( -1 * WALLWIDTH, 
                                              (i - 1) * WALLWIDTH );
            justPassed = false;
        }
    }
    //Right Side
    if( xRef == -1 ) 
    {
        //Clear out old row on opposite side
        this.walls.push( [] );
        this.walls.shift( 1 );
        //Decide whether the new row is empty or a turning corridor
        if( random() < 0.17 ) before = true;
        else if( random() < 0.204 ) after = true;
        else if( random() < 0.2572 )
        {
            before = true;
            after = true;
        }
        //There can't be two empty rows next to each other
        for( var i = 0; i < this.walls[1].length-2; i++ )
        {
            if( this.walls[this.walls.length-2][i] == 0 
                & this.walls[this.walls.length-2][i+1] == 0 )
            {
                before = false;
                after = false;
            }
        }
        //Generate the row
        for( var i = 0; i < this.walls[this.walls.length-2].length; i++ )
        {
            //Check if the row intersects a corridor
            if( this.walls[this.walls.length-2][i] == 0 )
            {
                passed = true;
                justPassed = true;
            }
            //Generate a wall unless this row is empty or blocking a corridor
            if( ( this.walls[this.walls.length-2][i] == 0 & i != 0 &&
                this.walls[this.walls.length-2][i-1] != 0 && 
                i != this.walls[this.walls.length-2].length - 1 &&
                this.walls[this.walls.length-2][i+1] != 0 ) ||
                ( before && (!passed || justPassed) ) || ( after && passed ) )
            {
                this.walls[this.walls.length-1][i] = 0;
                if( figureCounter == FIGUREFREQ - 1 ) 
                    this.figures.push( makeFigure( (this.walls.length-2) 
                                                   * WALLWIDTH, 
                                                   (i-1) * WALLWIDTH ) );
                figureCounter = (figureCounter + 1) % FIGUREFREQ;
            }
            else this.walls[this.walls.length-1][i] = 
                 makeWall( (this.walls.length-2) 
                           * WALLWIDTH, (i-1) * WALLWIDTH );
            justPassed = false;
        }
    }
    //Top
    if( yRef == 1 )
    {
        //Clear out old row on opposite side
        for( i = 0; i < this.walls.length; i++ )
        {
            this.walls[i].unshift( -1 );
            this.walls[i].splice( this.walls[i].length - 1, 1 );
        }
        //Decide whether the new row is empty or a turning corridor
        if( random() < 0.17 ) before = true;
        else if( random() < 0.204 ) after = true;
        else if( random() < 0.2572 )
        {
            before = true;
            after = true;
        }
        //There can't be two empty rows next to each other
        for( var i = 0; i < this.walls.length-2; i++ )
        {
            if( this.walls[i][1] == 0 & this.walls[i+1][1] == 0 )
            {
                before = false;
                after = false;
            }
        }
        //Generate the row
        for( var i = 0; i < this.walls.length; i++ )
        {
            //Check if the row intersects a corridor
            if( this.walls[i][1] == 0 )
            {
                passed = true;
                justPassed = true;
            }
            //Generate a wall unless this row is empty or blocking a corridor
            if( ( this.walls[i][1] == 0 & i != 0 && this.walls[i-1][1] != 0 
                  && i != this.walls.length - 1 
                  && this.walls[i+1][1] != 0 ) 
                  || (before && (!passed || justPassed)) || (after && passed))
            {
                this.walls[i][0] = 0;
                if( figureCounter == FIGUREFREQ - 1 ) 
                    this.figures.push( makeFigure( (i-1) * WALLWIDTH,
                                       -1 * WALLWIDTH ) );
                figureCounter = (figureCounter + 1) % FIGUREFREQ;
            }
            else 
                this.walls[i][0] = makeWall((i-1) * WALLWIDTH, -1 * WALLWIDTH);
            justPassed = false;
        }
    }
    //Bottom
    if( yRef == -1 )
    {
        //Clear out old row on opposite side
        for( i = 0; i < this.walls.length; i++ )
        {
            this.walls[i].push( -1 );
            this.walls[i].shift( 1 );
        }
        //Decide whether the new row is empty or a turning corridor
        if( random() < 0.17 ) before = true;
        else if( random() < 0.204 ) after = true;
        else if( random() < 0.2572 )
        {
            before = true;
            after = true;
        }
        //There can't be two empty rows next to each other
        for( var i = 0; i < this.walls.length-2; i++ )
        {
            if( this.walls[i][this.walls.length-2] == 0 
                & this.walls[i+1][this.walls.length-2] == 0 )
            {
                before = false;
                after = false;
            }
        }
        //Generate the row
        for( var i = 0; i < this.walls.length; i++ )
        {
            //Check if the row intersects a corridor
            if( this.walls[i][this.walls[0].length-2] == 0 )
            {
                passed = true;
                justPassed = true;
            }
            //Generate a wall unless this row is empty or blocking a corridor
            if( ( this.walls[i][this.walls[0].length-2] == 0 & i != 0 
                  && this.walls[i-1][this.walls[0].length-2] != 0 
                  && i != this.walls.length - 1 
                  && this.walls[i+1][this.walls[0].length-2] != 0 ) 
                  || (before && (!passed || justPassed)) || (after && passed)) 
            {
                this.walls[i][this.walls[0].length-1] = 0;
                if( figureCounter == FIGUREFREQ - 1 ) 
                    this.figures.push( makeFigure( (i-1) * WALLWIDTH,
                                      (this.walls[0].length-2) * WALLWIDTH ) );
                figureCounter = (figureCounter + 1) % FIGUREFREQ;
            }
            else 
                this.walls[i][this.walls[0].length-1] = 
                makeWall( (i-1) * WALLWIDTH,
                          (this.walls[0].length-2) * WALLWIDTH );
            justPassed = false;
        }
    }
}

//Update the level, moving objects inside and adding new rows if needed
function levelStep()
{
    //If the offset for the walls is greater than the width of a wall,
    //Shift the array of walls and add a new row
    if( abs( this.xOffset ) >= WALLWIDTH )
    {
        //Incorporate offset into walls' basic x-positions
        for( var j = 0; j < this.walls.length; j++ )
        {
            for( var k = 0; k < this.walls[j].length; k++ )
            {
                if( this.xOffset > 0 )
                {
                    this.walls[j][k].x += WALLWIDTH;
                }
                if( this.xOffset < 0 )
                {
                    this.walls[j][k].x -= WALLWIDTH;
                }
            }
        }
        //Incorporate offset into figures' basic x-positions
        for( var j = 0; j < this.figures.length; j++ )
        {
            if( this.xOffset > 0 )
            {
                this.figures[j].x += WALLWIDTH;
            }
            if( this.xOffset < 0 )
            {
                this.figures[j].x -= WALLWIDTH;
            }
            //Remove figures that are off the screen
            if( this.figures[j].x > width + FIGUREWIDTH / 2 
                || this.figures[j].x < 0 - FIGUREWIDTH / 2 )
            {
                this.figures.splice( j, 1 );
                j--;
            }
        }
        //Reset the offset and add a new row
        if( this.xOffset > 0 )
        {
            this.xOffset -= WALLWIDTH;
            this.addRow( 1, 0 );
        }
        if( this.xOffset < 0 )
        {
            this.xOffset += WALLWIDTH;
            this.addRow( -1, 0 );
        }
    }
    if( abs( this.yOffset ) >= WALLWIDTH )
    {
        //Incorporate offset into walls' basic y-positions
        for( var j = 0; j < this.walls.length; j++ )
        {
            for( var k = 0; k < this.walls[j].length; k++ )
            {
                if( this.yOffset > 0 )
                {
                    this.walls[j][k].y += WALLWIDTH;
                }
                if( this.yOffset < 0 )
                {
                    this.walls[j][k].y -= WALLWIDTH;
                }
            }
        }
        //Incorporate offset into figures' basic y-positions
        for( var j = 0; j < this.figures.length; j++ )
        {
            if( this.yOffset > 0 )
            {
                this.figures[j].y += WALLWIDTH;
            }
            if( this.yOffset < 0 )
            {
                this.figures[j].y -= WALLWIDTH;
            }
            //Remove figures that are off the screen
            if( this.figures[j].y > height + FIGUREWIDTH / 2 
                || this.figures[j].y < 0 - FIGUREWIDTH / 2 )
            {
                this.figures.splice( j, 1 );
                j--;
            }
        }
        //Reset the offset and add a new row
        if( this.yOffset > 0 )
        {
            this.yOffset -= WALLWIDTH;
            this.addRow( 0, 1 );
        }
        if( this.yOffset < 0 )
        {
            this.yOffset += WALLWIDTH;
            this.addRow( 0, -1 );
        }
    }
}

//Checks if a square at x,y with size size would collide with the wall
//at index a,b of the array of walls
function levelWallCollision( x, y, size, a, b )
{
    var wall = this.walls[a][b];
    if( wall == 0 ) return false;
    return abs( x - ( wall.x + this.xOffset ) ) < size / 2 + WALLWIDTH / 2 
           & abs( y - ( wall.y + this.yOffset ) ) < size / 2 + WALLWIDTH / 2;
}

//Check collision for all the walls
function levelCollisionSearch( x, y, size )
{
    for( i = 0; i < this.walls.length; i++ )
    {
        for( j = 0; j < this.walls[i].length; j++ )
        {
            if( this.wallCollision( x, y, size, i, j ) ) return true;
        }
    }
    return false;
}

//Draw the wall at index a,b of the wall array
function levelDrawWall( a, b )
{
    var wall = this.walls[a][b];
    if( wall == 0 ) return;
    push();
    stroke( WALLCOLORDARK );
    fill( WALLCOLOR );
    rect( wall.x + this.xOffset, wall.y + this.yOffset, WALLWIDTH, WALLWIDTH );
    wall.pattern.draw( wall.x + this.xOffset, wall.y + this.yOffset );
    pop();
}

//Checks if a square at x,y with size size would collide with a figure
//at index a of the figure array
function levelFigureCollision( x, y, size, a )
{
    if( a >= this.figures.length ) return false;
    var figure = this.figures[a];
    return abs( x - ( figure.x + this.xOffset ) ) < size / 2 + FIGUREWIDTH / 2
                & abs( y - ( figure.y + this.yOffset ) ) 
                   < size / 2 + FIGUREWIDTH / 2;
}

//Check collision for all the figures. If found, returns the index of
//the colliding figure in the figure array. If not, returns -1.
function levelFigureCollisionSearch( x, y, size )
{
    for( i = 0; i < this.figures.length; i++ )
    {
        if( this.figureCollision( x, y, size, i ) ) return i;
    }
    return -1;
}

//Draw the figure at index a of the figure array
function levelDrawFigure( a )
{
    var figure = this.figures[a];
    if( figure == 0 ) return;
    push();
    stroke( 0 );
    fill( figure.figureColor );
    ellipse( figure.x + this.xOffset, figure.y + this.yOffset,
             FIGUREWIDTH, FIGUREWIDTH );
    pop();
}

//Draw all the walls and figures
function levelDraw()
{
    for( i = 0; i < this.walls.length; i++ )
    {
        for( j = 0; j < this.walls[i].length; j++ )
        {
            this.drawWall( i, j );
        }
    }
    for( i = 0; i < this.figures.length; i++ )
    {
        this.drawFigure( i );
    }
}

//Make a level, which contains arrays of walls and figures as well as a shared
//x and y offet which applies to every object in the level
function makeLevel()
{
    var wallsArray = [];
    var figuresArray = [];
    for( i = 0; (i - 1) * WALLWIDTH <= width + WALLWIDTH; i++ )
    {
        wallsArray.push( [] );
        for( j = 0; (j - 1) * WALLWIDTH <= height + WALLWIDTH; j++ )
        {
            if( i == 4 || j == 4 ) wallsArray[i].push( 0 );
            else 
                wallsArray[i].push( makeWall( (i - 1) * WALLWIDTH,
                                    (j - 1) * WALLWIDTH ) );
        }
    }
    level = { walls: wallsArray, figures: figuresArray, xOffset: 0, yOffset: 0,
              draw: levelDraw, drawWall: levelDrawWall,
              wallCollision: levelWallCollision,
              collisionSearch: levelCollisionSearch,
              step: levelStep, addRow: levelAddRow,
              drawFigure: levelDrawFigure, 
              figureCollision: levelFigureCollision,
              figureCollisionSearch: levelFigureCollisionSearch };
    return level;
}

//Thomas Wrabetz
//Section C
//twrabetz@andrew.cmu.edu
//Pattern object for wall blocks

var DOTSIZE = 3;
var colors = [ [66,134,234,255], [23,216,213,255],
               [23,216,236,255], [68,216,23,255], [228,242,42,255] ];

function makePattern() {
    var angle;
    var newPattern={c: random(colors), arms: int( random( 4 ) ) + 2, 
                    a: random(2*PI), draw: drawPattern, dotPositionArray: [] };
    for( var i = 0; i < newPattern.arms; i++ )
    {
        for( var j = 0; j < WALLWIDTH / 2 - 5; j+= DOTSIZE * 2 )
        {
            angle = newPattern.a + i * (2 * PI / newPattern.arms);
            newPattern.dotPositionArray.push( j * cos( angle ) + 
                     ( sin( j ) * 20 * cos( angle + PI / 2 ) ) );
            newPattern.dotPositionArray.push( j * sin( angle ) + 
                     ( sin( j ) * 20 * sin( angle + PI / 2 ) ) );
        }
    }
    return newPattern;
}

function drawPattern( x, y ){
    fill(this.c)
    push();
    noStroke();
    var currentX;
    var currentY;
    for( var i = 0; i < this.dotPositionArray.length - 1; i+= 2 )
    {
            ellipse( x + this.dotPositionArray[i], y + this.dotPositionArray[i+1],
                     DOTSIZE, DOTSIZE );
    }
    pop();
}

//Anna Boyle
//Section D
//aboyle@andrew.cmu.edu
//Quote generator

var abstractNouns = ["Rebellion", "Curiosity", "Jealousy", "Friendship",
"Family", "Evil", "Life", "Hope", "Grace", "Love", "Faith", "Opportunity",
"Dedication", "Insanity", "Fortune", "Luck", "Hatred", "Knowledge", "Pain",
 "Heaven"];
var inspireNouns = ["rainbow", "cloud", "light", "star", "candle", "child",
"dream", "building", "hero", "breeze", "eye", "moon", "snowflake", "apple",
"tree", "flower", "butterfly", "mirror", "door", "heart"];
var inspireNounsPlural = ["rainbows", "clouds", "lights", "stars", "candles",
"children", "kisses", "buildings", "hands", "brothers", "sisters", 
"snowflakes", "dreams", "apples", "trees", "flowers", "butterflies", "mirrors",
"doors", "hearts"];
var strangeNouns=["peach cobbler", "deodorant", "used tissue", "conch shell",
"toaster", "pasta strainer", "blade of grass", "grandma's house", "unicycle",
"weed whacker", "shampoo bottle", "corpse", "snickerdoodle",
"ten gallon hat", "toupee", "colony of termites", "mother-in-law",
"sexy firemen calendar", "underground bunker", "angry baboon"];
var strangeNounsPlural = ["alien invasions", "clowns", "podiatrists",
"belly dancers", "cacti", "voodoo dolls", "raspberries", "dust bunnies",
"distant relatives", "kentucky fried chicken", "rotten eggs", "nudists",
"nunchuks", "toenail clippings", "rocket scientists", "green beans", "nuns",
"croissants", "drunk ballerinas", "shoelaces" ];
var inspireVerbs= ["flies", "moves", "shines", "waits", "stands", "goes",
"sleeps", "thinks", "cries", "laughs", "yells", "watches", "jumps"];
var inspireVerbsObj = ["hold", "hug", "love", "hate", "grab", "accept",
"support", "look at", "want", "sacrifice", "kiss", "pray for", "abandon"];
var inspireVerbsGerund= ["flying", "moving", "doing", "waiting", "standing",
"going", "saying", "thinking", "crying", "laughing", "yelling", "watching",
"jumping"];
var inspireVerbsObjGerund = ["holding", "hugging", "loving", "hating",
"grabbing", "accepting", "supporting", "seeing", "wanting", "finding",
"kissing", "praying for", "abandoning"];
var strangeVerbs=["dances", "dies", "melts", "yodels", "sneezes", "does yoga",
"crawls", "beatboxes", "undresses", "vomits", "whistles", "rollerblades",
"explodes"];
var strangeVerbsObj=["stab", "fight", "smack", "bury", "kick", "exorcise",
"kidnap", "high five", "sniff", "smuggle", "tickle", "cuddle", "nibble"];
var strangeVerbsGerund=["dancing", "dying", "melting", "yodeling", "sneezing",
"doing yoga","crawling", "sleeping", "undressing", "vomiting", "whistling",
"rollerblading", "exploding"];
var strangeVerbsObjGerund=["stabbing", "fighting", "smacking", "burying",
"kicking", "exorcising", "kidnapping", "high fiving", "sniffing", "smuggling",
"tickling", "cuddling", "nibbling"];
var locationWords=["behind", "in front of", "next to", "inside of", "below",
"on top of", "above", "under", "among", "beside", "over", "far away from",
"underneath"];
var comparison=["darker", "sadder", "bigger", "smaller", "harder", "softer",
"better", "worse", "faster", "slower", "stronger", "weaker", "happier", 
"drunker", "older", "younger", "smarter", "dumber", "hotter", "colder"];
var personQuote=["Albert Einstein", "Mahatma Gandhi", "Oprah Winfrey",
"George Washington", "Nelson Mandela", "Jesus Christ", "Benjamin Franklin",
"Plato", "Mother Teresa", "My mom", "Beyonce", "Martin Luther King Jr.",
"Santa Claus"]

//variable for the quote templates
var whichQuote;

/*nCh=nineteen choices, tCh=twelve choices
There are multiple variables to prevent parts of speech with same amount of
choices don't get constantly paired with each other */

var nCh1;
var nCh2;
var nCh3;
var nCh4;
var tCh1;
var tCh2;
var tCh3;
var tCh4;

//Variables related to drawing the speech bubble
var txt;
var txtH;
var bubbleHeight;
var singleLineHeight;
var bubbleX = 0;
var bubbleY = 0;
var drawBubble = false;
var bubbleID = -1;
var inspiroMeter=0;

function updateBubble(){
//randomizes which number in the array will be chosen for the parts of speech
    nCh1=int(random(20));
    nCh2=int(random(20));
    nCh3=int(random(20));
    nCh4=int(random(20));
    tCh1=int(random(13));
    tCh2=int(random(13));
    tCh3=int(random(13));
    tCh4=int(random(13));
//randomzies which quote template will be chosen
    whichQuote=int(random(14));
    inspiroMeter=inspiroMeter+20;

}

//Chooses which quote template will be chosen based on the random number
//between 0 and 13

function printQuote( num )
{

    switch(num)
  {
      case 0:
      worthTwo();
      break;
    case 1:
      tryToBe();
      break;
    case 2:
      whenYouHave();
      break;
    case 3:
      judgeEach();
      break;
    case 4:
      ifYouMiss();
      break;
    case 5:
      theBest();
      break;
    case 6:
      duringOurMoments();
      break;
    case 7:
      letUs();
      break;
    case 8:
      palesInComparison();
      break;
    case 9:
      haveSeen();
      break;
    case 10:
      inSeason();
      break;
    case 11:
      combination();
      break;
    case 12:
      onlyICan();
      break;
    case 13:
      jokeQuote();
     break;
  }
}

//Below are all the quote template functions
//bubbleHeight changes the size of bubble when there are different amounts of text

function tryToBe(){
    text("Try to be a "+inspireNouns[nCh1]+" in someone's "
    +strangeNouns[nCh2], txt, singleLineHeight);
    bubbleHeight=75;
}

function worthTwo(){
    text("One "+inspireNouns[nCh1]+" is worth two "+
    strangeNounsPlural[nCh2], txt, singleLineHeight);
    bubbleHeight=75;
}

function whenYouHave(){
    text("When you have a "+strangeNouns[nCh1]+", you've got to ", txt, txtH);
    text(inspireVerbsObj[tCh1]+" it and never "+strangeVerbsObj[tCh2]+
    " it", txt, txtH+25);
    bubbleHeight=130;
}

function judgeEach(){
    text("Don't judge each day by the "+inspireNounsPlural[nCh1],
    txt, txtH);
    text(" you "+inspireVerbsObj[tCh1]+", but by the "+strangeNounsPlural[nCh1]
    +" you "+strangeVerbsObj[tCh1], txt, txtH+25);
    bubbleHeight=130;
}

function ifYouMiss(){
    text("Shoot for the "+inspireNouns[nCh1]+", and if you miss", txt, txtH);
    text(" you will still be "+locationWords[tCh1]+" the "
    +strangeNounsPlural[nCh2], txt, txtH+25);
    bubbleHeight=130;
}

function theBest(){
    text("The best preparation for tomorrow is", txt, txtH);
    text(strangeVerbsObjGerund[tCh1]+" your "+
    strangeNouns[nCh1]+" today", txt, txtH+25);
    bubbleHeight=130;
}

function duringOurMoments(){
    text("It is during our "+comparison[nCh1]+" moments that we must", txt, txtH);
    text("focus to "+strangeVerbsObj[tCh1]+" the "+
    strangeNounsPlural[nCh2], txt, txtH+25);
    bubbleHeight=130;
}

function letUs(){
    text("Let us sacrifice our "+inspireNounsPlural[nCh1]
    +" so that", txt, txtH);
    text("our children can "+strangeVerbsObj[tCh1]+" a "+
    comparison[nCh2]+" "+strangeNouns[nCh3], txt, txtH+25);
    bubbleHeight=130;
}

function palesInComparison(){
    text("What "+inspireVerbs[tCh1]+" behind you and what "+
    inspireVerbs[tCh2]+" in front of you,", txt, txtH);
    text("pales in comparison to what "+strangeVerbs[tCh3]+" "+
    locationWords[tCh4]+" you", txt, txtH+25)
    bubbleHeight=130;
}

function haveSeen(){
    text("If I have seen further than others, it is", txt, txtH);
    text("by "+strangeVerbsGerund[tCh1]+" "+locationWords[tCh2]+" "
    +strangeNounsPlural[nCh1], txt, txtH+25)
    bubbleHeight=130;
}

function inSeason(){
    text(abstractNouns[nCh1]+" is a fruit in season at all times,", txt, txtH);
    text("and within reach of every "+strangeNouns[nCh2], txt, txtH+25);
    bubbleHeight=130;

}
function combination(){
    text(abstractNouns[nCh1]+" and "+strangeNounsPlural[nCh2]+
    " are a powerful combination", txt, singleLineHeight);
    bubbleHeight=75;
}


function onlyICan(){
    text("Only you can "+strangeVerbsObj[tCh1]+" your "+strangeNouns[nCh1]+".",
    txt, txtH);
    text("No one else can do it for you.", txt, txtH+25);
    bubbleHeight=130;
}

function jokeQuote(){
    text("This project definitely deserves an A", txt, txtH);
    text("-- "+personQuote[tCh1], txt+15, txtH+25);
    bubbleHeight=130;
}

For our final project, we made an Inspirational Quote Maze. The player moves a small square around in a randomly generated maze using the WASD keys. The dots in the maze tell the player inspirational quotes when they collide. For every quote the character receives, they gain a couple points in their “InspiroMeter.” Once they hear enough quotes, the game is over and they are congratulated for being inspired.
            Thomas mainly worked in the wall, player, and patterns files. He made the player movements and randomly generated the maze and the dots found within. He made it so the player can’t receive a different quote from the same dot twice in a row. He also created patterns to make the blocks look more exciting. 
            Anna mainly worked in the main and quotes files. She decided on the quote templates, made arrays filled with parts of speech, and randomized both of them for unique quotes. She made the speech bubble that appears when a character is talking. She also made the “InspiroMeter” and made the game end after a certain number of quotes. 
            Overall, we think that our project turned out well and we are proud of our efforts!

]]>
https://courses.ideate.cmu.edu/15-104/f2017/2017/12/08/final-project-thomas-wrabetz-anna-boyle/feed/ 0
Looking-outwards 12 Thomas Wrabetz https://courses.ideate.cmu.edu/15-104/f2017/2017/11/18/looking-outwards-12-thomas-wrabetz/ https://courses.ideate.cmu.edu/15-104/f2017/2017/11/18/looking-outwards-12-thomas-wrabetz/#respond Sun, 19 Nov 2017 00:56:21 +0000 https://courses.ideate.cmu.edu/15-104/f2017/?p=23198 Continue reading "Looking-outwards 12 Thomas Wrabetz"]]>

The book

This is a generative book by allison parrish. The book is entirely randomized, although the sentences are put together so that they follow each other in a valid manner. I personally don’t think it makes much sense, but it is still an interestinggt precursor, demonstrating both the potentialities and the drawbacks/difficulties of text mashing.

]]>
https://courses.ideate.cmu.edu/15-104/f2017/2017/11/18/looking-outwards-12-thomas-wrabetz/feed/ 0
Final project- proposal twrabetz https://courses.ideate.cmu.edu/15-104/f2017/2017/11/18/final-project-proposal-twrabetz/ https://courses.ideate.cmu.edu/15-104/f2017/2017/11/18/final-project-proposal-twrabetz/#respond Sun, 19 Nov 2017 00:39:10 +0000 https://courses.ideate.cmu.edu/15-104/f2017/?p=23187

Final-Project-Proposal-aboyle

I will be collaborating with Anna (the proposal link is above)

1 additional note-we already have the generative maze portion of the program working.

]]>
https://courses.ideate.cmu.edu/15-104/f2017/2017/11/18/final-project-proposal-twrabetz/feed/ 0
Looking-Outwards 11 Thomas Wrabetz https://courses.ideate.cmu.edu/15-104/f2017/2017/11/11/looking-outwards-11-thomas-wrabetz/ https://courses.ideate.cmu.edu/15-104/f2017/2017/11/11/looking-outwards-11-thomas-wrabetz/#respond Sun, 12 Nov 2017 04:57:28 +0000 https://courses.ideate.cmu.edu/15-104/f2017/?p=22720 Continue reading "Looking-Outwards 11 Thomas Wrabetz"]]>

I’m doing sound art now because I did Ronald Jenkees during the sound art week

“Journey into Hyperland” is a sound art experience that brings a crucial element of the musician’s world- the crazy acid trip- directly to your domestic screen. It’s parametrically generated which means it draws upon variables such as the user’s location and time of day. If you let it use your mic it can generate more stuff, which is kind of interesting although I didn’t see any tangible reaction to my sounds. In any case, the title does not lie as this work is hype to the max. There was also an elephant, so clearly the author’s animal selection abilities are as powerful as his programming skills. It’s like browsing around google earth when you’re bored except instead of the earth it’s a psychedelic EDM swamp with elephants and flying submarines.

]]>
https://courses.ideate.cmu.edu/15-104/f2017/2017/11/11/looking-outwards-11-thomas-wrabetz/feed/ 0
Project 11 Thomas Wrabetz https://courses.ideate.cmu.edu/15-104/f2017/2017/11/11/project-11-thomas-wrabetz/ https://courses.ideate.cmu.edu/15-104/f2017/2017/11/11/project-11-thomas-wrabetz/#respond Sun, 12 Nov 2017 04:57:13 +0000 https://courses.ideate.cmu.edu/15-104/f2017/?p=22718 Continue reading "Project 11 Thomas Wrabetz"]]>

sketch

//Thomas Wrabetz
//Section C
//twrabetz@andrew.cmu.edu
//Project-11

function turtleLeft(d) {
    this.angle -= d;
}
  
function turtleRight(d) {
    this.angle += d;
}
 
 
function turtleForward(p) {
    var rad = radians(this.angle);
    var newx = this.x + cos(rad) * p;
    var newy = this.y + sin(rad) * p;
    this.goto(newx, newy);
}
 
 
function turtleBack(p) {
    this.forward(-p);
}
 
 
function turtlePenDown() {
    this.penIsDown = true;
}
 
 
function turtlePenUp() {
    this.penIsDown = false;
}
 
 
function turtleGoTo(x, y) {
    if (this.penIsDown) {
      stroke(this.color);
      strokeWeight(this.weight);
      line(this.x, this.y, x, y);
    }
    this.x = x;
    this.y = y;
}
 
 
function turtleDistTo(x, y) {
    return sqrt(sq(this.x - x) + sq(this.y - y));
}
 
 
function turtleAngleTo(x, y) {
    var absAngle = degrees(atan2(y - this.y, x - this.x));
    var angle = ((absAngle - this.angle) + 360) % 360.0;
    return angle;
}
 
 
function turtleTurnToward(x, y, d) {
    var angle = this.angleTo(x, y);
    if (angle < 180) {
        this.angle += d;
    } else {
        this.angle -= d;
    }
}
 
 
function turtleSetColor(c) {
    this.color = c;
}
 
 
function turtleSetWeight(w) {
    this.weight = w;
}
 
 
function turtleFace(angle) {
    this.angle = angle;
}
 
 
function makeTurtle(tx, ty) {
    var turtle = {x: tx, y: ty,
                  angle: 0.0, 
                  penIsDown: true,
                  color: color(128),
                  weight: 1,
                  left: turtleLeft, right: turtleRight,
                  forward: turtleForward, back: turtleBack,
                  penDown: turtlePenDown, penUp: turtlePenUp,
                  goto: turtleGoTo, angleto: turtleAngleTo,
                  turnToward: turtleTurnToward,
                  distanceTo: turtleDistTo, angleTo: turtleAngleTo,
                  setColor: turtleSetColor, setWeight: turtleSetWeight,
                  face: turtleFace};
    return turtle;
}

var turtle;


function setup()
{
    createCanvas( 480, 480 );
    background( 255 );
    turtle = makeTurtle( width / 2, height / 2 );
    turtle.penDown;
    turtle.setWeight( 3 );
    turtle.setColor(0,0,0);
}

var turtleDist = 100;
var turtleSpeed = 1;
var turtleAcceleration = 0.05;

function draw()
{
    turtle.forward( turtleSpeed );
    if( dist( turtle.x, turtle.y, mouseX, mouseY ) < turtleDist) turtleSpeed += turtleAcceleration;
    else turtleSpeed -= turtleAcceleration * 2;
    turtleDist = dist( turtle.x, turtle.y, mouseX, mouseY );
    if( turtleSpeed < 0 )
    {
        turtle.left( 180 );
        turtleSpeed = -turtleSpeed;
    }
    turtle.turnToward( mouseX, mouseY, 7 );
    
}

It’s a turtle that chases you down.

]]>
https://courses.ideate.cmu.edu/15-104/f2017/2017/11/11/project-11-thomas-wrabetz/feed/ 0
looking-outward 10 Thomas Wrabetz https://courses.ideate.cmu.edu/15-104/f2017/2017/11/03/looking-outward-10-thomas-wrabetz/ https://courses.ideate.cmu.edu/15-104/f2017/2017/11/03/looking-outward-10-thomas-wrabetz/#respond Fri, 03 Nov 2017 21:03:58 +0000 https://courses.ideate.cmu.edu/15-104/f2017/?p=21090 Continue reading "looking-outward 10 Thomas Wrabetz"]]>

The Breathing Column is an architecture prototype by Caitlin Morris. It is a large installation that reacts to nearby people by turning, expanding and contracting in a lifelike fashion. The prototype is from 2010- I was not able to find a video of the finished installation. In any case, it is an interesting combination of architecture and computing that challenges the perception of buildings as static.

]]>
https://courses.ideate.cmu.edu/15-104/f2017/2017/11/03/looking-outward-10-thomas-wrabetz/feed/ 0
Project-10 Thomas Wrabetz https://courses.ideate.cmu.edu/15-104/f2017/2017/11/02/project-10-thomas-wrabetz/ https://courses.ideate.cmu.edu/15-104/f2017/2017/11/02/project-10-thomas-wrabetz/#respond Thu, 02 Nov 2017 21:21:53 +0000 https://courses.ideate.cmu.edu/15-104/f2017/?p=20907 0)); … Continue reading "Project-10 Thomas Wrabetz"]]>

sketch
The landscape is space with planets that have varying orbiting moons.

//Thomas Wrabetz
//Section C
//twrabetz@andrew.cmu.edu
//Project-10

planetArray = [];
planetFrames = 0;
planetFrequency = 110;

function stepPlanet()
{
    this.x += this.xspeed;
    this.y += this.yspeed;
    return ((this.x < width + this.radius * 2) & (this.y < height + this.radius * 2) && (this.y > 0));
}

function drawPlanet()
{
    push();
    translate( this.x, this.y );
    rotate( this.tilt );
    for( var i = 0; i < this.moonArray.length; i++ )
    {
        val = (this.moonArray[i].orbitFrames * this.moonArray[i].orbitSpeed) % TWO_PI;
        if( val < PI / 2 || val > 3 * PI / 2 )
        {
            this.moonArray[i].draw( this );
        } 
    }
    fill( this.planetColor );
    ellipse( 0, 0, this.radius, this.radius );
    fill( this.ringColor );
    ellipse( 0, 0, this.radius * this.ringWidth, this.radius * this.ringWidth / 10 );
    fill( this.planetColor );
    ellipse( 0, 0, this.radius * (this.ringWidth - 1) / 2 + this.radius, this.radius * (this.ringWidth - 1) / 20 );
    fill( 0 );
    arc( this.radius / 2, 0, this.radius * (this.ringWidth - 1) / 2, this.radius * (this.ringWidth - 1) / 20, -HALF_PI, HALF_PI);
    arc( -this.radius / 2, 0, this.radius * (this.ringWidth - 1) / 2, this.radius * (this.ringWidth - 1) / 20, HALF_PI, PI+HALF_PI);
    fill( this.planetColor );
    arc( 0, 0, this.radius, this.radius, PI, TWO_PI );
    for( var j = 0; j < this.moonArray.length; j++ )
    {
        val = (this.moonArray[j].orbitFrames * this.moonArray[j].orbitSpeed) % TWO_PI;
        if( val > PI / 2 & val < 3 * PI / 2 )
        { 
            this.moonArray[j].draw( this );
        }
    }
    pop();
}

function makePlanet()
{
    planet = { radius: random( 50, 125 ), x: 0, y: 0, 
               planetColor: color( random(256), random(256), random(256) ), ringColor: color( random(256), random(256), random(256), ), ringWidth: random( 1.15, 2 ), 
               tilt: random( 360 ), xspeed: random( 0.75, 2 ), yspeed: random( -0.5, 0.5 ), moonArray: [], draw: drawPlanet, step: stepPlanet };
    numMoons = random( -2, 4.5 );
    for( var i = 0; i < numMoons; i++ )
    {
        planet.moonArray.push( makeMoon() );
    } 
    planet.y = random( planet.radius, width - planet.radius );
    planet.x = - planet.radius * 2;
    return planet;
}

function drawMoon( planet )
{
    moonDist = planet.radius * this.orbitDistance * sin( this.orbitFrames * this.orbitSpeed );
    moonPerp = planet.radius * this.orbitDistance * cos( this.orbitFrames * this.orbitSpeed ) * this.orbitAxis2;
    sizeModifier = 1 - cos( this.orbitFrames * this.orbitSpeed )/4;
    moonX = moonDist * cos( this.orbitAxis ) - moonPerp * sin( this.orbitAxis );
    moonY = moonDist * sin( this.orbitAxis ) + moonPerp * cos( this.orbitAxis );
    fill( this.moonColor );
    ellipse( moonX, moonY, this.radius * sizeModifier, this.radius * sizeModifier );
    this.orbitFrames++;
}

function makeMoon()
{
    moon = { radius: random( 10, 20 ), orbitSpeed: random( 0.025, 0.05 ), orbitDistance: random( 1, 2 ), orbitAxis: random(0,TWO_PI), orbitAxis2: random(0,1), orbitFrames: 0,
             moonColor: random( 125, 255 ), draw: drawMoon };
    return moon;
}

function setup()
{
    createCanvas( 480, 480 );
    noStroke();
}

function draw()
{
    background( 0 );
    if( planetFrames <= 0 )
    {
        planetArray.push( makePlanet() );
        planetFrames = random( 90, 130 );
    }
    planetFrames--;
    for( var i = 0; i < planetArray.length; i++ )
    {
        planetArray[i].draw();
        if( !planetArray[i].step() )
        {
            planetArray.splice( i, 1 );
            i -= 1;
        }
    }
}

]]>
https://courses.ideate.cmu.edu/15-104/f2017/2017/11/02/project-10-thomas-wrabetz/feed/ 0
lookingoutwards-09 Thomas Wrabetz https://courses.ideate.cmu.edu/15-104/f2017/2017/10/27/lookingoutwards-09-thomas-wrabetz/ https://courses.ideate.cmu.edu/15-104/f2017/2017/10/27/lookingoutwards-09-thomas-wrabetz/#respond Sat, 28 Oct 2017 03:59:03 +0000 https://courses.ideate.cmu.edu/15-104/f2017/?p=20624 Continue reading "lookingoutwards-09 Thomas Wrabetz"]]>

My looking outwards of someone else’s looking outwards is the Ross Spiral curriculum from week 7 (data visualization).

Ross Spiral Curriculum

The original looking outwards

I agree that the visualization is quite cool and nicely suggests the spiral nature of k-12 education (most of it anyways- in my british elementary school all we spiraled through was the tudors). However I am skeptical about the computational nature of the spiral- i.e., it seems to just be a linear sequence of topics arranged into a spiral, and not reflecting an actual data computation that would reveal the spiral-like nature of data on certain parameters of k-12 curricula.

]]>
https://courses.ideate.cmu.edu/15-104/f2017/2017/10/27/lookingoutwards-09-thomas-wrabetz/feed/ 0
Project-09 Thomas Wrabetz https://courses.ideate.cmu.edu/15-104/f2017/2017/10/27/project-09-thomas-wrabetz/ https://courses.ideate.cmu.edu/15-104/f2017/2017/10/27/project-09-thomas-wrabetz/#respond Sat, 28 Oct 2017 03:58:41 +0000 https://courses.ideate.cmu.edu/15-104/f2017/?p=20622 Continue reading "Project-09 Thomas Wrabetz"]]>

sketch

//Thomas Wrabetz
//Section C
//twrabetz@andrew.cmu.edu
//Project-09

var underlyingImage;
var locations = [];
var squares = [];


function preload() {
    var myImageURL = "https://i.imgur.com/uCMUDGO.jpg";
    underlyingImage = loadImage(myImageURL);
}

function setup() {
    createCanvas(200, 250);
    noStroke();

    underlyingImage.loadPixels();
    frameRate(60);
    for( var i = 0; i < width / 5; i++ )
    {
        locations.push( [] );
        for( var j = 0; j < height / 5; j++ )
        {
            locations[i].push(0);
        }
    }
}

function draw()
{
    for( var i = 0; i < len(squares); i++ )
    {
        squares[i].draw();
    }
}

function squareStep()
{
    if( this.y == this.targetY ) return;
    this.y += 1;
}

function squareDraw()
{
    push();
    fill( this.color );
    rect( this.x, this.y, 5, 5 );
    pop();
}

function makeSquare( sx, sy, stargetY, scolor )
{
    s = { x: sx, y: sy, targetY: stargetY, step: squareStep, draw: squareDraw, color: scolor };
    return s;
}

function draw() {
    background(0);
    var targetX = int(random((width-1)/5))*5;
    var test = false;
    for( var i = 0; i < locations.length; i++ )
    {
        if( locations[i][0] == 0 ) test = true;
    }
    for( var i = 0; i < squares.length; i++ )
    {
        squares[i].step();
        squares[i].draw();
    }
    if( !test ) return;
    while( locations[targetX/5][0] )
    {
      targetX = int(random((width-1)/5))*5;
    }
    for( var i = 0; i < height / 5; i++ )
    {
        if( locations[targetX/5][i] == 1 )
        {
            locations[targetX/5][i-1] = 1;
            squares.push( makeSquare( targetX, 0, (i-1)*5, underlyingImage.get( targetX, (i-1)*5 ) ) );
            break;
        }
        if( i == height/5 - 1 )
        {
            locations[targetX/5][i] = 1;
            squares.push( makeSquare( targetX, 0, i*5, underlyingImage.get( targetX, i*5 ) ) );
        }
    }

    
}

It’s a picture of me from highschool made out of falling blocks.

]]>
https://courses.ideate.cmu.edu/15-104/f2017/2017/10/27/project-09-thomas-wrabetz/feed/ 0
Looking-Outwards 08 Thomas Wrabetz https://courses.ideate.cmu.edu/15-104/f2017/2017/10/20/looking-outwards-08-thomas-wrabetz/ https://courses.ideate.cmu.edu/15-104/f2017/2017/10/20/looking-outwards-08-thomas-wrabetz/#respond Sat, 21 Oct 2017 03:53:41 +0000 https://courses.ideate.cmu.edu/15-104/f2017/?p=19414 Continue reading "Looking-Outwards 08 Thomas Wrabetz"]]>

Chris Sigrue is an artist, programmer, teacher, and inventor. I enjoyed her lecture and the audience participation in her works (something we have not really seen yet). There were a lot of really interesting and innovative exhibits: because of the audience participation, there was a level of unexpected and renewing novelty that went beyond even ordinary randomness.

]]>
https://courses.ideate.cmu.edu/15-104/f2017/2017/10/20/looking-outwards-08-thomas-wrabetz/feed/ 0