Butcher’s Crossing and Lab Documentation

John Williams’ Butchers Crossing is a novel I have a long history with. 

I first read the book in 2010 and became obsessed with it. The chaotic way nature was represented was unlike any other western I had ever read or seen before. Williams’ denial of Emerson’s idealism and descriptions of the protagonist Will as he came face to face with futility had me quite enamored. So much so that I started a long process of trying to acquire the rights to make the book a film. I’ll spare the details but nothing ever became of my attempts and two years ago I had to quit the conquest. 

When we were given the opportunity to create an environment in Unreal, my mood board was about a preconceived idea about baseball. That was until Butcher’s Crossing came back into my brain and I couldn’t resist the urge to have another go with the text. 

The atmosphere I was looking to represent was two-fold. I wanted one that had some warm colors, that appeared as if it was occurring at dawn to connote a sense of newness. Unfortunately, my limitations with the software presented me from adorning the landscape with other features – different sorts of foliage, more muted colors, a more craggy “cliff”. I wanted this first part to convey a sense of stumbling onto something untouched and private.

My other atmospheric goal – and one in which I feel I didn’t succeed so well – was to convey a slight touch of danger; some sort of harbinger of ill-will. I put a light fog over the scene and sprinkled in some sharp rocks in an attempt to convey this. I also made sure some of the lake was touched by the sun to give it a sort of “on-fire” look.

At the end of the day, while I would like to make a few changes – a slightly more ominous atmosphere, a better looking horse, a few cowboys – I was really happy with what I was able to create with just a few days of UE4 under my belt. 

As a result of using source material, I have three characters that have already been created and fleshed out for me. They are:

Will: A 23 year-old Harvard drop out who has ventured out to “find himself in the great West”.

Miller: A surly hunter who is eager for wealth.

Charley Hoge: A one-armed veteran and companion of Miller’s. 

Fred Schneider: The stubborn voice of dissent. 

Part Two: Lab

This past Saturday Izzy, Ran, Spencer, Manning, Teresa and I got together to gather some movement data. 

Izzy and I were a little early so we calibrated the space without any issue and began to suit up.

Manning, Ran and Teresa handled most of the software while sporadically aiding Spencer in getting all of the sensors on Izzy and I. 

Once we were all suited up and skeletons had been made of us, Izzy and I began running though various movements. 

We had conversations to get natural hand gestures, we climbed on ladders, we rode pretend horses (really excited to see that one), and ‘went for a swim’. We did some flying, some dancing and some crawling around in the sewers (per Teresa’s request). 

Each member of the group made known what specific gestures they needed (Manning needed some jumping, I needed the horseback, etc), we saved and stored the data and went about our ways. I think I speak for all of us when I say we’re all eager to see what it looks like and integrate it into our environments!

Nature of Code Final

For my project, I wanted to create a simulation to see if a home run hit in one major league ballpark would leave another ballpark. At the beginning, my expectations were really lofty in terms of what factors I wanted to take into account. And by so lofty I meant: all of them. I wanted to take into account, humidity, air resistance, wind, exit velocity, distance travelled, etc. After attempting to do this, I figured it would be best if I started a bit simpler by taking weather out of it.

I started by extracting only baseball factors such as distance, exit velocity and launch angle. I used ESPN’s hit tracker – which keeps track of every single home run each season – as a reference for all of this information. I then created some code where I could begin applying forces to things. Due to how many factors needed to be taken into account plus the fact that pixels don’t really measure distance, there were certain constants that I needed to take into account. For example, gravity was always set to 0.2 and acceleration was always set to 5. As I begin to advance this project and bring in different factors, these things will change but keeping those two forces constant’s allowed me to advance my project.

I’ll get more into how I created the code below, but for now let’s take a look at the code in action.

This was the longest home run that was hit in 2016 and it was a good place to start. I knew that if I could map this, I would have the highest threshold for homeruns considering none travelled further than this. It was this home run that let me test if my code was working and in the end, it ended up being successful as you can see below. 

Now all I needed to do was test to see if a home run hit in one park would work in a different park. 

This is Manny Machado’s grand slam that he hit on April 28th. If we look at the code first we get the sense that it barely left the yard. Let’s take a look to see if that’s true. 

It is! Now let’s take a look to see if that same hit would’ve left the yard in Comerica Park. 

It wouldn’t have. The sketch works!

Let’s dive a bit deeper though. What can we tell about the data before we see the home run. 

If we look at Alex Gordon’s Home Run in the sketch, we get the feeling that it too barely left the park in CF. 

I am text block. Click edit button to change this text. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut elit tellus, luctus nec ullamcorper mattis, pulvinar dapibus leo.

Once again, the video shows this to be true.

How about a home run that wasn’t hit to center field? Can we use to sketch to see if it wasn’t hit to right or left field but hit to center instead, it still would’ve been a home run?

Let’s take a look at Chris Davis’ home run against the Blue Jays. It left the yard in right field and just barely made it over. 

So if that same hit was directed towards center field, would it have been a home run?

Nope, it looks like it would’ve come up just short. 

Forces in Baseball

Title:

Forces in Baseball

What is it:

A physics engine that looks to simulate the effects of various aspects of air density – humidity, temperature, altitude – and wind on a baseball.

Visual Mock-Up:

Sketch:

Status Update:

As I’ve started to explore this assignment I’ve realized how incredibly vast an undertaking it is. I feel like the best way to go about doing this is to reverse engineer a home run to see what factors I need to take into account, and how to take them into account going forward. So, I’ve decided to start with what was – by StatCast’s measurements – the HR that had the highest projected distance in 2016: Giancarlo Stanton’s solo shot against the Colorado Rockies on August 8th, 2016.

Here are things that I know about the home run:

  • Distance: 504 feet
  • Exit Velocity: 115.8
  • Launch Angle: 18.3
  • Height:72.3 Feet
  • Temperature: 75 degrees
  • Wind: 13.8 MPH ENE
  • Barometric Pressure: 29.85 Hg
  • Average Humidity: 55%
  • Weight of baseball: 145 g or 0.31967 lbs
  • Hangtime: 5.4 seconds

 

Statcast data: http://m.mlb.com/statcast/leaderboard#hr-distance

Weather features found: https://www.wunderground.com/history/airport/KDEN/2016/8/6/DailyHistory.html?req_city=&req_state=&req_statename=&reqdb.zip=&reqdb.magic=&reqdb.wmo=&MR=1

So how do I put these things in code? I know how to create different forces and how to apply them to different objects but what is the best way to proceed. I imagine it’s by starting with the ball at home plate with no forces applying to them. Then changing velocity and acceleration to launch angle and bat speed as those are two determining factors as to how far a home run is hit. Then applying all of the other aforementioned forces. I have difficulty weighting the forces though: which has more of an impact. Also, how do I determine the mapping of exit velocity? Find the highest and lowest measurement of 2016?

 

Everything below is personalized questions and notes so you don’t need to read further if you don’t like.

 

Questions:

When you’re applying a force, you’re essentially changing acceleration, correct? Because acceleration = that new force. This doesn’t negate the acceleration that’s already in there, correct?

The forces that I need to put into a sketch all fall under categories that effect air density: temperature, humidity, and altitude. The higher the altitude, the lower the air density, the further the ball flies.

How do I make a force effect the entire sketch? Like I need air density to be a blanket that slows down the entire sketch.

Is the best thing than to recreate a home run using the data that we have? Like Stanton hit a HR in Coors that went a projected 504 feet, with an exit velo of 115.8, a launch angle of 18.3. The inning was the top of the 5th so the temperature was about 75 degrees, wind was about 14 mph and was blowing NE.

Check out Alan Nathan, physics professor

5 things that can affect a baseball game from this accuweather article:

  1. Air temperature can change a baseball’s trajectory. A ball coming off the bat at 100 mph with a 30 degree launch angle will travel about 2.5 feet less in 60 degree weather as compared to 70 degree weather. That’s not a big difference in this context but games in April are played in 40 degree weather while a game in the same ballpark in August can be played in 90 degree weather. That’s a 10 feet difference which can easily be the difference between a fly ball and a home run.
  2. Air density. Look at Coors Field in Colorado which is a mile above sea level and therefore has less air density than your average baseball stadium. The balls used in this stadium at stored in a humidor at a constant 50% relative humidity and at 70 degrees to help change the coefficient restitution or bounciness of the ball. The ball becomes a bit heavier and the ball doesn’t come off the bat as fast and doesn’t quite travel as far. What is the average mass of a baseball?(it’s 145 grams).Due to the density of the air, breaking balls like Curveballs and Sliders will not break as much in less dense air. Pitchers perform better at Coors when it’s colder because the ball will spin more.
  3. High and low temperatures If you are sweating a lot, it’s harder to feel the ball and get a good grip on it. Same thing if it’s too cold, the batter will lose feeling in his fingers.
  4. Cloud Coverage A bright blue sky – or high sky – can cause problems with depth where as clouds can cover up the ball.
  5. Wind Some pitchers that rely on movement from their breaking pitches prefer to have the wind in their face, they think it will add movement to their pitches while some feel the opposite.

Notes from Alan Nathan’s “You Can Observe A Lot By Watching” 

  • Quotes from The Physics of Baseball by Robert K. Adair
    • “Our goal is not to reform the game but to understand it”
    • “The physics of baseball isn’t rocket science. It’s much harder”
  • The bat will slow down after contact is made with the pitch
  • The bat is not a rigid object, and the further away from the “sweet spot” the hit is, the more the bat will vibrate or even splinter in half.
  • Queue up to 18:19 to see the different vibrations of a bat
  • The sweet spot is the node on a bat where vibration would be smallest. That’s why it hurts a bit when you get a hit o the sweet spot. At the sweet spot vibrations are minimized.
  • The manner at which a bat breaks depends on where the impact occurs.  If the impact occurs on the end of the bat then it bends towards the pitcher and that’s the way it breaks. Compare that to when the bat breaks closer to the barrel and it cracks towards the catcher.
  • The ball doesn’t know the end of the bat is even there because the impact takes 1/1000 of a second.
  • The batter could just let go of the bat just prior before making contact with the ball and it wouldn’t make a difference to what happens with the ball. This means: if a bat is swung at a certain speed, it doesn’t matter who is holding that bat. 
  • Look at Todd Frazier’s 5/30/12 home run. Ball hit 375 feet and the bat was barely in his hands. Grip doesn’t matter.

Nasty, Nasty, Nasty

  • Ball swerves in direction that leading edge is turning
  • Pitch F/X. Created by Marv White
    • two video cameras @ 60 FPS set up in each ballpark above first base line and above home plate
    • Tracks every pitch in every ballpark
  • “Hitting is fifty percent above the shoulders” — Ted Williams & “Hitting is timing; pitching is upsetting timing” — Warren Spahn
  • Control: the ability to throw strikes. Command: the ability to throw well located strikes
  • Movement: how much a pitch deviates from a straight line.
  • For Jon Lester’s 4 seam there is back spin which means the force is actually moving upward, it drops because of gravity but the force due to the spin is upwards. It also breaks slightly to the side, bearing in to a LHH.
  • A knuckleball has no spin whatsoever, it has to do with how the seams are oriented. If the ball is barely spinning or spinning slowly, the seams have the most effect on the ball. If the ball were perfectly smooth there would be no knuckleball effect.  Small changes in how you release that ball can cause big changes in what happens to the ball when it gets to home plate.

Three For the Price of One

  • Backspin on the ball because the ball slides along the surface of the bat temporarily and the friction between the ball and the bat acts in the opposite direction
  • If a batter is out in front of a ball it will move towards left field if he is a right handed batter and towards right field if he is a left handed batter. Ball begins to spin counter clockwise.
  • Live drives in the outfield curve towards the foul pole

Building a worse mouse trap

  •  When a ball hits a wooden bat, the ball’s surface will change but the wooden bats won’t. All of the energy of the collision is taken up by the ball when it squashes, not the wooden bat. That’s super inefficient.
  • When you get a hit with the aluminum bat something called the trampoline effect occurs.  Result of trampoline effect: less energy lost in the bat.
  • Ball bat coefficient of restitution. When it’s large the performance of the bat is better when it’s small the performance of the bat is worse. BBCOR of a wood bat is about 0.5. You want to regulate the performance of the bat’s you regulate the BBCOR.

Extra Innings: The Carry of a Fly Ball

  • Three pieces of information about every home run:
    • Precise landing point of the home run
    • The time it takes to travel from contact to landing
    • And initial speed and angle
  • With that information you can do…
  • What does it mean when you say the ball “carries well”. If you look at the actual distance the ball traveled compared to how it would travel in a vacuum, if there were no air effects and only gravity it would travel one distance and with air effects it would travel another
  • If you take the same initial velocity of a home run and say how far would this go if there were no air, gravity but no air, it would travel 571 feet. With air effects it goes about 397. 397/571 is 0.695. So 0.695 is the carry.
  • Look up Alan Nathan’s Normalized Carry done in 2009
  • The ball carries very well in Denver but doesn’t carry in Cleveland.
  • Denver is a mile above sea level and the air density is roughly 80% of what it is at sea level so the bar carries further because there is less air. A ball that would travel 400 feet would travel 425 in Denver.
  • When the temperature is high, the air density is less and the ball carries further.

Polar Rectangles

Between the particle systems and oscillations there was a lot of content that was learned, each of which I was curious to explore. When making pendulums, I wanted to make something that was like a Processing version of Miley Cyrus’s “Wrecking Ball”. The Particles systems reminded me of volcanoes and I wanted to play with color. Then I did the polar coordinates video and ended up experimenting with different variables for the better part of an hour. I put “The Who” on and just sort of went to town and got the following.  

It doesn’t really look like it but this was my first foray into multi-dimensionality. I’m still a bit confused on how to incorporate the Z axis but these are the next steps I would like to be taking. 

Using the Force

For this weeks assignment, I wanted to see if I could create a simple game using different forces. I’ll admit, I spent a bunch of time on video 2.2. Not because it was particularly difficult conceptually but because I had so much fun applying different forces to one object. To me, it immediately took the form of a ball that people were trying to keep balanced in the air. Then it resembled a balloon floating away, then it oddly brought me back to a game I used to play in middle school and high school that I haven’t thought about for YEARS called Bubble Trouble. It was then I realized, that this week I should focus on actually turning this into a rudimentary idea.

I will say my original idea was to have to faces on the screen, one on the left and one on the right. When you pressed the right button the left face would exert a wind force and push a ball towards the right face who would then push it back towards the left face with a wind force of its own. Then I thought maybe it would be cool to make the ball in the center into a flower, and as wind was exerted it’s pedals would fall off but I couldn’t figure out how to illustrate it’s stem and how THAT would bend with the flower.

I eventually decided to focus on a game where the point was to exert as many different forces on the ball as possible. That for some reason began to resemble a sheep herder keeping his sheep in order and not letting them run off. That’s how I came to this:

 

The code for the sketch is in the google drive located here

Project Development Studio

MLBAR

Dream: I am interested in how I can use new technology to enhance a fans live experience at a Major League Baseball game. I want to be able to create something that will be all inclusive: something that both informs the newcomer and engages the baseball fanatic. The ideas implemented should be malleable enough to not just enhance the experience of a baseball game but of all live events.

Vision: The tech would have a lot of features, all of them stemming from your mobile device. One crucial foundation to keep in mind through all of this: the physicality of the experience is one that separates the body from the tech in a realistic fashion. The mobile device will not be covering the eyes as is common with a VR experience. Instead, the user will keep the phone at arms length –  as if they are taking a picture – as the AR experience happens. It is crucial that the user isn’t thrown into a virtual reality and that reality exists around them as things are augmented. Now, for the experience:

You and your friend decide to take a road trip to see your favorite team the Baltimore Orioles play the Cleveland Indians at Progressive Field in Ohio. You get your tickets and get to the stadium a bit early to watch some batting practice. Your friend asks you who is in the starting lineup tonight. You turn your camera on, point your phone to the field and from the grass emerges a graphic with the two starting lineups. “Oh, he’s got Manny Machado batting second? Doesn’t he usually bat third?” your friend asks. You highlight Manny Machado’s name and all of his statistics appear. “Nah, he usually bats second.”

“How does he do against this pitcher?” 

You pull up a highlight of what happened the last time Manny Machado went up againsst Danny Salazar. It shows him striking out.

“Not so well.”

You sit down and the game begins. After an inning or two, you start to get hungry. “What’s this stadium got by way of food?” your friend asks. You hold your phone up to the stadium and an array of concessions pop up. Above a few of them there is a small star that notates which concession Indians fans feel is a must have, below that there is a review and under that, a timer which indicates how long the line is for that particular concession.

“This place called Melt Bar and Grill has something called the Parmageddon that’s supposed to be great. The line is like 10 minutes but it just won some award for ‘Best Ballpark Food.'”

“Sounds good, mind if I use the restroom before we go?”

You turn your phone around to look for the nearest restroom. Several icons pop up to show you where they are located.

“There’s one close to the concession stand but there’s a five minute wait; the one right outside your section has a one minute wait.”

You get your food, return to your seats and settle in to watch the rest of the game. It’s now the bottom of the 7th. The Orioles are up 4 – 3 but their starter Kevin Gausman has just given up a two out double with Edwin Encarnacion on deck. 

“They should bring in Brad Brach,” says you friend. 

“No way, let him finish the inning.”

You open your phone and point it to the scoreboard. A poll appears: “What should the manager do: ‘Bring in Brad Brach”, “Keep Gausman in”, “Intentionally walk Encarnacion”. 

Your friend votes for the first option and you vote the second. The poll fills up and it turns out 70% of the fans who voted agree with your friend.

The game ends (the Orioles won) and you head back to your hotel room with your friend.

“Man, that was some home run Manny Machado hit, huh?”

“Yea,” you say, “let’s see it again”. You open your app and displayed in AR in your hotel room is that home run Manny Machado hit two hours ago. 

Goal: Create a mobile AR app that enhances the viewing experience of a live event. Give the app as much functionality as possible in a one semester span. In the meantime, create a video that shows what the app looks like when it is used optimally. 

Plan: 

Midterm: Pitch Video

Final: MVP app that includes all functions of the app but with a select few being able to be used. 

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

The above video is from a midterm that was the first step towards creating an interactive batting cage that allows users to face off with real pitchers from Major League Baseball. The midterm featured a hollowed out plastic bat fitted with an accelerometer along with an Arduino Uno and is programed so that when a certain location is reached, a swing occurs in a p5 sketch.  The p5 sketch itself is a rudimentary batting practice where a “fastball” is thrown at the same speed every few seconds.

While this was certainly enjoyable, it definitely was a bit easy. The next step is to take actual data from five separate pitchers – Noah Syndergaard, Clayton Kershaw, Yu Darvish, Mariano Rivera and Tim Wakefield – and code it into the sketch. Rather than use all of the data made available though – my source for all of this is Fangraphs –  I boiled it down to what was essential for the sketch: the pitcher’s arsenal, the max/min velocity for each speed, the frequency which it was thrown and it’s xMov. The bat will also be fitted with a vibrating motor disc and haptic motor controller so that when the user gets a hit the bat will vibrate depending on if they made good contact or not. Let’s say the user is having too much difficulty hitting Clayton Kershaw. They can press a button located on the batting helmet they will be wearing to change pitchers. Let’s say the best the Show has to offer is too difficult for them. They can step on home plate to change game modes. Ultimately, when this is all said and done, I would love to take the final and make it a VR experience.

If you’re interested in seeing the final first hand it will be on display at the ITP Winter Show on December 18th and 19th and you can check my progress with it here.

P.S. In case you’re thinking to yourself: “Rivera? Wakefield?!” I’ve got two friends working on the project who are Yankees and Red Sox fans and while I am a die-hard Orioles fan, I couldn’t bring myself to put Dylan Bundy or Mike Mussina or like…Kevin Brown – can you believe he was an Oriole? – into the sketch. Though a part of me wanted to put Arrieta in there and just have him throw his cutter as a big middle finger to the Orioles pitching staff.

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.