For this week’s assignment I wanted to make a dice-roller for monopoly – As in, an object that you shake as if you’re shaking dice and that triggers the dice roll in the monopoly I had previously made in processing. This proved to be challenging.
I wanted to make the roller as compact and sturdy as possible, since it will be subject to shaking and I didn’t want anything to come lose, so I started with this circuit:
I used an arduino maker1000 because of it’s small size. The shaking was detected using a tilt sensor. Everything is soldered on in one unit so it was easy to hold and shake and everything would still be stable. However, no matter how hard I tried, the maker1000 would not communicate with processing. So I switched to a redboard.
Here’s the video of how it works:
The code:
Arduino:
const int tiltPin = 6; const int ledPin = 10; int tiltState; // the current reading from the input pin int lastTiltState = LOW; // the previous reading from the input pin int counter = 0; unsigned long lastDebounceTime = 0; unsigned long debounceDelay = 20; void setup() { // put your setup code here, to run once: pinMode(tiltPin, INPUT); pinMode(ledPin, OUTPUT); Serial.begin(9600); digitalWrite(ledPin, HIGH); Serial.write(0); } void loop() { if (Serial.available() > 0) { int inByte = Serial.read(); if (counter <= 20) { digitalWrite(ledPin, HIGH); Serial.write(0); } else { counter = 0; digitalWrite(ledPin, LOW); Serial.write(1); delay(2000); } int reading = digitalRead(tiltPin); if (reading != lastTiltState) { lastDebounceTime = millis(); } if ((millis() - lastDebounceTime) > debounceDelay) { if (reading != tiltState) { tiltState = reading; counter++; } } // Serial.print(reading); // Serial.print(" || "); // Serial.println(counter); lastTiltState = reading; } // put your main code here, to run repeatedly: }
Processing:
import processing.serial.*; //0 name, 1 type, 2 owner, 3 cost, 4 rent, 5 xcoordinate, 6 ycoordinate // types: 0 = income tax, 1 = normal, 2 = railroad, 3 = utilities, 4 = community chest and chance, 5 = jail and free parking, 6 = go,7 = supertax String[][] places = { {"Go", "6", "Bank", " ", "-200", "750", "750"}, // 0 {"Old kent road", "1", "Bank", "60", "6", "660", "750"}, // 1 {"Community chest", "4", "Bank", " ", "0", "595", "750"}, // 2 {"White chapel road", "1", "Bank", "60", "6", "530", "750"}, //3 {"Income tax", "0", "Bank", " ", "200", "465", "750"}, // 4 {"Kings cross station", "2", "Bank", "200", "25", "400", "750"}, // 5 {"The angel islington", "1", "Bank", "100", "10", "335", "750"}, // 6 {"Chance", "4", "Bank", " ", "0", "270", "750"}, // 7 {"Euston Road", "1", "Bank", "100", "10", "205", "750"}, // 8 {"Pentonville Road", "1", "Bank", "120", "12", "140", "750"}, // 9 {"Jail", "5", "Bank", " ", "0", "50", "750"}, // 10 {"Pall Mall", "1", "Bank", "140", "14", "50", "660"}, // 11 {"Electric Company", "3", "Bank", "150", "15", "50", "595"}, // 12 {"Whitehall", "1", "Bank", "140", "14", "50", "530"}, // 13 {"Northumberland Avenue", "1", "Bank", "160", "16", "50", "465"}, // 14 {"Marylebone station", "2", "Bank", "200", "25", "50", "400"}, // 15 {"Bow street", "1", "Bank", "180", "18", "50", "335"}, // 16 {"Community chest", "4", "Bank", " ", "0", "50", "270"}, // 17 {"Marlborough street", "1", "Bank", "180", "18", "50", "205"}, // 18 {"Vine street", "1", "Bank", "200", "20", "50", "130"}, // 19 {"Free Parking", "5", "Bank", " ", "0", "50", "50"}, // 20 {"Strand", "1", "Bank", "220", "22", "140", "50"}, // 21 {"chance", "4", "Bank", " ", "0", "205", "50"}, // 22 {"Fleet street", "1", "Bank", "220", "22", "270", "50"}, // 23 {"Trafalgar square", "1", "Bank", "240", "24", "335", "50"}, // 24 {"Fenchurch st station", "2", "Bank", "200", "25", "400", "50"}, // 25 {"Leicester square", "1", "Bank", "260", "26", "465", "50"}, // 26 {"Coventry street", "1", "Bank", "260", "26", "530", "50"}, // 27 {"Waterworks", "3", "Bank", "150", "15", "595", "50"}, // 28 {"Piccadilly", "1", "Bank", "280", "28", "660", "50"}, // 29 {"Jail", "5", "Bank", " ", "0", "750", "50"}, // 30 {"Regent street", "1", "Bank", "300", "30", "750", "130"}, // 31 {"Oxford street", "1", "Bank", "300", "30", "750", "205"}, // 32 {"Community chest", "4", "Bank", " ", "0", "750", "270"}, // 33 {"Bond street", "1", "Bank", "320", "32", "750", "335"}, // 32 {"Marylebone station", "2", "Bank", "200", "25", "750", "400"}, // 15 {"Chance", "4", "Bank", " ", "0", "750", "465"}, // 33 {"Park lane", "1", "Bank", "350", "32", "750", "530"}, // 32 {"Supertax", "7", "Bank", " ", "200", "750", "595"}, {"Mayfair", "1", "Bank", "400", "40", "750", "660"}, }; int toRoll; int prevToRoll; boolean allowRoll = true; int circlesize = 10; int turn = 0; int diceroll; PImage bg; boolean first = true; boolean proceed = false; // colors: red or blue Player p1 = new Player("red", int(places[0][5]), int(places[0][6]), 10); Player p2 = new Player("blue", int(places[0][5]), int(places[0][6]), -10); Serial myPort; void setup() { printArray(Serial.list()); String portname=Serial.list()[2]; println(portname); myPort = new Serial(this, portname, 9600); //myPort.clear(); //myPort.bufferUntil('\n'); first = false; size(800, 800); bg = loadImage("board.jpg"); background(0); fill(255); textSize(16); text("Welcome to mehnopoly. It's almost monopoly, but seriously lower your expectations.", 20, 50); text("The game is for two players. or You can play against yourself if you can't find friends. I dont judge.", 20, 100); text("You win by making your opponent go bankrupt. Go nuts!", 20, 150); text("Press S to start the game", 20, 200); textSize(12); text("Fun Fact: Monopoly was originally created as a statement against capitalism.", 20, 250); } void draw() { if (proceed==true ){ refresh(); allowRoll = false; diceroll = rollDice(); handleRoll(); proceed=false; } if (first) { textSize(24); fill(255, 127, 0); text("Player 1 has "+p1.money+" left", 150, 200); text("Player 2 has "+p2.money+" left", 150, 250); text("Player 1's turn", 150, 300); text("Press R to roll dice", 150, 350); } } int keycounter = 0; class Player { int money, xpos, ypos, rails, utilities, offset, placecount, propertyamount; int[] properties = new int[50]; String col; Player (String n, int xp, int yp, int off) { col = n; placecount = 0; money = 1500; offset = off; xpos = xp; ypos = yp; rails = 0; utilities = 0; propertyamount = 0; } void display() { strokeWeight(2); stroke(255, 255, 255); if (col == "red")fill(255, 0, 0); if (col == "blue")fill(0, 0, 255); ellipse(xpos+offset, ypos, circlesize, circlesize); } void updatePos() { xpos = int(places[placecount][5]); ypos = int(places[placecount][6]); } } int rollDice() { return round(random(2, 12)); //return 7; } void checkLanded(Player x) { textSize(24); fill(255, 127, 0); text("You rolled "+diceroll+" and landed on: "+places[x.placecount][0], 150, 200); if (int(places[x.placecount][1]) == 5 || int(places[x.placecount][1]) == 6)text("Press E to end turn", 150, 250); // if income tax if (int(places[x.placecount][1]) == 0) { fill(255, 127, 0); text("You pay 200 for income tax", 150, 250); x.money-=200; text("You now have: "+str(x.money)+" left", 150, 300); text("Press E to end turn", 150, 350); // if purchasable } else if (int(places[x.placecount][1]) == 1 || int(places[x.placecount][1]) == 2 || int(places[x.placecount][1]) == 3) { // if owner is bank if (places[x.placecount][2] == "Bank") { fill(255, 127, 0); text("Property isn't owned, what would you like to do?", 150, 250); text("Press B to buy for "+places[x.placecount][3]+" or press E to end turn", 150, 300); // if owner is not bank } else { // if it's a normal purchasable if (int(places[x.placecount][1]) == 1) { if (turn == 0 && places[x.placecount][2] == "Player2")handleRent(p1, p2, int(places[x.placecount][4])); if (turn == 1 && places[x.placecount][2] == "Player1")handleRent(p2, p1, int(places[x.placecount][4])); // if railroad } else if (int(places[x.placecount][1]) == 2) { int rent; if (turn == 1 && places[x.placecount][2] == "Player1") { rent = checkRailRent(p1); handleRent(p2, p1, rent); } else if (turn == 0 && places[x.placecount][2] == "Player2") { rent = checkRailRent(p2); handleRent(p1, p2, rent); } // if utilities } else if (int(places[x.placecount][1]) == 3) { int rent = 0; if (turn == 0 && places[x.placecount][2] == "Player2") { if (p2.utilities == 1)rent= 7*diceroll; if (p2.utilities == 2)rent= 15*diceroll; handleRent(p1, p2, rent); } else if (turn == 1 && places[x.placecount][2] == "Player1") { if (p1.utilities == 1)rent= 7*diceroll; if (p1.utilities == 2)rent= 15*diceroll; handleRent(p2, p1, rent); } } } // super tax } else if (int(places[x.placecount][1]) == 7) { fill(255, 127, 0); text("You pay 100 for super tax", 150, 250); x.money-=200; text("You now have: "+str(x.money)+" left", 150, 300); text("Press E to end turn", 150, 350); //community chest and chance } else if (int(places[x.placecount][1]) == 4) { int r = round(random(1, 3)); if (!(r == 2)) { text("Jeff Bezos felt generous today, he gave you 100!", 150, 250); text("Assuming 1 = $100,000 , this amounts to", 150, 300); text("a whooping 0.0001% of his net worth", 150, 350); text("press E to end turn", 150, 400); x.money += 100; } else { text("You did some contractual work on one of", 150, 250); text("Trump's properties! He paid you a 1000!", 150, 300); text("Just kidding, he didn't pay you at all.", 150, 350); text("In fact you paid a 100 for materials.", 150, 400); text("press E to end turn", 150, 450); x.money -= 100; } } checkWin(); } void checkWin() { if (p1.money < 0) { refresh(); fill(255, 127, 0); text("P2 has won", 150, 200); noLoop(); } if (p2.money < 0) { refresh(); fill(255, 127, 0); text("P1 has won", 150, 200); noLoop(); } } void endTurn() { refresh(); fill(255, 127, 0); text("Player 1 has "+p1.money+" left", 150, 200); text("Player 2 has "+p2.money+" left", 150, 250); if (turn == 0) { fill(255, 127, 0); text("Player 1's turn has ended. Player 2's turn", 150, 300); turn = 1; } else { fill(255, 127, 0); text("Player 2's turn has ended. Player 1's turn", 150, 300); turn = 0; } text("Press R to roll or I for a list of your properties,", 150, 350); allowRoll = true; checkWin(); } void refresh() { background(bg); p1.display(); p2.display(); fill(0); rect(100, 100, 600, 600); } void buy(Player x) { fill(255, 127, 0); if (places[x.placecount][2] == "Bank") { x.money -= int(places[x.placecount][3]); x.properties[p1.propertyamount] = x.placecount; x.propertyamount++; text(places[x.placecount][0]+" has been purchased", 150, 200); if (turn == 0) places[x.placecount][2] = "Player1"; if (turn == 1) places[x.placecount][2] = "Player2"; if (int(places[x.placecount][1]) == 2) { x.rails += 1; text("You now have "+x.rails+" railroads", 150, 250); text("Press E to end turn", 150, 300); } else if (int(places[x.placecount][1]) == 3) { x.utilities += 1; text("You now have "+x.utilities+" utilities", 150, 250); text("Press E to end turn", 150, 300); } else { text("Press E to end turn", 150, 250); } } checkWin(); } int checkRailRent(Player x) { if (x.rails == 1) return x.rails*25; if (x.rails == 2) return x.rails*25; if (x.rails == 3) return 100; if (x.rails == 4) return 200; return 0; } void handleRent(Player renter, Player rentee, int rent) { renter.money -= rent; rentee.money += rent; fill(255, 127, 0); text("Property is owned, you have paid "+rent+" in rent", 150, 250); text("You have "+renter.money+" left", 150, 300); text("Press E to end turn", 150, 350); checkWin(); } void handleRoll() { if (turn == 0) { if (p1.placecount + diceroll >= 40) { p1.placecount = p1.placecount+diceroll - 40; p1.money += 200; } else { p1.placecount+= diceroll; } p1.updatePos(); refresh(); checkLanded(p1); } else { if (p2.placecount + diceroll >= 40) { p2.placecount = p2.placecount+diceroll - 40; p2.money += 200; } else { p2.placecount+= diceroll; } p2.updatePos(); refresh(); checkLanded(p2); } } void serialEvent(Serial myPort) { int x = myPort.read(); println(x); if (x == 1 && allowRoll) { proceed=true; } //toRoll = myPort.read(); //println(toRoll); myPort.write(0); } void keyPressed() { //keycounter++; //if (keycounter == 1) first = true; //if (keycounter == 2) first = false; if (key =='s')refresh(); //refresh(); // Roll dice phase if ((key == 'r' || key == 'R')&&allowRoll) { allowRoll = false; diceroll = rollDice(); handleRoll(); } if ((key == 'b' || key =='B')&& !allowRoll) { refresh(); if (turn == 0) { buy(p1); } else { buy(p2); } } if ((key == 'e' || key == 'E')&& !allowRoll) { refresh(); endTurn(); } if ((key == 'i' || key == 'I') && allowRoll) { fill(255, 127, 0); if (turn == 0) { int ycounter = 200; for (int i = 0; i<p1.propertyamount; i++, ycounter+=50) { text(places[p1.properties[i]][0], 150, ycounter); } } if (turn == 1) { int ycounter = 200; for (int i = 0; i<p2.propertyamount; i++, ycounter+=50) { text(places[p2.properties[i]][0], 150, ycounter); } } } }