πŸ“‹Tutorials

We will take a simple Calculator app and make it multiplayer... in minutes 🀯

WALKTHROUGH

1. Clone Calculator app (or any other React JS app)

git clone https://github.com/madzadev/calculator.git

Open the repository in your choice of code editor and run command npm install to install the dependencies. You can test out the original app by running the command npm run start.

2. Install DPAPI Packages

npm i @dpapi/server @dpapi/react

3. Create RoomProvider

Wrap the child elements with RoomProvider

src/index.js
import React from "react";
import ReactDOM from "react-dom";
import {RoomProvider} from "@dpapi/react";

import App from "./App";
import "./index.css";

const rootElement = document.getElementById("root");
ReactDOM.render(
  <RoomProvider>
    <App />
  </RoomProvider>,
  rootElement
);

4. Add Multiplayer Functionalities

useContext is used to create client socket connection. joinRoom, roomCount and liveCursors are added to the React App which shall be rendered.

src/App.js
// Retain all app import statements πŸ‘ˆπŸΌ
import {useContext} from "react";
import "./App.css";
import {
  clientSocket,
  roomCount,
  liveCursors,
  joinRoom,
} from "@dpapi/react";

// Retain original calculator app code πŸ‘ˆπŸΌ

const App = () => {
  const socket = useContext(clientSocket);
  joinRoom("calcRoom", socket);
  const usersCount = roomCount("calcRoom", socket);
  const cursors = liveCursors("calcRoom", socket);

  let [calc, setCalc] = useState({/* Retain code here */});
  // Retain original calculator app code πŸ‘ˆπŸΌ
  const resetClickHandler = () => {/* Retain code here🏼*/};

  return (
    <div className="App"> // ❗ Remember to add a CSS file
      <h1>Number of users in the room: {usersCount}</h1>
      {cursors.map((cursor, index) => {
        if (cursor.socketId !== socket.id) {
          return (
            <div
              key={cursor.socketId || index}
              className="other-cursor" // ❗ Style your cursors with CSS
              style={{
                left: cursor.x,
                top: cursor.y,
              }}
            />
          );
        } else { return null; }
      })}
      <br />
      <Wrapper>
        // Retain original calculator app code πŸ‘ˆπŸΌ
      </Wrapper>
    </div>
  );
};

export default App;

5. Cursor CSS Elements

Create a new file called App.css in the src directory.

src/App.css
.App {
  text-align: center;
 }

.other-cursor {
  position: absolute;
  width: 10px;
  height: 10px;
  border: 0;
  border-radius: 50%;
  background-color: red;
 }

EXTRA: Custom Cursor

In this section, we will assign random cursor icons to every client. This is useful for providing a fun and dynamic user experience in a shared space.

We make use of React useState & useEffect hooks to assign and re-render cursor icons.

src/App.js
// Retain all app import statements πŸ‘ˆπŸΌ
import {useEffect} from "react";
// Retain original calculator app code πŸ‘ˆπŸΌ

const cursorUrlArray = [
  "https://icons.iconarchive.com/icons/svengraph/daft-punk/256/Daft-Punk-Guyman-Off-icon.png",
  "https://icons.iconarchive.com/icons/everaldo/starwars/128/Darth-Vader-icon.png",
  "https://icons.iconarchive.com/icons/everaldo/starwars/128/clone-old-icon.png",
  "https://icons.iconarchive.com/icons/svengraph/daft-punk/256/Daft-Punk-Thomas-On-icon.png",
];

const App = () => {

  // Retain DPAPI functions πŸ‘ˆπŸΌ
  
  const [cursorUrl, setCursorUrl] = useState("");
  useEffect(() => {
  setCursorUrl(
    cursorUrlArray[Math.floor(Math.random() * cursorUrlArray.length)]
  );
  },[]);

  let [calc, setCalc] = useState({/* Retain code here */});
  // Retain original calculator app code πŸ‘ˆπŸΌ
  const resetClickHandler = () => {/* Retain code here🏼*/};

  return (
        // Retain DPAPI code from above πŸ‘ˆπŸΌ
              <div
              key={cursor.socketId || index}
              className="other-cursor" // ❗ Style your cursors with CSS
              style={{
                left: cursor.x,
                top: cursor.y,
                backgroundImage: `url(${cursorUrl})`,
              }}
        // Retain all other code from above πŸ‘ˆπŸΌ
    );
};

export default App;

Inside the useEffect hook, the setCursorUrl function is called to randomly select one of the cursorUrl values from the array and set it as the initial state of cursorUrl

Update Cursor CSS Elements

src/App.css
.App {
  text-align: center;
 }
 
.other-cursor {
    position : absolute;
    width: 35px;
    height: 35px;
    background-size: contain;
    border-radius: 100%;
}

Last updated