Desenvolvimento

27 set, 2024

Aprenda a criar um jogo de xadrez multiplayer com React

Publicidade

Neste tutorial, vamos te guiar na construção de um jogo de xadrez multiplayer usando o SuperViz. Jogos multiplayer exigem sincronização e interação em tempo real entre os jogadores, tornando-os aplicações ideais para as capacidades do SuperViz. Este tutorial vai te mostrar como criar um jogo de xadrez onde dois jogadores podem jogar um contra o outro em tempo real, vendo os movimentos um do outro à medida que acontecem.

Vamos ensinar como configurar um tabuleiro de xadrez usando a biblioteca react-chessboard, gerenciar o estado do jogo com o chess.js e sincronizar os movimentos dos jogadores com o SuperViz. Essa configuração permite que múltiplos participantes entrem em um jogo de xadrez, façam seus movimentos e experimentem um ambiente de jogo fluido e interativo. Vamos começar!

Pré-requisitos

Para seguir este tutorial, você precisará de uma conta no SuperViz e de um token de desenvolvedor. Se você já tem uma conta e um token, pode seguir para o próximo passo.

Criar uma conta

Para criar uma conta, vá para https://dashboard.superviz.com/register e crie uma conta usando o Google ou um e-mail/senha. É importante notar que ao usar e-mail/senha, você receberá um link de confirmação que precisará clicar para verificar sua conta.

Obtendo um Token de Desenvolvedor

Para usar o SDK, você precisará fornecer um token de desenvolvedor, pois ele é essencial para associar as solicitações do SDK à sua conta. Você pode obter tokens de desenvolvimento e produção do SuperViz no painel de controle.
Copie e salve o token de desenvolvedor, pois você precisará dele nos próximos passos deste tutorial.

Passo 1: Configurando sua Aplicação React

Para começar, você precisará configurar um novo projeto React, onde integraremos o SuperViz.

1. Crie um Novo Projeto React

Primeiro, crie uma nova aplicação React usando o Create React App com TypeScript.

npm create vite@latest chess-game -- --template react-ts
cd chess-game

 

2. Instale as Bibliotecas Necessárias

Em seguida, instale as bibliotecas necessárias para o nosso projeto:

npm install @superviz/sdk react-chessboard chess.js uuid
  • @superviz/sdk: SDK para integrar funcionalidades de colaboração em tempo real, incluindo sincronização.
  • react-chessboard: Biblioteca para renderizar um tabuleiro de xadrez em aplicações React.
  • chess.js: Biblioteca para gerenciar a lógica e as regras do jogo de xadrez.
  • uuid: Biblioteca para gerar identificadores únicos, útil para criar IDs exclusivos para os participantes.

3. Configure o Tailwind

Neste tutorial, vamos usar o framework de CSS Tailwind. Primeiro, instale o pacote tailwind.

npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p

Agora, precisamos configurar o caminho dos templates. Abra o arquivo tailwind.config.js na raiz do projeto e insira o seguinte código:

/** @type {import('tailwindcss').Config} */
export default {
  content: [
    "./index.html",
    "./src/**/*.{js,ts,jsx,tsx}",
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}

Em seguida, adicione as diretivas do Tailwind ao arquivo CSS global. (src/index.css)

@tailwind base;
@tailwind components;
@tailwind utilities;

4. Configure as Variáveis de Ambiente

Crie um arquivo .env na raiz do seu projeto e adicione a sua chave de desenvolvedor do SuperViz. Essa chave será usada para autenticar sua aplicação com os serviços do SuperViz.

VITE_SUPERVIZ_API_KEY=SUA_CHAVE_SUPERVIZ

Passo 2: Implementando a Aplicação Principal

Nesta etapa, vamos implementar a lógica principal da aplicação para inicializar o SuperViz e gerenciar os movimentos do jogo de xadrez em tempo real.

1. Implemente o Componente App

Abra o arquivo src/App.tsx e configure o componente principal da aplicação, usando o SuperViz para gerenciar o ambiente colaborativo.

import { v4 as generateId } from 'uuid';
import { useCallback, useEffect, useRef, useState } from "react";
import SuperVizRoom, { Realtime, RealtimeComponentEvent, RealtimeMessage, WhoIsOnline } from '@superviz/sdk';
import { Chessboard } from "react-chessboard";
import { Chess, Square } from 'chess.js';

2. Defina Constantes

Defina as constantes para a chave da API, ID da sala e ID do jogador.

const apiKey = import.meta.env.VITE_SUPERVIZ_API_KEY as string;

const ROOM_ID = 'chess-game';

const PLAYER_ID = generateId();

3. Defina o Tipo de Mensagem de Xadrez

Crie um tipo para lidar com as mensagens de movimento de xadrez.

type ChessMessageUpdate = RealtimeMessage & {

  data: {

    sourceSquare: Square;

    targetSquare: Square;

  };

};

4. Crie o Componente App

Configure o componente principal App e inicialize as variáveis de estado.

export default function App() {

export default function App() {
  const [initialized, setInitialized] = useState(false);
  const [gameState, setGameState] = useState<Chess>(new Chess());
  const [gameFen, setGameFen] = useState<string>(gameState.fen());

  const channel = useRef<any | null>(null);

Explicação:

  • initialized: Uma variável de estado para rastrear se o ambiente SuperViz foi configurado.
  • gameState: Uma variável de estado para gerenciar o estado do jogo de xadrez usando a biblioteca chess.js.
  • gameFen: Uma variável de estado para armazenar a string FEN (Forsyth-Edwards Notation), que representa a posição atual do jogo.
  • channel: Um ref para armazenar o canal de comunicação em tempo real.

5. Inicializar SuperViz e Componentes em Tempo Real

Crie uma função initialize para configurar o ambiente SuperViz e sincronizar em tempo real.

const initialize = useCallback(async () => {
  if (initialized) return;

  const superviz = await SuperVizRoom(apiKey, {
    roomId: ROOM_ID,
    participant: {
      id: PLAYER_ID,
      name: 'player-name',
    },
    group: {
      id: 'chess-game',
      name: 'chess-game',
    }
  });

  const realtime = new Realtime();
  const whoIsOnline = new WhoIsOnline();

  superviz.addComponent(realtime);
  superviz.addComponent(whoIsOnline);

  setInitialized(true);

  realtime.subscribe(RealtimeComponentEvent.REALTIME_STATE_CHANGED, () => {
    channel.current = realtime.connect('move-topic');

    channel.current.subscribe('new-move', handleRealtimeMessage);
  });
}, [handleRealtimeMessage, initialized]);

Explicação:

  • initialize: Uma função assíncrona que inicializa a sala SuperViz e verifica se já foi configurada para evitar duplicatas.
  • SuperVizRoom: Configura a sala, o participante e os detalhes do grupo para a sessão.
  • Assinatura em Tempo Real: Conecta ao canal move-topic e escuta novos movimentos, atualizando o estado local conforme necessário.

6. Lidar com Movimentos de Xadrez

Crie uma função para tratar os movimentos de xadrez e atualizar o estado do jogo.

const makeMove = useCallback((sourceSquare: Square, targetSquare: Square) => {
  try {
    const gameCopy = gameState;
    gameCopy.move({ from: sourceSquare, to: targetSquare, promotion: 'q' });

    setGameState(gameCopy);
    setGameFen(gameCopy.fen());

    return true;
  } catch (error) {
    console.log('Movimento Inválido', error);
    return false;
  }
}, [gameState]);

Explicação:

  • makeMove: Tenta fazer um movimento no tabuleiro de xadrez, atualizando o estado do jogo e a string FEN se o movimento for válido.
  • Promoção: Promove automaticamente um peão para rainha se ele alcançar a última linha.

7. Lidar com Queda de Peça

Crie uma função para lidar com eventos de queda de peça no tabuleiro.

const onPieceDrop = (sourceSquare: Square, targetSquare: Square) => {
  const result = makeMove(sourceSquare, targetSquare);

  if (result) {
    channel.current.publish('new-move', {
      sourceSquare,
      targetSquare,
    });
  }

  return result;
};

Explicação:

  • onPieceDrop: Lida com a lógica para quando uma peça é solta em um novo quadrado, fazendo o movimento e publicando-o no canal SuperViz se for válido.

8. Lidar com Mensagens em Tempo Real

Crie uma função para lidar com mensagens em tempo real recebidas sobre os movimentos feitos por outros jogadores.

const handleRealtimeMessage = useCallback((message: ChessMessageUpdate) => {
  if (message.participantId === PLAYER_ID) return;

  const { sourceSquare, targetSquare } = message.data;
  makeMove(sourceSquare, targetSquare);
}, [makeMove]);

Explicação:

  • handleRealtimeMessage: Escuta mensagens de movimento recebidas e atualiza o estado do jogo se o movimento for feito por outro participante.

9. Hook useEffect para Inicialização

Use o hook useEffect para disparar a função initialize ao montar o componente.

useEffect(() => {
  initialize();
}, [initialize]);

Explicação:

  • useEffect: Chama a função initialize uma vez quando o componente é montado, configurando o ambiente SuperViz e a sincronização em tempo real.

10. Renderizar a Aplicação

Retorne a estrutura JSX para renderizar a aplicação, incluindo o tabuleiro de xadrez e os recursos de colaboração.

return (
  <div className='w-full h-full bg-gray-200 flex items-center justify-center flex-col'>
    <header className='w-full p-5 bg-purple-400 flex items-center justify-between'>
      <h1 className='text-white text-2xl font-bold'>SuperViz Chess Game</h1>
    </header>
    <main className='w-full h-full flex items-center justify-center'>
      <div className='w-[500px] h-[500px] shadow-sm border-2 border-gray-300 rounded-md'>
        <Chessboard position={gameFen} onPieceDrop={onPieceDrop} />
        <div className='w-[500px] h-[50px] bg-gray-300 flex items-center justify-center'>
          <p className='text-gray-800 text-2xl font-bold'>Turno: {gameState.turn() === 'b' ? 'Preto' : 'Branco'}</p>
        </div>
      </div>
    </main>
  </div>
);

Explicação:

  • Cabeçalho: Exibe o título da aplicação.
  • Tabuleiro de Xadrez: Renderiza o tabuleiro usando o componente Chessboard, com gameFen como a posição e onPieceDrop como o manipulador de eventos para a queda de peças.
  • Indicador de Turno: Exibe o turno do jogador atual (Preto ou Branco).

Passo 3: Entendendo a Estrutura do Projeto

Aqui está uma visão geral rápida de como a estrutura do projeto suporta um jogo de xadrez multiplayer:

App.tsx:

    • Inicializa o ambiente SuperViz.
    • Configura as informações do participante e os detalhes da sala.
    • Gerencia a sincronização em tempo real para os movimentos de xadrez.
  • Tabuleiro de Xadrez:
    • Exibe o tabuleiro e gerencia os movimentos das peças.
    • Integra a comunicação em tempo real para sincronizar movimentos entre jogadores.
  • Lógica de Xadrez:
    • Usa o chess.js para gerenciar as regras do jogo e validar os movimentos.
    • Atualiza o estado do jogo e a string FEN para refletir a posição atual do tabuleiro.

Passo 4: Executando a Aplicação

1. Inicie a Aplicação React

Para rodar sua aplicação, utilize o seguinte comando no diretório do seu projeto:

npm run dev

Este comando irá iniciar o servidor de desenvolvimento e abrir sua aplicação no navegador padrão. Você poderá interagir com o tabuleiro de xadrez e ver as jogadas em tempo real à medida que outros participantes entrarem na sessão.

2. Teste a Aplicação

  • Movimentos de Xadrez em Tempo Real: Abra a aplicação em várias janelas ou abas do navegador para simular múltiplos participantes e verifique se as jogadas feitas por um jogador são refletidas em tempo real para os outros.
  • Interação Colaborativa: Teste a responsividade da aplicação fazendo movimentos e observando como o estado do jogo é atualizado para todos os participantes.

Resumo

Neste tutorial, construímos um jogo de xadrez multiplayer usando o SuperViz para a sincronização em tempo real. Configuramos uma aplicação React para lidar com as jogadas de xadrez, permitindo que múltiplos jogadores colaborem de forma fluida em um tabuleiro compartilhado. Esta configuração pode ser estendida e personalizada para se adaptar a vários cenários onde a interação em jogos é necessária.

Sinta-se à vontade para explorar o código completo e outros exemplos no repositório do GitHub para mais detalhes.