PComp Final

In my last blog post regarding this project, I talked about the progress we’d made. We had fabricated a button into a baseball helmet, revamped the sketch so that it would run properly and built a home plate, which looked a little something like this:
At this time in our process, Grant and Katie and I had a sketch that – unbeknownst to us at the time – was about 85% done, a batting helmet that had functionality, and a hollowed out bat. Here’s what remained: coding the FSR’s, putting the vibrating motor sensor into the bat, mounting the Arduino 101 into the bat, making our code more specific and, most importantly, making sure that the bat, helmet and home plate worked in tandem with one another. We knew that in order to reach our goal of being done by Monday night – we wanted to give ourselves at least 24 hours of extra time – we had to start delegating certain tasks. Luckily for Grant and I, Katie is truly a master fabricator; she is the assistant technical director for the Tisch Grad acting program. It was decided that Grant and Katie would start to get more specific with the hardware while I would focus on the code. We would meet up this past Saturday and spend the weekend making sure everything worked together.
I knew that before I could start worrying about how to incorporate all three of the elements of the project together, they had to be working seamlessly individually. The helmet already done with, I focused first on the FSR’s. I wasn’t too concerned about the code on the Arduino side, I was more worried about making each FSR individually trigger something. Essentially, the FSR was going to need to act as a button; once it was pressed something would happen. But because the “button” needed to be on home plate and therefore needed to be stepped on, I figured it would be easiest and most in line with our ‘try-to-make-the-tech-hard-to-see’ aesthetic to stick with the FSR’s. I created some code in p5 from scratch to see if it would work and after tinkering for a few hours, each button triggered a different part of the sketch. Now onto the bat.
Building a home for the 101
Paneling for the Batters Box
Precision, precision, precision. The biggest issue that I faced in my midterm is that there was way too much delay with the bat. You would swing and would have to wait a second before the bat would swing with you. If I was going to try to simulate getting a hit from a professional baseball player, timing would be of the utmost importance. After making sure my ‘handshaking’ was working and removing every console log from the code, I feel there has been a vast improvement in the precision of the bat. However, the issue now lay with a different element of the bat: the vibrating motor.
Making an enclosure for the helmet
Threading vibrating motor through the bat
It was very important to me to make the user feel as if they really got a hit when playing this game. At first I thought I was going to need to use a haptic motor controller to set up different kinds of hits but resident Joe Mango showed me a much easier way: bypass the haptic motor controller and set a regular vibrating motor to a PWM pin. Switch back and forth between having it “high” and having it “low”. I was concerned that “high” wouldn’t be felt throughout the plastic bat but fortunately, the motor produced the perfect amount of vibration. My biggest issue now was how to let the arduino code know when something had been triggered in the p5 code. This lab proved to be instrumental in this working. There are still some issues with this vibrating motor that I will get to later.
Now that all three instruments were working separate from one another, it was time to try to make them work in unison. Daniel Shiffman informed us that in order to maximize efficiency, we would now need to consolidate our three huge pieces of code – we had a code for each mode and were triggering them in the html. While Grant focused on this, I tried to dig into how I was going to make the three elements work together. Turns out you cannot open multiple serial ports in the p5 editor. This was a very alarming shock. Here we were about a week away from everything being due and it just may not work. An hour and a half worth of office hours with Shawn Van Every – whom I cannot thank enough for all of his patience with me – all elements were running pretty well with one another.
Now on to fabrication. 
I let Katie know that the vibrating motor needed to be in the lower shaft of the bat and the arduino needed to be at the top. She put an enclosure in the bottom of the bat to isolate the motor, insulated it with foam to prevent additional movement, and cut the bat in half. This way I could have easy access to the motor should it cease to work. With the other half, she made a circular piece of wood to stabilize the center, ran the wire from the motor through that and up to the top where she made a piece of wood to screw to the arduino. Did I tell you she was a genius? She then spray painted the bat to make it look more realistic and less plastic. I think she succeeded.
Onto the home plate. We decided on three colors, Grant fixed the home screen to adjust them while Katie and I spray painted them. Katie added wood paneling to the sides also to give it more of a sheen. She then turned it around and made an enclosure for the Arduino and breadboard that was operating the FSR’s which featured a long wooden piece to prevent the board from moving around at all. With all of the fabrication now done, we decided to spend our additional time on Saturday utilizing the free theater Katie had in the Grad building to film the commercial/instructional video that you saw at the top of the page.
The final step in the process was the perf board. The arduino and Bluetooth that was hooked up to it were going to be moving around a LOT as they are in the main shaft of the bat. Not only do they need to be very stabilized to the bat but the connections need to be super stabilized as well. My first perf board was an utter failure. My second was a success but the header pins on the male to female wires kept breaking off. By my third perf board I became a soldering pro though and I feel like it looks and works pretty well.
 
            With everything done, Grant and I had a few hours to test out all the components together. While we were thrilled that they were working together, there is one area where there could be some improvement: the vibrating motor sensor. We just cannot get it to vibrate at the right time. It seems like there is too much happening even with all of the console logs removed. Perhaps it’s because there is too much in the preload but even when I removed the music files, there was still significant lag. At this point, I’m at a loss and I hope to pick your brain about how I can better correct this in the future.
 
            At the end of the day, this has been an amazing project to work on. It’s so bizarre to look back on that first sketch I did about baseball and think about how far I’ve come. There are so many people that deserve acknowledgement: Joe Mango, Shawn Van Every, Tom Igoe, Dan O’Sullivan and Dan Shiffman, Kat Sullivan, Jingwen Zhu, Justin Peake, Or Fleischer, and I’m sure there are more. Of course, none of this would have happened if not for the dedication and commitment of my partners Grant Henry and Katie Takacs.
 
I was sitting in Maryland over Thanksgiving. Grant and Katie had decided to get together the weekend after to work on fabrication while I took a few extra days and focused on the coding side of things. At one point, I got a text from them. It was a photo of that grass batters box. I couldn’t believe it; I had a grin from ear to ear. It was so noticeable my dad asked me what was up. I turned my phone to him and showed him the photo. I was just blown away by how awesome it was. “Man,” he said, “this is some group you got, huh?” It sure was.

ICM Final

UPDATE: FINAL CODE HAS BEEN ADDED TO THE BOTTOM OF THE PAGE

What Does It Take To Be A Major League Baseball Player?

I don’t know if a lot of you are aware but it is very, very difficult to be a Major League Baseball Player. In most professional sports, there are few steps: you play in college, you get drafted, and if you prove good enough you get to play professional football, hockey or basketball. This is not the case in Major League Baseball. If you are 100% the best player in college, if there has never been anyone like you to play the game at the rare age of 18 or 21 you are still placed in a brutal minor league system that can completely control your soul. Let’s take a look at a trailer for the film “A Player to be Named Later” for more information.

I asked this question to give you a better idea of why I love this sport so much: it’s not just a sport it’s a story that grows and changes every single year and never gets boring. There are truly millions of examples of this but let’s stick with one that happened this past year. For those who don’t know, pitchers rarely get the chance to hit. A typical batter will get upwards of 600 – 700 opportunities to get a hit and a pitcher may get like…50 at most. Michael Lorenzon, a pitcher for the Reds this year – got five. Five opportunities to just get a hit. On around August 12th, Michael Lorenzon’s father – whom he was very close with – passed away. After returning from a bereavement list, Lorenzon was put into the game for his team.

This is why I love baseball.

As is true with all things you love, you want to know more about it and maybe try to instill some of that information in others.

When I started learning coding awhile ago, I was a bit terrified because I was in an unfamiliar place. However, when I started using baseball statistics in coding, the experience of discomfort lessened. Coding became secondary, a byproduct of needing to learn how to make baseball more accessible. I started with a simple baseball game:

When I made this, I was super excited. I had finally made a baseball game! Very strange to look back on it now. The evolution of the game is entirely thanks to the introduction of JSON files. They gave me the opportunity to take real baseball data – of which there is an abundance – and apply it to my work. I’ll never forget being late to a bar that night because I was so excited to make this:

After I had fun with this, I decided why not mix the two, which led me to my final. How cool would it be if I could take real data and use it to show the difference in a pitchers arsenal. I’ve seen plenty of videos and .gif’s but something about visualizing the data got me really excited. Luckily, I found two amazing partners – and fellow baseball fans – in Katie Takacs and Grant Henry and after countless hours we made what can only best be shown in a local host.

Here is the final code:

var gameMode = ‘EASY’;

//EASY MODE
var x = 380;
var y = 285;
var speed = 3.5;
var speedb = 0;
var accx = -0.01;
var deg = 0;

var serial;
var serialTwo;
var serialThree;
var ballX, ballY, ballZ;
var batX, batY, batZ;
var portName = ‘/dev/cu.AdafruitEZ-Link71f3-SPP’; ///dev/cu.AdafruitEZ-Link71f3-SPP; for accelerometer
var portNameTwo = ‘/dev/cu.AdafruitEZ-Link743a-SPP’; ///dev/cu.AdafruitEZ-Link743a-SPP; for buttons
var portNameThree = ‘/dev/cu.usbmodem1421′;//’/dev/cu.usbmodem1411’; or whatever port you’re plugged into for FSR’s
var w = 35;

var prevBallY;
var counter = 150;
var batspeed = 5;

//hits counter variables
var score = 0;
var imgScore;
var bringEm;
var shaggy;
var noMatter;

var swinging = false;
//var getHit = false;

var inData;
var outByte = 0;

//HARD MODE
var sensorValue = 5;
var ball, pitchSelector, data, data2;
var bigList = [];
var speedHard = 3;

//p is from 0-4 and determines which pitcher’s stat’s we’re accessing: 0 is Thor, 1 is kershaw, etc
var p = 1;
//k is however many pitches the pitcher has in their arsenal
var k = 4;
// r is the minimumim vel for each pitcher
var r = 30;
//b is second real value in PitchMapMin
var b = 101.4;
//s is first real value in PitchMapMov
var s = -9.0;
//q is second real value in PitchMapMov
var q = 5;

// changes colors in the switch to make colors unanimous across the board
var cOne = 255;
var cTwo = 255;
var cThree = 0;
var cFour = 244;
var cFive = 66;
var cSix = 66;

//pitchers display variables
var currentImg;
var kershaw;
var mo;
var thor;
var wake;
var yu;

//Wake’s variables. Adj makes his movement start earlier, Knuckle allows for his wacky movement
// to be in the code
var wakeAdj = 400;
var knuckle = 0;

// making JSON data global.
var PitchMax;
var PitchMin;
var PitchMapMov;
var PitchMapMax;
var PitchMapMin;
var PitchMapMov;
var PitchrandomSpeed;
var PitchSpeed;

//GAME MODE
var speedc = 1;

// timer variables
var clockStart = 60;
var interval;

var modeEasy = false;
var modeHard = false;
var modeGame = false;
var modeMenu = false;
function preload() {
img = loadImage(‘backgroundField.png’);
image2 = loadImage(‘Bat.png’);
image3 = loadImage(‘baseball.png’);
image4 = loadImage(‘mainMenu3.png’);
mySound = loadSound(‘Cheer.mp3’);

// load pitchers images
kershaw = loadImage(‘kershawTag2.png’);
mo = loadImage(‘moTag.png’);
thor = loadImage(‘thorTag.png’);
wake = loadImage(‘wakeTag.png’);
yu = loadImage(‘yuTag.png’);

// load easter egg sounds
bringEm = loadSound(‘BringEmOut.wav’);
shaggy = loadSound(‘Boombastic.wav’);
noMatter = loadSound(‘WinNoMatter.wav’);

//load pitcher data
data = loadJSON(‘ReorderedPitcherData.json’, gotData);
data2 = loadJSON(‘ReorderedPitcherData2.json’, gotData2);
}

function setup() {
createCanvas(800, 650);
angleMode(DEGREES);
startTimer();
noMatter.onended(startTimer);

//starts at Kershaw
currentImg = kershaw;
//sensorValue = 1;

serial = new p5.SerialPort(“localhost”, 8083);
serial.on(‘list’, printList);
serial.on(‘data’, serialEvent);
serial.on(‘open’, openPort);
serial.list();
serial.open(portName);

serialTwo = new p5.SerialPort(“localhost”, 8081);
serialTwo.on(‘list’, printList);

serialTwo.on(‘data’, serialEventTwo);
serialTwo.on(‘open’, openPortTwo);

serialTwo.open(portNameTwo);
serialThree = new p5.SerialPort(“localhost”, 8082);
serialThree.on(‘list’, printList);

serialThree.on(‘data’, serialEventThree);
serialThree.on(‘open’, openPortThree);
serialThree.open(portNameThree);
textSize(24);

}
function draw() {
clear();
image(img, -30, -50, width+30, height);
// batMove();
// if(getHit === true){
// //console.log(“buzz?”);
// serial.write(“C”);
// console.log(‘writing c’)
// //console.log(serial.write);
// }
// if(getHit === false){
// serial.write(“L”);
// console.log(‘writing L’)
// }

// background(0);
// fill(255);
// text(batX + ” ” + batY + ” ” + batZ, width/2, height/2);

if (ballX === 0 && ballY === 0 && ballZ === 0 && clockStart === 60){
modeMenu = true;
modeEasy = false;
modeHard = false;
modeGame = false;

}
if(modeMenu === true){

image(image4, 0, 0, width+40, height);
modeEasy = false;
modeHard = false;
modeGame = false;
}

if (ballX > 400){
clear();
modeEasy = true;
modeMenu = false;
modeHard = false;
modeGame = false;
clockStart = 59;
score = 0;
}

if(modeEasy === true) {
//console.log(“why aren’t you swinging”);
printTimerShmimer();
printScore();
baseball();
pitch();
returnball();
bat();
contact();
}

if (ballY > 400){
clear();
modeEasy = false;
modeHard = true;
modeMenu = false;
modeGame = false;
clockStart = 59;
score = 0;
}

if(modeHard === true){
//what causes the ball itself to move
if(typeof ball != “undefined”){
ball.display();
ball.move();
if(ball.inScreen()) {
for (var i = 0; i < data.pitchers[p].pitches.length ; i++){
for (var j = 0; j < data.pitchers[p].pitches[i][“Frequency”]/10; j++){
bigList.push(i);
}
}
pitchSelector = bigList[floor(random(bigList.length))];
//console.log(“pitch selection” + pitchSelector);
ball = new Thor(pitchSelector);

//console.log(“Sensor Value: ” + sensorValue);
}
// pitchDisplay();

}

printScore();
printTimerShmimer();
bat();
contactHard();
// changePitcher();
}

if (ballZ > 400){
clear();
modeHard = false;
modeGame = true;
modeMenu = false;
modeEasy = false;
clockStart = 59;
score = 0;
}

if(modeGame === true){

//pitcher image display
if (typeof currentImg != “undefined”) {
image(currentImg, 80, 5, 125, 250);
}

//what causes the ball itself to move
if(typeof ball != “undefined”){
ball.display();
ball.move();
barDisplay();
if(ball.inScreen()) {
for (var i = 0; i < data2.pitchers[p].pitches.length ; i++){
for (var j = 0; j < data2.pitchers[p].pitches[i][“Frequency”]/10; j++){
bigList.push(i);
}
}
pitchSelector = bigList[floor(random(bigList.length))];
//console.log(“pitch selection” + pitchSelector);
ball = new Thor2(pitchSelector);

//console.log(“Sensor Value: ” + sensorValue);
}
pitchDisplay();
}
//console.log(PitchrandomSpeed);

pitchText();
pitchDisplay();
printScore();
printTimerShmimer();
bat();
contactGame();
changePitcher();
adjustStats();

}
}

//baseball display
function baseball() {
fill(255);
ellipseMode(CORNER);
ellipse(x, y, w, w);
image(image3, x, y, w-1, w-1);
}

//baseball movement
function pitch() {
y = y + speed;
x = x + speedb;
// speedb = speedb + accx * 2;

if (y >= height*2.5) {
y = 235;
}
}

//baseball restarts
function returnball() {
if (x > 800 || x < -100 || y > height*1.65 || y < -900) {
baseball();
x = 380;
y = 285;
speed = 3;
speedb = 0;
}
}
//batter up
function bat() {
translate(245, 450);
rotate(deg);
noStroke();
fill(100, 100, 100, 0);
image(image2, 0, 0, 25, 180);
// console.log(“bat”);
// console.log(swinging);
if (swinging) {
deg = deg – batspeed;
}

if (deg <= -180) {
deg = 0;
swinging = false;
}

var diffY = ballY – prevBallY;

if (batX > 105 && batX < 120 && counter > 150) {
swinging = true;
counter = 0 ;

}
// console.log(deg);
counter++;
prevBallY = ballY;

if (y < 225 || x < 0) {
serial.write(“L”);
}
}

//bat hits ball
function contact() {
var diff = deg + 90;
image(image2, 0, 0, 25, 180);

if (abs(diff) < 10) {
if (y > 442 && y < 558) {
if (!mySound.isPlaying()) {
mySound.play();
serial.write(“C”);
speed = speed * random(-4, -1);
speedb = speedb + random(-10, 5);
// see addScore function…
addScore();
}
}
}
}
//}

// send when an event occurs *GAME MODE*
function Thor2(pitch/*frequency*/) {
this.x = 375;
this.y = 220;
this.speedHard = 1;
this.speedc = 0;

this.w = 10;

this.rgb = [0,200,100];

// noprotect
switch (pitch){
//knuckleball will be
case 0:
//red…fastball
this.rgb = [cFour,cFive,cSix];
//console.log(this.rgb);
break;
case 1:
//yellow… curveball
this.rgb = [cOne,cTwo,cThree];
//console.log(this.rgb);
break;
case 2:
//turqouise … change-up
this.rgb = [66,244,235];
//console.log(this.rgb);
break;
case 3:
//purple… slider
this.rgb = [125,66,244];
//console.log(this.rgb);
break;
case 4:
//lime green…sinker
this.rgb = [0,255,0];
//console.log(this.rgb);
break;
case 5:
// blue …cutter
this.rgb = [0, 0, 205];
//console.log(this.rgb);
break;
case 6:
//orange…two-seamer
this.rgb = [255,165, 0];
//console.log(this.rgb);
break;
default:
this.rgb = [0,200,100];
//console.log(‘no color was passed into ball’);
}

PitchMax = data2.pitchers[p].pitches[pitch].MaxVelo;
PitchMin = data2.pitchers[p].pitches[pitch].MinVelo;
PitchxMov = data2.pitchers[p].pitches[pitch].xMov;
//mapping of maximum velocity
PitchMapMax = map(PitchMax, 50, b, 0, 8);
//mapping of minimum velocity
PitchMapMin = map(PitchMin, r, b, 0, 8);
// mapped xMov of fastball
PitchMapMov = map(PitchxMov, s, q, -7, 4);

// pitch velo will randomly vary between max and min
PitchrandomSpeed = random(PitchMapMax, PitchMapMin);
PitchSpeed = Math.round(random(PitchMin, PitchMax));

this.display = function(){
fill(this.rgb[0],this.rgb[1],this.rgb[2], 100);
image(image3, this.x, this.y, this.w, this.w);
ellipseMode(CORNER);
ellipse(this.x, this.y, this.w-1, this.w-1);
}

this.move = function(){
this.y = this.y + this.speedHard + PitchrandomSpeed;
this.x = this.x + this.speedc;

if(this.y> wakeAdj) {
this.x = this.x + PitchMapMov + knuckle;
}

if (this.y > 400){
this.w = this.w +2;
}

if (this.y < 219) {
this.w = this.w – 1.65;
}

};

this.inScreen = function(){
if (this.y < 225 || this.x < 0) {
serial.write(“L”);
}
if(this.y > height*2 || this.y < -500) {
return true;
}
};
}

// send when an event occurs *HARD*
function Thor(pitch/*frequency*/) {
this.x = 375;
this.y = 220;
this.speedHard = 3.5;
this.speedb = 0;

this.w = 10;

this.rgb = [0,200,100];

// noprotect
switch (pitch){
//knuckleball will be
case 0:
//red…fastball
this.rgb = [cFour,cFive,cSix];
//console.log(this.rgb);
break;
case 1:
//yellow… curveball
this.rgb = [cOne,cTwo,cThree];
//console.log(this.rgb);
break;
case 2:
//turqouise … change-up
this.rgb = [66,244,235];
//console.log(this.rgb);
break;
case 3:
//purple… slider
this.rgb = [125,66,244];
//console.log(this.rgb);
break;
case 4:
//lime green…sinker
this.rgb = [0,255,0];
// console.log(this.rgb);
break;
case 5:
// blue …cutter
this.rgb = [0, 0, 205];
// console.log(this.rgb);
break;
case 6:
//orange…two-seamer
this.rgb = [255,165, 0];
//console.log(this.rgb);
break;
default:
this.rgb = [0,200,100];
// console.log(‘no color was passed into ball’);
}

PitchMax = data.pitchers[p].pitches[pitch].MaxVelo;
PitchMin = data.pitchers[p].pitches[pitch].MinVelo;
PitchxMov = data.pitchers[p].pitches[pitch].xMov;
//mapping of maximum velocity
PitchMapMax = map(PitchMax, 50, b, 0, 8);
//mapping of minimum velocity
PitchMapMin = map(PitchMin, r, b, 0, 8);
// mapped xMov of fastball
PitchMapMov = map(PitchxMov, s, q, -7, 4);

// pitch velo will randomly vary between max and min
PitchrandomSpeed = random(PitchMapMax, PitchMapMin);
PitchSpeed = Math.round(random(PitchMin, PitchMax));

this.display = function(){
fill(this.rgb[0],this.rgb[1],this.rgb[2], 100);
image(image3, this.x, this.y, this.w, this.w);
ellipseMode(CORNER);
ellipse(this.x, this.y, this.w-1, this.w-1);
}

this.move = function(){
this.y = this.y + this.speedHard;
this.x = this.x + this.speedb;

if(this.y> wakeAdj) {
this.x = this.x + PitchMapMov + knuckle;
}

if (this.y > 400){
this.w = this.w +2;
}

if (this.y < 219) {
this.w = this.w – 1.70;
serial.write(“L”);
}

};

this.inScreen = function(){
if (this.y < 225 || this.x < 0) {
serial.write(“L”);
}

if(this.y > height*2 || this.y < -500) {
return true;
}
};
}

function gotData(){
ball = new Thor(0);
}

function gotData2(){
ball = new Thor2(0);
}

// bat hits ball
function contactHard() {
var diff = deg + 90;
image(image2, 0, 0, 25, 180);

if (abs(diff) < 10) {
if (ball.y > 442 && ball.y < 558 && ball.x > 325 && ball.x < 450) {
if (!mySound.isPlaying()) {
serial.write(“C”);
mySound.play();
ball.speedHard = ball.speedHard – 15;
ball.speedb = ball.speedb + random(-10,5);

// see addScore function…
addScore();
}
}
}
}

// bat hits ball
function contactGame() {
var diff = deg + 90;
image(image2, 0, 0, 25, 180);

if (abs(diff) < 10) {
if (ball.y > 442 && ball.y < 558 && ball.x > 325 && ball.x < 450) {
if (!mySound.isPlaying()) {
serial.write(“C”);
mySound.play();
ball.speedHard = ball.speedHard – 15;
ball.speedc = ball.speedc + random(-10,5);

// see addScore function…
addScore();
}
}
}
}

//score counter
function addScore() {
//add one
score++;

//Easter egg sounds
if (score == 5) {
bringEm.play();
}
if (score == 10) {
shaggy.play();
}
}

//scroll through the pitchers when right arrow is pressed
function changePitcher() {
if (sensorValue == 1) {
if (currentImg == kershaw) {
currentImg = thor;
}
}
if (sensorValue == 2) {
if(currentImg == thor) {
currentImg = yu;
}
}
if (sensorValue == 3) {
if(currentImg == yu) {
currentImg = mo;
}
}
if (sensorValue == 4) {
if (currentImg == mo) {
currentImg = wake;
}
}
if (sensorValue == 5) {
if (currentImg == wake) {
currentImg = kershaw;
}
}
}

function adjustStats(){
if(sensorValue == 1){
thorSpecifics();
}
if(sensorValue == 2){
yuSpecifics();
}
if(sensorValue == 3){
moSpecifics();
}
if (sensorValue == 4) {
wakeSpecifics();
}
if(sensorValue == 5){
kershawSpecifics();
}
}

//Displays the score
function printScore() {
textAlign(LEFT);
fill(255, 200);
textSize(40);
textStyle(BOLD);
// image(imgScore, 300, 15, 220, 150);
text(“HITS ” + score, width-350, 185);

if (score == 5){
fill(0, 200);
// textSize(40);
text(“HITS ” + score, width-350, 185);
textAlign(CENTER);
text( “HOMERUN!”, width/2, 50);
}

if (score == 10) {
fill(0, 200);
// textSize(40);
text(“HITS ” + score, width-350, 185);
textAlign(CENTER);
text( “Grant Slam!”, width/2, 50);
}

if (score == 15){
fill(0, 200);
// textSize(40);
text(“HITS ” + score, width-350, 185);
textAlign(CENTER);
text( “Fasten Your Seatbelts!”, width/2, 50);
}

if (score == 20){
fill(0, 200);
// textSize(40);
text(“HITS ” + score, width-350, 185);
textAlign(CENTER);
textSize(20);
text( “Wicked Clutch Hittah!”, width/2, 50);
}
}

function barDisplay(){
noStroke();
fill(90, 200);
rect(25, 545, 190, 40);
}

function pitchText(){
textStyle(BOLD);
textAlign(CENTER);
textSize(10);
text(“PITCH | SPEED”, 120, 540);
}
function textDisplay(){
strokeWeight(2);
stroke(50);
textSize(20);
textStyle(BOLD);
textAlign(CENTER);

}

function printList(portList) {
for (var i = 0; i < portList.length; i++) {
// println(i + ” ” + portList[i]);
}
}

function openPort() {
serial.write(‘x’);
console.log(“port 1”);
}

function openPortTwo() {
serialTwo.write(‘x’);
console.log(“port 2”);
}

function openPortThree() {
serialThree.write(‘x’);
console.log(“port 3”);
}
//accelerometer/vibrating sensor
function serialEvent() {
var inString = serial.readStringUntil(‘\r\n’);
if (inString.length > 0) {
if (inString !== ‘hello’) {
var values = split(inString, ” “);
if (values.length > 0) {
batX = Number(values[0]);
// batY = Number(values[1]);
// batZ = Number(values[2]);
}
//console.log(batX);

}
serial.write(‘x’);
}
}
// button
function serialEventTwo() {
var inStringTwo = serialTwo.readLine();
if (inStringTwo.length > 0) {
inStringTwo = inStringTwo.trim();
sensorValue = inStringTwo;
//console.log(sensorValue);
//sensorValue = Number(inString/4);
}
}

//FSR’s
function serialEventThree(){
var inStringThree = serialThree.readStringUntil(‘\r\n’);
//console.log(inStringThree);

if (inStringThree.length > 0) {
if(inStringThree !== ‘hello’) {
var valuesFSR = split(inStringThree, ” “);
if (valuesFSR.length > 2) {
ballX = Number(valuesFSR[0]);
ballY = Number(valuesFSR[1]);
ballZ = Number(valuesFSR[2]);
//console.log(ballX);
}
}
serialThree.write(‘x’);

}

}

function thorSpecifics(){
p = 0;
k = 5;
r = 50;
s = -9.0;
q = 5.0;
b = 101.4;
cOne = 255;
cTwo = 255;
cThree = 0;
cFour = 244;
cFive = 66;
cSix = 66;
bigList = [];
wakeAdj = 400;
knuckle = 0;
pitchMapMov = map(PitchxMov, s, q, -7, 4);
}

function yuSpecifics(){
p = 2;
k = 7;
r = 50;
s = -10.0;
q = 10.0;
b = 101.4
cOne = 255;
cTwo = 255;
cThree = 0;
cFour = 244;
cFive = 66;
cSix = 66;
bigList = [];
wakeAdj = 400;
knuckle = 0;
pitchMapMov = map(PitchxMov, s, q, -7, 4);
}

function moSpecifics (){
p = 3;
k = 1;
r = 50;
s = -10.0;
q = 5.0;
b = 101.4;
cOne = 0;
cTwo = 0;
cThree = 205;
cFour = 244;
cFive = 66;
cSix = 66;
bigList = [];
wakeAdj = 400;
knuckle = 0;
pitchMapMov = map(PitchxMov, s, q, -7, 4);
}

function wakeSpecifics(){
p = 4;
k = 1;
r = 40;
s = -9;
q = 5;
b = 77.0;
cOne = 255;
cTwo = 255;
cThree = 0;
cFour = 255;
cFive = 105;
cSix = 180;
wakeAdj = 250;
pitchMapMov = 0;
knuckle = random(-10, 10);
bigList = [];
}

function kershawSpecifics(){
p = 1;
k = 4;
r = 30;
s = -9.0;
q = 5.0;
b = 101.4;
cOne = 255;
cTwo = 255;
cThree = 0;
cFour = 244;
cFive = 66;
cSix = 66;
wakeAdj = 400;
knuckle = 0;
pitchMapMov = map(PitchxMov, s, q, -7, 4);
bigList = [];
}

function pitchDisplay(){
//kershaw
if(currentImg == kershaw && sensorValue == 5 && pitchSelector == 0 && ball.y > height){
textDisplay();
//red
fill(255, 102, 102);
text(“Fastball: ” + PitchSpeed + ” MPH”, 120, 570);
}
if(currentImg == kershaw && sensorValue == 5 && pitchSelector == 1 && ball.y > height){
textDisplay();
//yellow
fill(255, 255, 0);
text(“Curveball: ” + PitchSpeed + ” MPH”, 120, 570);
}
if(currentImg == kershaw && sensorValue == 5 && pitchSelector == 2 && ball.y > height){
textDisplay();
//cyan
fill(66, 244, 235);
text(“Change-Up: ” + PitchSpeed + ” MPH”, 120, 570);
}
if(currentImg == kershaw && sensorValue == 5 && pitchSelector == 3 && ball.y > height){
textDisplay();
//purple
fill(236, 179, 255);
text(“Slider: ” + PitchSpeed + ” MPH”, 120, 570);
}

//Thor
if(currentImg == thor && sensorValue == 1 && pitchSelector == 0 && ball.y > height){
textDisplay();
//red
fill(255, 102, 102);
text(“Fastball: ” + PitchSpeed + ” MPH”, 120, 570);
}

if(currentImg == thor && sensorValue == 1 && pitchSelector == 1 && ball.y > height){
textDisplay();
//yellow
fill(255, 255, 0);
text(“Curveball: ” + PitchSpeed + ” MPH”, 120, 570);
}

if(currentImg == thor && sensorValue == 1 && pitchSelector == 2 && ball.y > height){
textDisplay();
//cyan
fill(66, 244, 235);
text(“Change-Up: ” + PitchSpeed + ” MPH”, 120, 570);
}

if(currentImg == thor && sensorValue == 1 && pitchSelector == 3 && ball.y > height){
textDisplay();
//purple
fill(236, 179, 255);
text(“Slider: ” + PitchSpeed + ” MPH”, 120, 570);
}

if(currentImg == thor && sensorValue == 1 && pitchSelector == 4 && ball.y > height){
textDisplay();
//green
fill(0, 255, 0);
text(“Sinker: ” + PitchSpeed + ” MPH”, 120, 570);
}
// Darvish
if(currentImg == yu && sensorValue == 2 && pitchSelector == 0 && ball.y> height){
textDisplay();
//red
fill(255, 102, 102);
text(“Fastball: “+ PitchSpeed + ” MPH”, 120, 570);
}

if(currentImg == yu && sensorValue == 2 && pitchSelector == 1 && ball.y>height){
textDisplay();
//yellow
fill(255, 255, 0);
text(“Curveball: ” + PitchSpeed + ” MPH”, 120, 570);
}

if(currentImg == yu && sensorValue == 2 && pitchSelector == 2 && ball.y>height){
textDisplay();
//cyan
fill(66, 244, 235);
text(“Change-Up: “+ PitchSpeed + ” MPH”, 120, 570);
}

if(currentImg == yu && sensorValue == 2 && pitchSelector == 3 && ball.y>height){
textDisplay();
//purple
fill(236, 179, 255);
text(“Slider: “+ PitchSpeed + ” MPH”, 120, 570);
}

if(currentImg == yu && sensorValue == 2 && pitchSelector == 4 && ball.y>height){
textDisplay();
//green
fill(0, 255, 0);
text(“Sinker: ” + PitchSpeed + ” MPH”, 120, 570);
}

if(currentImg == yu && sensorValue == 2 && pitchSelector == 5 && ball.y>height){
textDisplay();
//blue
fill(102, 163, 255);
text(“Cutter: “+ PitchSpeed + ” MPH”, 120, 570);
}

if(currentImg == yu && sensorValue == 2 && pitchSelector == 6 && ball.y>height){
textDisplay();
//orange
fill(255, 165, 0);
text(“Two-Seam: “+ PitchSpeed + ” MPH”, 120, 570);
}
//Rivera
if(currentImg == mo && sensorValue == 3 && pitchSelector == 0 && ball.y>height){
textDisplay();
//red
fill(255, 102, 102);
text(“Fastball: “+ PitchSpeed + ” MPH”, 120, 570);
}

if(currentImg == mo && sensorValue == 3 && pitchSelector == 1 && ball.y>height){
textDisplay();
//blue
fill(102, 163, 255);
text(“Cutter: “+ PitchSpeed + ” MPH”, 120, 570);
}
//Wakefield
if(currentImg == wake && sensorValue == 4 && pitchSelector == 0 && ball.y>height){
textDisplay();
//pink
fill(255, 105, 180);
text(“Knuckleball: “+ PitchSpeed + ” MPH”, 120, 570);
}
}

//Timer Interval Set – run function every 1000millis
function startTimer() {
clockStart = 60;
//console.log(‘timer starting’);
interval = setInterval(timerShmimer, 1000);
}

//Timer subtract and stop when you get to 0
function timerShmimer() {
clockStart–;

if (clockStart === 0) {
clockStart = 0;
clearInterval(interval);
noMatter.play();
}
}

//display for Timer
function printTimerShmimer() {
textSize(40);
fill(255, 200);
textAlign(LEFT);
text(” TIME ” + clockStart, width-400, height-520);
// text(clockStart, width-200, height-525);
}
//SWITCH BETWEEN THE MODES**PITCHERS IN GAME MODE
function keyPressed() {
if (keyCode == UP_ARROW) {
swinging = true;
} else if (keyCode == RIGHT_ARROW) {
gameMode = ‘EASY’;
} else if (keyCode == LEFT_ARROW){
gameMode = ‘HARD’;
} else if (keyCode == DOWN_ARROW){
gameMode = ‘GAME’;
}

if (keyCode == ENTER) {
if (currentImg == kershaw) {
sensorValue = 1;
currentImg = thor;
} else if (currentImg == thor) {
sensorValue = 2;
currentImg = yu;
} else if (currentImg == yu) {
sensorValue = 4;
currentImg = wake;
} else if (currentImg == wake) {
sensorValue = 3;
currentImg = mo;
} else if (currentImg == mo) {
sensorValue =5;
currentImg = kershaw;
}
}
return false;

}

//swings the bat upon click
function mousePressed() {
// console.log(“mouse pressed”);
swinging = true;
}

function keyPressed() {
if (keyCode == UP_ARROW) {
gameMode = ‘MENU’;
} else if (keyCode == RIGHT_ARROW) {
gameMode = ‘EASY’;
} else if (keyCode == LEFT_ARROW){
gameMode = ‘HARD’;
} else if (keyCode == DOWN_ARROW){
gameMode = ‘GAME’;
}

if (keyCode == ENTER) {
if (currentImg == kershaw) {
sensorValue = 1;
currentImg = thor;
} else if (currentImg == thor) {
sensorValue = 2;
currentImg = yu;
} else if (currentImg == yu) {
sensorValue = 4;
currentImg = wake;
} else if (currentImg == wake) {
sensorValue = 3;
currentImg = mo;
} else if (currentImg == mo) {
sensorValue =5;
currentImg = kershaw;
}
}
return false;

}

Virtual Batting Cage Updates

img_7512

We’ve made a lot of progress in the past couple weeks on our project, mostly in terms of Fabrication and computing. We’ve constructed a helmet equipped with two buttons – one to toggle between pitchers and one to take you to the home screen. The purpose of the pitcher button – located on the  brim of the helmet – is to simulate what a hitter may do physically while at the plate. While the .gif below is meant as a comedic exaggeration, it’s not uncommon for a batter to touch the brim of his helmet before taking a pitch; there may be some valuable tar there to make his hands stick to his bat better.

We’ve also constructed a place for the batter to stand when they are taking their ‘at-bat’. The next step for this will be to integrate FSR’s into the home plate. We would also like to signal where the batter should stand.

img_0541img_0542img_0550-1img_0547img_0558img_0560fullsizerender

In terms of the coding, we are making some real great strides as well. Here is a sketch showing what the final background will look like:

And here is a video showing what the final code will look like in terms of pitchers.

Finally there is a preview of what this will look like when this is all tied together.

The Virtual Batting Cage

“Baseball is dull only to dull minds”

I am a baseball fan. Have been since I was a little kid and will likely be till the day I die. To me the sport transcends the physical space it is played on and enters into a narrative and symbolic realm. When you tend to be vocal about baseball like I am, you hear a lot of rebukes: “How hard could it be?” “Why are the players so fat?” “It’s so boring.” Well, to quote the great Red Barber, “Baseball is dull only to dull minds” and I guess I intend to do some sharpening. My ICM finale will attempt to educate users about baseball by having them play the sport themselves. I hope to show them the nuance, the beauty and the difficulty of the sport both visually and physically.
I know a good amount about baseball, which is to say I know about…oh, let’s say 30% of what baseball has to teach. One area that I struggle with is pitch recognition. For those unfamiliar, a pitcher has a certain arsenal with which he throws i.e. a fastball, a changeup, a curveball and a slider. If I were to describe these pitches to you they would sound very different but when they are moving at 90+ MPH, they’re hard to tell the difference. How can I create something that helps pitch recognition but isn’t just me sitting down at a screen and watching baseball highlights?

“Baseball is ninety percent mental and the other half is physical”


Over the summer I started working for a baseball website that does exactly what I am looking to do. I guess I was sort of curious as to how I could make this visual experience a more interactive one. For my PComp Midterm, I took the following sketch and replaced the mouse-pressed bat with an actual physical bat but this was just the beginning. What I aim to do with my ICM final is to make this a full-fledged experience. There will be a home plate that is essentially a trigger for three different modes. If you tap on the green part of the plate, the p5 sketch will throw fastballs right down the middle; this will be “Easy Mode”. If you tap on the yellow part of the plate, there will be a “Hard Mode” that features more challenging pitches like curveballs and sliders. If you press the red part “Game Mode”, an image will appear in the top left hand corner of the sketch featuring a pitcher who you will face off against.
Due to the fact that this is both a PComp and an ICM final, I’ve spent a bit more time focusing on the physical elements first as I feel that it will dictate what the ICM final ends up looking like. Truth be told though, it wasn’t until I play test the PComp idea that I got a lot of great feedback on what the ICM sketch should incorporate. Below is a tentative sketch as to what the screen will look during “Game Mode”.
img_7388
As you can see, there’s a mound and a ball being thrown towards you. There’s a batter’s box and a home plate, which will resemble what the user is actually standing on: a grass batters box next to a home plate. In the top left hand corner will be the face of the pitcher you are facing off against. Below him will be his arsenal. In the center of the screen there will be a scoreboard keeping track of how much time you have left to accrue hits and a hit counter.

Code

Luckily, a big part of the actual code is done due to my midterm, but there is still a lot left to accomplish. I need to create my own JSON file with various pieces of data from the pitchers we want to incorporate into the sketch. I need to figure out a way to map that data so that it appears accurately and realistically into the sketch too. After that, we can work on the other, more aesthetic features. Work has already begun on creating a button that can switch between different pitchers and is featured below (code here).

More?

As of now, there are still a lot of things that can be added and subtracted from the experience. I’m interested in providing as much information as possible while maintaining clarity in the sketch. The last thing I would want would be for the user to be overloaded with information. I would like to provide just enough for them to develop a genuine curiosity about baseball so that they might pursue an interest in it in the future.

The Future   

Ultimately, I would love to take this an put it into an even more immersive 3D experience. I feel like you’ll be able to get a good understanding of pitch recognition on a 2D plain, but you won’t be able to fully get it until you experience it in 3D.

Update!

Since last week, there have been a lot of strides made, here are a few of them:

Frequency.

The particular sketch that you are looking at is not only representative of the arsenal that Noah “Thor” Syndergaard threw in the 2016 season but also represents how frequently he threw said pitch:

Stadium and Scoreboard

This sketch shows a close resemblance to what the final product will look like. The pitchers will be able to be rotated (here it is using the keypressed function but in the final you will press a button located on the helmet (see video)), and a scoreboard will tally how many hits you’ve gathered.

Button 

A very cranky girlfriend uses the button function

Genre and p5

So for this assignment, I wanted to play around with the sound library in p5 by visualizing different genres on my bass. I was curious if there was any visible difference between funk and classical or rock and something more harmonic when the notes were given a form. I’m curious to see what happens if I play a p5 sketch before I play the video of me with the bass to see if people can guess what genre this is. Unfortunately, the audio that I got from my Mac speakers is… nothing short of awful. But it’s mostly there to prove that what I am playing is what is occurring in the sketch. The code is at the very bottom of the sketch. 

var song;
var fft;
var button;
var mic;

var volhistory = [];

function toggleSong() {
background(255);
}

function setup() {
createCanvas(400, 400);
mic = new p5.AudioIn();
mic.start();
angleMode(DEGREES);
button = createButton(‘toggle’);
button.mousePressed(toggleSong);
//song.play();
fft = new p5.FFT();
fft.setInput(mic);
}

function draw() {
// background(0);
var spectrum = fft.analyze();
var vol = mic.getLevel();
stroke(random(255), random(255), random(255));
for (var i=0; i var amp = spectrum[i];
var y = map(amp, 0, 256, height, 0);
ellipse(i, y, vol*200, vol*200);
}
// volhistory.push(vol);
stroke(255);
noFill();
}
// translate(width / 2, height / 2);
// beginShape();
// for (var i = 0; i < 360; i++) {
// var r = map(volhistory[i], 0, 1, 10, 100);
// var x = r * cos(i);
// var y = r * sin(i);
// vertex(x, y);
// }
// endShape();

// if (volhistory.length > 360) {
// volhistory.splice(0, 1);
// }
// //ellipse(100, 100, 200, vol * 200);
// }

BABIP Comparisons

The below is an example and is much better viewed in full screen

 

So for this assignment I knew that I wanted to do something with baseball data. Luckily for me, baseball data is plentiful and easy to access; my go to is Fangraphs.

It’s easy to visualize baseball data but difficult to do so in a way that can be revealing. Anyone can great a histogram of all the HR’s that have been hit in June or by left handed batters, but that data visualization doesn’t really serve to reveal anything. I was curious in how the data can inform me of something that I didn’t know before.

In the past ten years or so, or definitely since the release of the novel and movie Moneyball, the baseball world has been obsessed with sabermetrics which is the application of statistical analysis to baseball. One of the key statistics to come out of the sabermetrics movement has been BABIP which can be described in depth if you click the link in the sketch. For better or worse though, it’s essentially a comparative statistic that reveals how lucky a batter has been in a given stretch. There is a career BABIP that is only created after 1,000 at-bats, and a players more recent numbers are compared to his career numbers to see if he’s getting luckier than usual or not.

This sketch is the beginning of what I hope to be a bigger project which is generating my own Fantasy Baseball draft software. I’d love for users to be able to have these sort of visual comparisons for a lot more fields than just BABIP.

Synthesis Day and Sketch

 

Synth Day

To be honest, this wasn’t too much of a struggle for me. Or the only moments in which there was a struggle was the debugging… I guess that’s always the case though. I didn’t have trouble conceptually. It was pretty rudimentary to understand that you’re replacing a variable with a sensor value and that sensor is going to have an effect on your sketch. What was difficult, and what I would like to understand a bit more of, is what exactly is happening in all of that code that we virtually copy and paste on synthesis day. That aside, the day was enjoyable for the sheer amount of possibilities it opened up including for the baseball sketch I can’t seem to get away from.

In terms of that sketch, my partner Swapna and I thought it would be cool to “become” the pitcher in my baseball sketch. Rather than have the ball automatically redraw itself once it left the frame, it would be cool to determine via the press of a button when the baseball would be thrown. Adding that definitely makes the sketch more of a game just a really…boring one. However it’s a start. Perhaps now I can introduce four different buttons each corresponding to a different pitch; button one is a fastball, button two a curve etc. My P-Comp – and hopefully ICM – midterm is going to revolve around a lot of this stuff. DO YOU KNOW ANYONE AT MLB, DANO?!

SKETCH

 

I admit: I am having some problems again with ICM. It’s sort of like , you said in class, the plateau is gone and the hill is in the midst of being climbed. Once again, I understand the concepts. I know what a constructor function is and how they work logically. However, I am having a lot of difficulty applying the concept to a sketch from scratch. For my sketch this week, I took some code that was in the Coding Rainbow video and made it my own a bit which is fine. I understand that’s a viable way to learn. But what I’d love to do, and what I am still trying to work on is making this from the get-go. If I don’t understand a bit better by end of week, I see some office hours in our future. NO SPORTS TALK ALLOWED.

 

CODE:

var bubbles = [];

function preload () {
img = loadImage(“Coaster.jpg”);
}

function setup() {
createCanvas(600, 400);
img.loadPixels();
for (var i = 0; i < 20; i++) {
bubbles[i] = new Bubble();
}
}

function mouseDragged () {
bubbles.push(new Bubble(mouseX, mouseY));
}

function draw() {
background(255);
image(img,0,0,600,400);
for (var i = 0; i < bubbles.length; i++) {
bubbles[i].move();
bubbles[i].display();
}

if (bubbles.length > 10) {
bubbles.splice(0,1);
}
}
function Bubble(x,y) {
this.x = x;
this.y = y;

this.display = function() {
stroke(255);
fill(0);
rect(this.x,this.y-24, 25,25);
stroke(10);
strokeWeight(2);
fill(255);
ellipse(this.x+24,this.y,12,12);
ellipse(this.x, this.y, 12, 12);

};

this.move = function() {
this.x = this.x + random(-0.5, 0.5);
this.y = this.y + random(-0.5, 0.5);

};
}

 

My First Baseball Game

Well it’s certainly getting to that point where ICM is a challenge. I think the difficulty I’m having with it is that I am just overwhelmingly anxious about it yet when I try to pinpoint what specifically I am anxious about, I can’t. I was explaining it to my friend Patrick this way: when I eat lunch I eat my sandwich, then my chips, then my dessert. I don’t understand those people who eat chips while they’re eating those sandwich and I have a severe disdain for those monsters who put chips ON their sandwich and that’s what coding is. I understand for loops and if statements and Boolean variables independent from one another but when you put all of them in a sandwich? Uh-uh.

I decided the best way to deal with my anxiety about all of this was to start simple…keep it rudimentary, ya know. So that explains my first sketch. I originally wanted it to be people watching TV and when you clicked on the television, it turned on to show Dan-O’s face. I was getting way too stressed and not getting to my other assignments so I decided to simplify it. Instead of focusing on mousePressed or anything like that, I just kept it simple with if statements. I felt pretty confident about inserting images so I decided to put Dan-O’s face in there to try and somewhat keep with my theme.

My second sketch was one I was really proud of and one that…sort of let things click in my mind. I was taking a break from ICM and watching the end of the Orioles game. It was the top of the 9th, man on first against a division rival who we needed to beat to stay alive in the playoff race. My favorite Oriole, Hyun Soo Kim, came up to bat with a man on first down by a run, and then BAM a two run shot to right center field. I decided I had to commemorate this moment in code. I started with an image behind home plate. I inserted some variables – something I felt shaky doing – and figured out logically how to make what I wanted to make. I threw in some if statements and as I was doing so was like….man, I can make a game of my own. So I inserted a mousePressed function that made the ball appear to be hit when the mouse was clicked. To make it more difficult, I decreased the range in which you could “swing” (read: click). I also figured I needed to add sound so I used the reference library but couldn’t get it quite right. Thanks to Matt and Kat, I was able to realize my issue: I was doing function preload twice.

For the last sketch…it was sort of a failure but I figured it was a good learning experience. I used a for loop to set up my images but I want them to be able to switch places (pink on bottom, blue on top…how risqué), when mousePressed is clicked but I can’t figure out how to do it for the life of me.

Stargate

I feel like my post this week is…sort of constantly in a state of flux. I used this past week’s lessons as a chance to have some fun and play around. I’m sure in like a few hours I won’t even remember what I uploaded. That’s not to say I didn’t take this seriously, I did, I’m just having so much fun exploring that I uploaded what made me laugh the most.

2001: A p5.js Odyssey

Computation & You!

How does computation apply to my interests? Well that’s….hm. The word computation in and of itself is one that I just struggle to wrap my head around. It’s like an idiom that I know in context but I struggle with in practice, sort of like, “A bird in the hand is worth two in the bush”. Well, I guess I don’t know what that really means either. Yet when I think of my interests – acting, sports, videogames, music – I can think of many ways in which computation applies. I would love to peel back the curtain in front of video games and see how they’re made, would love to sift through the bevy of data baseball annually spews out and make firm sense of it, would love to make an algorithm that shows just why Nina Simone gets me the way she does.

I think, above all though, computation applies to my interests because it provides an exciting new framework in which story can be told. Videogames, baseball, acting, it all comes down to story, doesn’t it? I’m reading this book by Jaron Lanier right now and in it he introduced me to the work of Karl Popper. Popper posits (lovely alliteration there; hope you said it out loud like I did) that science never achieves absolute, eternal truth, but instead gets closer and closer to truth by disqualifying false ideas. Computation provides a means to achieve a new truth in story and while that doesn’t disqualify other storytelling mediums, it does provide an exciting new tool of expression.

Karl Popper learning to code

My Sketch

 

My image is based off of a poster for the film 2001 A Space Odyssey – a favorite of mine. Originally, I was going to do my best to create the exact same image but I wanted a little bit more of a challenge so I decided to replace the walking stickman with a version of Hal based on a different 2001 poster. Eager to put a little bit of my own touch on it, I thought it would be cool to create the illusion of planets aligning above the obelisk. This is mostly where I ran into trouble.

Originally, I wanted a few of the planets to appear as if they were being eclipsed but I couldn’t figure out how to properly overlay two circles on top of one another to create that illusion. A classmate of mine, Michael Kriphack, gave me a quick and helpful lesson, reinforcing the order of operations. The issue ultimately ended up being resolved thanks to the push() and pop() functions and a great web editor that made the guessing game of where things should go far less laborious than it was with the downloadable p5 editor. In an ideal world, I would have loved for the planets to start off farther left and orbit around the center of the image, coming to a rest above the obelisk. Despite a few Google searches and some hard digging through the p5.Js reference library, I couldn’t figure out how to do this. Below is my code.

function setup() {
createCanvas(400, 400);
background(0);

//smallplanet
strokeWeight(3);
fill(250,250,0);
ellipse(196,28,75,45);

//mediumplanet
fill(250,200,0);
ellipse(198,50,90,65);

//largeplanet
fill(250,100,0);
ellipse(200,75,100,75);

//MainRectangle
fill(255);
rect(137.5,75,125,275);

//TopRectangle
strokeWeight(3);
rect(150,90,100,15);

//centercircle
fill(20,0,0);
ellipse(200,230,100,100);

fill(255,0,0);
ellipse(200,230,95,95);

fill(255,75,0);
ellipse(200,230,70,70);

fill(255,125,0);
ellipse(200,230,50,50);

fill(255,155,0);
ellipse(200,230,30,30);

fill(255,75,0);
ellipse(200,230,20,20);

fill(255,75,0);
ellipse(200,230,15,15);

//bottom line
strokeWeight(5);
line(139,310,260,310);

}

function draw() {

}