Pong Game Web based on huge RGB Matrix

Hello everyone,

our plan is to build a huge RGB Matrix on our office window wall.

We want that people from the other side of the river can play pong or other games on that matrix.
For now we try to test it on a small 32x16 RGB Matrix with ESP 32.

I got Pong running but I need someone to point me in the right direction when it comes to connecting it to the web so that somebody with a phone could control the paddle on the internet and play with his phone on the matrix.

Do I just make a web server with another esp32? How can somebody with the phone control the paddle instead of having the analog signal from the joystick now.

#include <Adafruit_GFX.h>
#include <Adafruit_NeoMatrix.h>
#include <Adafruit_NeoPixel.h>
#include <Arduino.h>
#include <SPI.h>

#define PIN 2


Adafruit_NeoMatrix matrix = Adafruit_NeoMatrix(32, 16, PIN,
  NEO_MATRIX_TOP     + NEO_MATRIX_LEFT +
  NEO_MATRIX_COLUMNS + NEO_MATRIX_ZIGZAG,
  NEO_RGB            + NEO_KHZ800);

// variables for the position of the ball and paddle
int paddleX = 0;
int paddleY = 0;
int oldPaddleX, oldPaddleY;
int ballDirectionX = 1;
int ballDirectionY = 1;
int score = 0;

int ballSpeed = 10; // lower numbers are faster

int ballX, ballY, oldBallX, oldBallY;

void setup() {
  Serial.begin(9600);
  // initialize the display
  matrix.begin();
  // black background 
  matrix.fillScreen(0);
  matrix.setTextColor(matrix.Color(0,255,0));
  matrix.print("GO MEIER");
  matrix.setTextWrap(false);
  matrix.show();
  delay(3000);
  matrix.fillScreen(0);
  matrix.show();
}

// this function checks the position of the ball
// to see if it intersects with the paddle
boolean inPaddle(int x, int y, int rectX, int rectY, int rectWidth, int rectHeight) {
  boolean result = false;

  if ((x >= rectX && x <= (rectX + rectWidth)) &&
      (y >= rectY && y <= (rectY + rectHeight))) {
    result = true;
  }

  return result;
}

// this function determines the ball's position on screen
void moveBall() {
  // if the ball goes offscreen, reverse the direction:
  if (ballX > matrix.width() - 1 || ballX < 0) {
    ballDirectionX = -ballDirectionX;
  }

  if (ballY > matrix.height() || ballY < 0) {
    ballDirectionY = -ballDirectionY;
  }

  // check if the ball and the paddle occupy the same space on screen
  if (inPaddle(ballX, ballY, paddleX, paddleY, 4, 1)) {
    if(ballX == paddleX && ballY == paddleY){
    ballDirectionX = -ballDirectionX;
    ballDirectionY = -ballDirectionY;
    }
    else if(ballX == paddleX + 3 && ballY == paddleY){
      ballDirectionX = ballDirectionX;
      ballDirectionY = -ballDirectionY;
    }
    else if(ballX == paddleX + 1 && ballY == paddleY){
      ballDirectionX = -ballDirectionX;
      ballDirectionY = -ballDirectionY;
    }
    else if(ballX == paddleX + 2 && ballY == paddleY){
      ballDirectionX = ballDirectionX;
      ballDirectionY = -ballDirectionY;
    }
  }

  // update the ball's position
  ballX += ballDirectionX;
  ballY += ballDirectionY;

  // erase the ball's previous position

  if (oldBallX != ballX || oldBallY != ballY) {
    matrix.drawPixel(oldBallX, oldBallY,matrix.Color(0,0,0));
  }


  // draw the ball's current position
  matrix.drawPixel(ballX, ballY,matrix.Color(150,150,0));

  oldBallX = ballX;
  oldBallY = ballY;

}

void loop() {

  // save the width and height of the screen
  int myWidth = matrix.width();
  int myHeight = matrix.height();

  // map the paddle's location to the position of the potentiometers
  paddleX = map(analogRead(A0), 0, 1023, 0, 31);
  paddleY = 15;
  
  // set the fill color to black and erase the previous
  // position of the paddle if different from present

  if (oldPaddleX != paddleX || oldPaddleY != paddleY) {
    matrix.fillRect(oldPaddleX, oldPaddleY, 4, 1,matrix.Color(0,0,0));
  }

    // draw the paddle on screen, save the current position
    // as the previous.
  //if(paddleX >= 0 && paddleX <= 11){
  matrix.fillRect(paddleX, paddleY, 4, 1,matrix.Color(0,0,255));
  //}
  //else if(paddleX < 0){
    //paddleX = 0;
    //matrix.fillRect(paddleX, paddleY, 3, 1,matrix.Color(0,0,255));
  //}
  //else if(paddleX >= 13){
  
  //}
  oldPaddleX = paddleX;
  oldPaddleY = paddleY;
  matrix.show();


  // update the ball's position and draw it on screen
  if (millis() % ballSpeed < 2) {
    moveBall();
  }
  matrix.show();
  if(ballY > 16 && (millis() > 10000)){
    score += 1;
    matrix.fillScreen(0);
    matrix.setTextColor(matrix.Color(255,0,0));
    matrix.setCursor(0,2);
    matrix.print(String(score));
    matrix.show();
    delay(4000);
    ballX = random(3,11);
    ballY = random(1,1);
    matrix.fillScreen(0);
    matrix.show();
    delay(1000);
  }
  delay(5);
}

Your help and tips are much appreciated.

Best regards,
Meier

Latency is going to be a big problem!

Yes, probably.Any idea how to fix issue with latency?

Now I found this guy making text and sending it over a web server which works great.

#include <ESP8266WiFi.h>
#include "espneotext.h"
#include <Adafruit_GFX.h>
#include <Adafruit_NeoMatrix.h>
#include <Adafruit_NeoPixel.h>
#ifndef PSTR
 #define PSTR // Make Arduino Due happy
#endif

#define PIN 2

const char* ssid = "...";
const char* password = "...";
String value;
//char charBuf[60];
int z=0;
int pixelsInText;
// Create an instance of the server
// specify the port to listen on as an argument
WiFiServer server(80);



  Adafruit_NeoMatrix matrix = Adafruit_NeoMatrix(32, 16, PIN,
  NEO_MATRIX_TOP     + NEO_MATRIX_LEFT +
  NEO_MATRIX_COLUMNS + NEO_MATRIX_ZIGZAG,
  NEO_RGB            + NEO_KHZ800);

const uint16_t colors[] = {
  matrix.Color(255, 0, 0), matrix.Color(0, 255, 0), matrix.Color(0, 0, 255) };


void setup() {
    matrix.begin();
  matrix.setTextWrap(false);
  matrix.setBrightness(40);
  matrix.setTextColor(colors[0]);
  Serial.begin(115200);
  delay(10);

    // Connect to WiFi network
  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  
  WiFi.begin(ssid, password);
  
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");
  
  // Start the server
  server.begin();
  Serial.println("Server started");

  // Print the IP address
  Serial.println(WiFi.localIP());

}

int x    = matrix.width();
int pass = 0;

void loop() {

  // Check if a client has connected
  WiFiClient client = server.available();
  if (!client) {
    return;
  }
  
  // Wait until the client sends some data
  Serial.println("new client");
  while(!client.available()){
    delay(1);
  }

  // Read the first line of the request
  String command1 = client.readStringUntil('/');
  String command = client.readStringUntil('/');
  Serial.println(command);
if (command == "text") {
value = client.readStringUntil('/');
z=1;
value.replace("%20", " ");
pixelsInText = (value.length() * 7)+8;
  Serial.println(value);
//value.toCharArray(charBuf, 70) ;
}
else {  // Prepare the response
  String s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n";
  s += file1;  
  client.flush();

  // Send the response to the client
while(s.length()>2000)
{
  String dummy = s.substring(0,2000);
  client.print(dummy);
  s.replace(dummy," ");
}
  
  client.print(s);
  delay(1);
  Serial.println("Client disconnected");

  // The client will actually be disconnected 
  // when the function returns and 'client' object is destroyed
}
if(z){
  while(x+17 > (matrix.width() - pixelsInText)){
 matrix.fillScreen(0);
  matrix.setCursor(--x, 0);
  matrix.print(value);
  matrix.show();
  delay(100);
  }
  x    = matrix.width();
}
}

Good start, but sending text is not so critical on latency.

I fear I don't have any bright ideas, just mentioning that for such an immediate game, latency is likely to be a limiting factor. :roll_eyes: