/* Modified from Making Things Talk by Tom Igoe (O'Reilly Press) Monski Pong (Using PongHatDuino) Language: Processing Uses the values from four sensors to animate a game of pong. Expects a serial string from the serial port in the following format: leftPaddle,rightPaddle,resetButton,serveButton,linefeed leftPaddle: ASCII numeric string from 0 - 1023 rightPaddle: ASCII numeric string from 0 - 1023 resetButton: ASCII numeric string from 0 - 1 serveButton: ASCII numeric string from 0 - 1 */ import processing.serial.*; // import the serial library int linefeed = 10; // Linefeed in ASCII Serial myPort; // The serial port float leftPaddle, rightPaddle; // variables for the flex sensor values int resetButton, serveButton; // variables for the button values int leftPaddleX, rightPaddleX; // horizontal positions of the paddles int paddleHeight = 50; // vertical dimension of the paddles int paddleWidth = 10; // horizontal dimension of the paddles // Adjust these values to suit your force-sensitive resistors: float leftMinimum = 0; // minimum value of the left flex sensor float rightMinimum = 0; // minimum value of the right flex sensor float leftMaximum = 600; // maximum value of the left flex sensor float rightMaximum = 600; // maximum value of the right flex sensor int ballSize = 10; // the size of the ball int xDirection = 1; // the ball�s horizontal direction. // left is �1, right is 1. int yDirection = 1; // the ball�s vertical direction. // up is �1, down is 1. int xPos, yPos; // the ball's horizontal and vertical positions boolean ballInMotion = false; // whether the ball should be moving boolean madeContact = false; // Serial contact flag. int leftScore = 0; int rightScore = 0; PFont myFont; int fontSize = 36; void setup() { // set the window size: size(640, 480); // initialize the ball in the center of the screen: xPos = width/2; yPos = height/2; // List all the available serial ports println(Serial.list()); // Open whatever port is the one you're using. myPort = new Serial(this, Serial.list()[0], 9600); // read bytes into a buffer until you get a linefeed (ASCII 10): myPort.bufferUntil(linefeed); // initialize the sensor values: leftPaddle = height/2; rightPaddle = height/2; resetButton = 0; serveButton = 0; // initialize the paddle horizontal positions: leftPaddleX = 50; rightPaddleX = width - 50; // set no borders on drawn shapes: noStroke(); // create a font with the second font available to the system: PFont myFont = createFont(PFont.list()[2], fontSize); textFont(myFont); } void keyPressed() { if (key == 'r' || key == 'R') { resetButton = 1; } else if (key == 's' || key == 'S') { serveButton = 1; } } void draw() { // if you've never gotten a string from the microcontroller, // keep sending carriage returns to prompt for one: if (madeContact == false) { myPort.write('\r'); } background(0); // draw the left paddle: rect(leftPaddleX, leftPaddle, paddleWidth, paddleHeight); // draw the right paddle: rect(rightPaddleX, rightPaddle, paddleWidth, paddleHeight); // calculate the ball's position and draw it: if (ballInMotion == true) { animateBall(); } // if the serve button is pressed, start the ball moving: if (serveButton == 1) { println("Start serve"); ballInMotion = true; serveButton = 0; } // if the reset button is pressed, reset the scores // and start the ball moving: if (resetButton == 1) { leftScore = 0; rightScore = 0; ballInMotion = true; resetButton = 0; } // print the scores: text(leftScore, fontSize, fontSize); text(rightScore, width-fontSize, fontSize); } // serialEvent method is run automatically by the Processing applet // whenever the buffer reaches the byte value set in the bufferUntil() // method in the setup(): void serialEvent(Serial myPort) { // if serialEvent occurs at all, contact with the microcontroller // has been made: madeContact = true; // read the serial buffer: String myString = myPort.readStringUntil(linefeed); // if you got any bytes other than the linefeed: if (myString != null) { myString = trim(myString); // split the string at the commas //and convert the sections into integers: int sensors[] = int(split(myString, ',')); // if you received all the sensor strings, use them: if (sensors.length == 4) { // calculate the flex sensors� ranges: float leftRange = leftMaximum - leftMinimum; float rightRange = rightMaximum - rightMinimum; // scale the flex sensors� results to the paddles� range: leftPaddle = height * (sensors[0] - leftMinimum) / leftRange; rightPaddle = height * (sensors[1] - rightMinimum) / rightRange; // assign the switches� values to the button variables: //resetButton = sensors[2]; //serveButton = sensors[3]; // print the sensor values: // print("left: "+ leftPaddle + "\tright: " + rightPaddle); // println("\treset: "+ resetButton + "\tserve: " + serveButton); } } } void animateBall() { // if the ball is moving left: if (xDirection < 0) { // if the ball is to the left of the left paddle: if ((xPos <= leftPaddleX)) { // if the ball is in between the top and bottom // of the left paddle: if((leftPaddle - (paddleHeight/2) <= yPos) && (yPos <= leftPaddle + (paddleHeight /2))) { // reverse the horizontal direction: xDirection =-xDirection; } } } // if the ball is moving right: else { // if the ball is to the right of the right paddle: if ((xPos >= ( rightPaddleX + ballSize/2))) { // if the ball is in between the top and bottom // of the right paddle: if((rightPaddle - (paddleHeight/2) <=yPos) && (yPos <= rightPaddle + (paddleHeight /2))) { // reverse the horizontal direction: xDirection =-xDirection; } } } // if the ball goes off the screen left: if (xPos < 0) { rightScore++; resetBall(); } // if the ball goes off the screen right: if (xPos > width) { leftScore++; resetBall(); } // stop the ball going off the top or the bottom of the screen: if ((yPos - ballSize/2 <= 0) || (yPos +ballSize/2 >=height)) { // reverse the y direction of the ball: yDirection = -yDirection; } // update the ball position: xPos = xPos + xDirection; yPos = yPos + yDirection; // Draw the ball: rect(xPos, yPos, ballSize, ballSize); } void resetBall() { // put the ball back in the center xPos = width/2; yPos = height/2; }