Rock Paper Scissors
Rock Paper Scissors
Or
What a Pain in the Ass.
So, building and coding a wireless rock-paper-scissors game proved to be way, way harder then I would have ever expected. Dave Spector and I started off using a slightly different approach then most everyone else seemed to take, using the Duplex Sender code as a foundation. Our idea seemed incredibly simple:
1) Use a 10k pot to select rock, paper, or scissors
2) Send the pot value via the Analog Duplex Sender code.
3) Insert that value into a RPS game.
And of course in the end, nothing worked.
After struggling, changing our code, swearing, and a lot of Robs help, we managed to get something together that allowed use to play 1 or 2 games of RPS, and then crashed completely. I still have no idea why this happened, and would like to take another look at all the code when I have a bit more time.
I still really don’t understand why our original approach failed so miserably.
Pics:
Code:
/*
XBee Analog Duplex sender
Language: Wiring/Arduino
This sketch configures an XBee radio via the serial port,
sends the value of an analog sensor out, and listens for
input from the radio, using it to set the value of
a PWM output.
Thanks to Robert Faludi for the critique and improvements
*/
#define sensorPin 0 // input sensor
#define txLed 2 // LED to indicate outgoing data
#define rxLed 3 // LED to indicate incoming data
#define analogLed 9 // LED that will change brightness with incoming value
#define threshold 10 // how much change you need to see on
// the sensor before sending
int gameState = 1; // 1 = choice, 2 = tx/rx, 3 = winner mode
int brightness = 0;
int sensorValue = 0;
int x = 0;
int y = 0;
int ledScissors = 7;
int ledRock = 5;
int ledPaper = 6;
int ledWinner = 4;
int ledLoser = 8;
int attackSwitchPin = 12; // Analog input pin that the switch is attached to
int attackSwitchValue = 0; //value read from attackSwitch
int lastSensorReading = 0; // previous state of the switch
int inByte= -1; // incoming byte from serial RX
char inString[6]; // string for incoming serial data
int stringPos = 0; // string index counter
void setup() {
// configure serial communications:
Serial.begin(9600);
// configure output pins:
pinMode(txLed, OUTPUT);
pinMode(rxLed, OUTPUT);
pinMode (analogLed, OUTPUT);
pinMode(ledRock, OUTPUT);
pinMode(ledScissors, OUTPUT);
pinMode(ledPaper, OUTPUT);
pinMode(ledWinner, OUTPUT);
pinMode(ledLoser, OUTPUT);
digitalWrite(ledRock, LOW); //turn off led
digitalWrite(ledPaper, LOW); //turn off led
digitalWrite(ledScissors, LOW); //turn off led
digitalWrite(ledWinner, LOW); //turn off led
digitalWrite(ledLoser, LOW); //turn off led
// set XBee’s destination address:
setDestination();
// blink the TX LED indicating that the main program’s about to start:
blink(3);
}
void setDestination() {
// put the radio in command mode:
Serial.print(”+++”);
// wait for the radio to respond with “OK\r”
char thisByte = 0;
while (thisByte != ‘\r’) {
if (Serial.available() > 0) {
thisByte = Serial.read();
}
}
// set the destination address, using 16-bit addressing.
// if you’re using two radios, one radio’s destination
// should be the other radio’s MY address, and vice versa:
Serial.print(”ATDH0, DL5678\r”); //sofia switch this to 1234
// set my address using 16-bit addressing:
Serial.print(”ATMY1234\r”); ///sofia switch to 5678
// set the PAN ID. If you’re working in a place where many people
// are using XBees, you should set your own PAN ID distinct
// from other projects.
Serial.print(”ATID1124\r”);
// put the radio in data mode:
Serial.print(”ATCN\r”);
}
// Blink the tx LED:
void blink(int howManyTimes) {
for (int i=0; i< howManyTimes; i++) {
digitalWrite(txLed, HIGH);
delay(200);
digitalWrite(txLed, LOW);
delay(200);
}
}
void loop() {
while (gameState == 1) {
getInput();
if (digitalRead(attackSwitchPin) == HIGH) {
gameState = 2;
}
}
while (gameState == 2) {
// send my choice and listen for opponent’s choice
// listen for incoming serial data:
if (Serial.available() > 0) {
// turn on the RX LED whenever you’re reading data:
digitalWrite(rxLed, HIGH);
handleSerial();
}
else {
// turn off the receive LED when there’s no incoming data:
digitalWrite(rxLed, LOW);
}
// if there’s something to send, send it:
if (sensorValue >= 0) {
//light the tx LED to say you’re sending:
digitalWrite(txLed, HIGH);
Serial.print(sensorValue, DEC );
Serial.print(”\r”);
delay(50);
// turn off the tx LED:
digitalWrite(txLed, LOW);
}
if (brightness < 5 && brightness>0){
y = 1;
}
if (brightness >= 5 && brightness<= 250){
y = 2;
}
if (brightness > 250){
y=3;
}
if (y > 0) {
Serial.print(sensorValue, DEC );
delay(50);
Serial.print(”\r”);
delay(50);
gameState = 3;
}
while (gameState == 3) {
// calculate who won and show the output on happy LEDs
if (x == 1 ){
digitalWrite(ledRock, HIGH); //turn on led
}
if (x == 2 ){
digitalWrite(ledPaper, HIGH); //turn on led
}
if (x == 3 ){
digitalWrite(ledScissors, HIGH); //turn on led
}
if (y == 1 ){
digitalWrite(ledRock, HIGH); //turn on led
//Serial.println (”Player 2 Chose ROCK!”);
}
if (y == 2 ){
// Serial.println (”Player 2 Chose PAPER!”);
digitalWrite(ledPaper, HIGH); //turn on led
}
if (y == 3 ){
// Serial.println (”Player 2 Chose SCISSORS!”);
digitalWrite(ledScissors, HIGH); //turn on led
}
if (x == y) {
//Serial.println(”It’s a draw!”);
digitalWrite(ledWinner, HIGH); //turn on led
digitalWrite(ledLoser, HIGH); //turn on led
}
if (x == 1 && y == 2) {
//Serial.println(”Paper covers Rock! PLAYER 2 WINS!”);
digitalWrite(ledLoser, HIGH); //turn off led
}
if (y == 1 && x == 2) {
//Serial.println(”Paper covers Rock! PLAYER 1 WINS!”);
digitalWrite(ledWinner, HIGH); //turn on led
}
if (x == 1 && y == 3) {
//Serial.println(”Rock smashes Scissors! PLAYER 1 WINS!”);
digitalWrite(ledWinner, HIGH); //turn on led
}
if (y == 1 && x == 3) {
//Serial.println(”Rock smashes Scissors! PLAYER 2 WINS!”);
digitalWrite(ledLoser, HIGH); //turn off led
}
if (x == 2 && y == 3) {
//Serial.println(”Scissors cuts Paper! PLAYER 2 WINS!”);
digitalWrite(ledLoser, HIGH); //turn off led
}
if (y == 2 && x == 3) {
//Serial.println(”Scissors cuts Paper! PLAYER 1 WINS!”);
digitalWrite(ledWinner, HIGH); //turn on led
}
if (digitalRead(attackSwitchPin) == HIGH) {
digitalWrite(ledRock, LOW); //turn off led
digitalWrite(ledPaper, LOW); //turn off led
digitalWrite(ledScissors, LOW); //turn off led
digitalWrite(ledWinner, LOW); //turn off led
digitalWrite(ledLoser, LOW); //turn off led
delay(3000);
y = 0;
brightness = 0;
Serial.flush();
gameState = 1;
}
// delay (3000);
// y = 0;
}
}
}
void getInput() {
// listen to the potentiometer:
sensorValue = analogRead(sensorPin)/4;
if (sensorValue > 0) { // if we got a real value from the readSensor() function
if (sensorValue < 5) {
digitalWrite(ledRock, HIGH);
digitalWrite(ledPaper, LOW);
digitalWrite(ledScissors, LOW);
x = 1;
}
if (sensorValue > 4 && sensorValue < 251) {
digitalWrite(ledRock, LOW);
digitalWrite(ledPaper, HIGH);
digitalWrite(ledScissors, LOW);
x = 2;
}
if (sensorValue > 250) {
digitalWrite(ledRock, LOW);
digitalWrite(ledPaper, LOW);
digitalWrite(ledScissors, HIGH);
x = 3;
}
}
}
void handleSerial() {
inByte = Serial.read();
// save only ASCII numeric characters (ASCII 0 - 9):
if ((inByte >= ‘0′) && (inByte <= ‘9′)){
inString[stringPos] = inByte;
stringPos++;
}
// if you get an ASCII carriage return:
if (inByte == ‘\r’) {
// convert the string to a number:
brightness = atoi(inString);
// set the analog output LED:
//analogWrite(analogLed, brightness);
// put zeroes in the array
for (int c = 0; c < stringPos; c++) {
inString[c] = 0;
}
// reset the string pointer:
stringPos = 0;
}
}