Week 7: Midterm! Halloween Dance Revolution!

For our midterm project, I was paired with Mingxi Xu. We wanted to make a version of Dance Dance Revolution that was more based on player input than pre-programmed dance moves. The idea was that one player would dance, and then the other player would have to copy the dance moves in order to win. And because our midterm was Halloween themed, we made the game Halloween themed as well. Mingxi made the very cool animation intro in our sketch that you see at the beginning of the above video.

To start, we order some larger (1.5 inch) force sensors to sense our dance moves. In the very early stages of prototyping we used a wire wrapper and some very thin wire to attach the sensors to our breadboard. We put them under a piece of canvas drop cloth we got at the hardware store in order to create a rudimentary dance pad. We wanted to use a drop cloth because it would be easy to paint on later. In the beginning though, we just marked the spot with some tape Xs.

A force sensor attached to thin solid wire using a wire wrapper.

A force sensor attached to thin solid wire using a wire wrapper.

 
Mingxi Xu testing our earliest dance pad prototype.

Mingxi Xu testing our earliest dance pad prototype.

Setting up the sensors was the easy part. Most of our project was spent debugging our P5 sketch ( Here is a link to it). Creating the logic for how the game would work was relatively straightforward, but the biggest stumbling block we faced was performance problems in .p5js. Mingxi really layed the groundwork for our program. Tracking time data is at the heart of our program. Our first prototypes used the frame count to keep track of time, and it worked great at first. Then we realized that if you do any more than four moves or so, the program slows way down and generates a lot of lag. This means that it’s impossible for Player 2 to follow your moves when time is effectively changed when it’s their turn.

So, I met with my ICM teacher, Allison Parrish, who solved our problems in one sentence. “You should use millis,” she said. And that’s what we did. “millis()” is a call in .p5js that keeps track of time since the program began using the computer’s clock in milliseconds. It’s constant, regardless of the program’s performance. Once we plugged it into our sketch, it worked great.

After that we had a million other problems that came up. I can’t even remember half of them now, they were so frequent, and so dumb in hindsight.

There were a lot of dumb mistakes on the Arduino end as well. At one point I swapped out the resistors on my breadboard for LEDs thinking, “This is so great! Now I can visibly see if the sensors are working or not on the breadboard!” Then, the next day we were tirelessly troubleshooting the weird sensor readings we were getting from our FSRs that were fluctuating from 300 to 700 or even 800 endlessly. One of them was especially bad. We were going nuts trying to fix it with Arduino code by constraining the sensor values. Then I remembered, “Oooooohhhh…. It’s because I took the resistors out.” Sure enough, when we plugged the 10K ohm resistors back into the breadboard, the sensor readings returned back to normal. It also makes sense why one of the sensors appeared to have an usually high value — it was the closest to the power source.

The culprit LEDS laying defeated after I removed them in frustration and replaced them with 10K resistors.

The culprit LEDS laying defeated after I removed them in frustration and replaced them with 10K resistors.

 

While we’re talking about sensor data, we went back and forth several times with whether to use our FSRs as digital data or to map them to digital data from analog data. Turns out you can just plug an analog sensor into a digital Arduino pin and it will inherently generate 1 or 0 values, so it does actually work to just plug an analog sensor into digital. However, we didn’t want the sensors to have a “hair trigger,” so we read them as analog and then chilled them out by saying “generate zeroes unless your value goes over 800,” with an “if” statement in our Arduino code. In the end that’s what we ended up using, and it worked pretty damn well.

The sensors generated a four-digit array of data separated by commas as delimiters. We interpreted that data into up, down, left or right values in .p5js. Oh! I almost forgot to mention our yellow button. We added a yellow button at the end that was just a switch in our game’s control flow. This was value 5 of our data array — just a digital switch.

This is our Arduino code for creating digital data from an analog sensor by creating a threshold from analog data. In this case, it’s 800.

This is our Arduino code for creating digital data from an analog sensor by creating a threshold from analog data. In this case, it’s 800.

 

The biggest problem we ran into, as previously stated, was .p5js performance. In the end, we realized that you just shouldn’t load images into P5 and expect the performance to be any good. Originally Mingxi created these nice illustrations that were going to be our arrows for gameplay. When we plugged them into the P5 sketch, the delay was astronomical. So, I recreated his drawings using bezier verteces in P5. It was time consuming, but once we plugged them into the sketch, the performance we infinitely better.

It was also during this time that we finalized our dance pad design. I used my wife, Marina’s, yoga mat folder in half as our dance pad in a nutshell, with the canvas on top and the sensors in between. Then I painted arrows on the canvas and basically put the whole thing together with tape. We also braided some solid wire using a drill and soldered them to the force sensors and hot glued them to avoid any shorts.

All in all, I’d call it a success!

Music credits:

Halloween intro - “Funny Halloween” — royalty-free stock music from Pond5..com
”Crazy” - Gnarls Barkley
”Good Vibrations” - Marky Mark and the Funky Bunch
”Never Gonna Give You Up” - Rick Astley
”Flashlight” - George Clinton and Parliament Funkadelic