Lachlan's avatar@lachlanjc/eduCourses
Physical Computing

Physical Virtual Project

It’s 2032 & there’s a record-setting drought—so drinking water has become scarce & expensive. In this game, the price of water rapidly fluctuates, you have a limited budget, and you need to decide when to buy the water you need to survive, buying 4 liters per day but no more. In the end, there’s no winning: once we’re bidding against each other for human necessities, we’ve collectively lost.

In person, this project came with a physical water bottle controller, which you lift off a magnetic platform to buy water. If you’re visiting online, press the space bar instead.

Game (click View Source for JS code):

Arduino code
int buttonState;
int lastButtonState = HIGH;
unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 50;
void setup() {
Serial.begin(9600);
while(Serial == false){};
pinMode(2, INPUT);
}
void loop() {
int reading = digitalRead(2);
if (reading != lastButtonState) {
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > debounceDelay) {
if (reading != buttonState) {
buttonState = reading;
Serial.println(reading);
if (reading == LOW) {
Serial.println("buy");
}
}
}
lastButtonState = reading;
}

2022-11-08: Playtesting

Playtested the game today! I unwrapped the sensor from the cardboard to improve the reliability of the read switch, at the sacrifice of aesthetics. Here’s Priyanka:

Several themes emerged in my observations/the feedback:

  • UI isn’t clear enough. I explained the concepts of the game verbally, but many players went through several rounds of the game before they understood the elements & how they interact.
  • The interaction I chose—picking up the water bottle—was foreign/strange. Players expected putting the bottle down to execute another action, or that the height of the bottle would correspond to something.
  • The magnetic switch isn’t reliable enough. While choosing an unreliable mechanism was part of the game, having it not work several times in a row because the magnet moved inside the bottle is more frustrating that incisive commentary.
  • Purchasing water, the primary dynamic of the game, didn’t get enough prominence in the UI—it requires focus to notice the drops filling in. A full-screen animation on change, and a more prominent “progress bar” design, would help.
  • I got notes that it’s strange that the budget increases without taking any action for work. This was an intentional choice on my part, as if there was some interaction to do “work” to make money, it needs to have a counter-acting force (such as how the price of water has the counter-acting force of your limited budget), but it’s something to consider.

The audience found it “anxiety-inducing,” “scary,” “nerve-wracking,” “high-concept,” & “addictive” (on the last one, several players returned to play more rounds). None of that was surprising but I’m glad the concept landed. Folks seemed to resonate with the message; though when they articulated it, they focused more on resource conservation, which wasn’t an explicit aspect, it’s logical & nonetheless on-theme.

2022-11-07: Serial killing

Made assorted improvements & bug fixes to the game, including discovering the p5 speech library’s .interrupt = true option, which allows the speaker to interrupt themselves, which was useful for the “game over” announcement. I used p5’s noLoop() to ensure this announcement wouldn’t be read aloud repeatedly.

But the main problem persisted: an unreliable serial connection. I restarted my Mac, and the serial connection magically began working again. After restarting the browser or reloading the page, though, it stopped working: it would connect to the Arduino port, but the serialEvent() function would never be called again. The Mac restart being the only fix made me consider if it was a Mac USB issue, but macOS doesn’t make restarting USB easy. I removed the USB adapter in favor of a direct cable, but that didn’t help. After over an hour of messing around, resetting permissions, and re-flashing the Arduino code countless times, I nearly gave up. (It was 2:30 AM.) Going back to first principles, I decided to look up the raw web serial docs, popping a listener in my console to print when serial events were coming into the browser, not when they were processed by p5. Alas, the events were coming in!

I started getting to work writing my own adapter for the vanilla serial API, but the data doesn’t come in in strings, and I realized it might take too long. On GitHub, I found @gohai/p5.webserial, an alternative library with a smaller API surface area. I rewrote my serial code to use this library instead, and it worked seamlessly! I can’t discern what the precise bug in the previous serial library was, but it was confirmed the source. With the new library, the unreliability was coming from the read switch magnets but not the software, as intended.

I switched the game to a monospace duospaced font, since Avenir felt too polished previously.

2022-11-05: So close, yet so far

I nearly finished the software today! The core game mechanic wasn’t there before—you could run out of water, but there was no constraining force on your budget, which is a key aspect of the commentary. Thus, I added a budget that changes alongside your hydration level, giving you consistent income that’s just never enough to live long. I played a bunch with the numbers, and the game may be too hard, as a typical run is around 2 days in the game. The price of water in this simulation is random, though I’m starting it at an outrageous $24.

Screenshot showing budget, price of water, and hydration

I modified the “game over” screen to have two outcomes: dehydration & bankruptcy, which an automated voice alerts you gleefully. (I’ve got a bug where it repeats this on loop instead of allowing you to play again; to fix tomorrow.)

Dehydrated

While the original idea called for hydration status LEDs, with the introduction of the budget concept in the software, reading 3 separate numbers aloud will be more confusing & frustrating to interact with than intriguing commentary; if you’re already looking at the screen, having status LEDs isn’t relevant. This cuts scope from the physical aspect of the project, unfortunately.

For the physical control, I need a glorified button. I want a physical water bottle on a platform you pick up to purchase water, then set back down. I got a read switch for this project, and an accompanying magnet to put in a small plastic water bottle I was given recently. I wired up the read switch on my breadboard & wrote a tiny program to output its value to test the interaction with the water bottle.

Circuit

I want the sensor to be hidden inside a cardboard(?) platform, and Priyanka helped me think through how to wire that: solder each end to a long wire (reused from my interactive object), heatshrink both joints to prevent interference inside the platform, then connect both ends to the breadboard. I soldered, covered the joints, cut two squares of cardboard, & then taped the wiring down.

Soldered read switch with heatshrinks

Luckily, the magnet is strong enough to work fine, even with the water bottle full of water, through the plastic and cardboard. I found it triggered events decently reliably when I picked up the water bottle, but there was a lot of noise in the sensor readings, which would result in perishing in the game. I followed the Arduino Debounce tutorial to not trigger events in quick succession:

int buttonState;
int lastButtonState = HIGH;
unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 50;
void setup() {
Serial.begin(100);
while(Serial == false){};
pinMode(2, INPUT);
}
void loop() {
int reading = digitalRead(2);
if (reading != lastButtonState) {
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > debounceDelay) {
if (reading != buttonState) {
buttonState = reading;
Serial.println(reading);
if (reading == LOW) {
Serial.println("buy");
}
}
}
lastButtonState = reading;
}

I added serial communication to the game, which is not yet working for reasons I can’t discover through any debugging means I tried for an hour. I might try a wholly different serial library; it’s essential this works.

At the end of today, the project is close, with the Arduino firing off buy events and the software listening for them & responding correctly, the link just isn’t working, which is frustrating.

2022-11-03: Game underway!

I haven’t started on the physical components yet, but I’ve got much of the basics in place for the software. It’s a p5 sketch that I’m running with the spacebar instead of a physical controller while I test it. I’ve got a fluctuating price for the water and a hydration level out of 4 (since humans, generously, need 4 liters of water a day). There’s one UI detail I like, where when you’re on your last bottle of water, it shakes in place.

Price and hydration screenshot

2022-10-31: Idea

Background: The world has a limited supply & increasing demand for potable freshwater. Long-term, renewable energy will make electricity cheap & abundant, and we’ll scale industrial-scale desalination alongside rain harvesting, toilet-to-tap, and other technologies to provide the water supply we need. But before those plants come online & while it’s prohibitively expensive—particularly in regions with conflict & not a lot of high-tech infrastructure—and as more unpredictable, intense droughts strike areas around the earth, there will be conflict & rising prices on fresh water.

My project imagines life in a drought-stricken place a decade from now, in 2032, where water has become scarce & expensive, through a callous commentary on how we treat each other. The price of water will rapidly fluctuate, and you have to decide when to buy it, but you’ll always get screwed by the rising/fluctuating prices. The player of this game will not be able to see the screen, but only get audio feedback & have the physical components in-hand, while the audience will see the screen & watch the player.

The p5 sketch:

  • Shows the current price of water as it rapidly changes
  • Announces the new price every few seconds with Web Speech, not explicitly stating the change but relying on the player to mentally diff the price & decide if now is a good time to buy
    • The price will change faster than announced, commenting on the poor digital infrastructure we expect from the government/institutions
  • Shows the audience how much the player has bought of what they need before they dehydrate

The physical components:

  • A “button” (potentially made of a water bottle with a force(?) sensor inside it) for buying water
  • Communicates with the p5 sketch for input & output
  • Status LEDs showing how much of the necessary water is purchased