Este projeto é um jogo multiplayer (cliente-servidor) desenvolvido em Python e Pygame no âmbito da disciplina de Sistemas Distribuídos.
O jogo Fast'n Rocks é uma corrida de sobrevivência baseada no desvio de obstáculos. Os jogadores controlam carros que se deslocam horizontalmente e devem evitar colisões com o trânsito (veículos e obstáculos) que desce ao longo do ecrã. O jogo permite a criação de salas (lobbies), onde múltiplos jogadores podem entrar e competir simultaneamente. O jogador que sobreviver durante mais tempo alcança a maior pontuação.
O sistema baseia-se numa arquitetura Cliente-Servidor:
- Servidor: Mantém o estado global do jogo (posição dos obstáculos, colisões, vida dos jogadores, pontuação e gestão das salas) e transmite (broadcast) as atualizações aos clientes.
- Cliente: Responsável apenas por enviar os inputs (movimentos e interações) para o servidor e por renderizar a interface gráfica com base nos estados recebidos do servidor.
- Imagens (Assets): A maior parte dos recursos gráficos (como carros, fundo da estrada, ecrã de Game Over e elementos de interface) foram adaptados a partir de pacotes de assets gratuitos disponíveis em plataformas comunitárias como o OpenGameArt.
- Sons: Os efeitos sonoros de explosão, música de fundo e de perda foram retirados de bibliotecas gratuitas e isentas de royalties.
Toda a lógica do jogo ocorre do lado do servidor (ficheiro servidor/estrutura_de_dados.py na classe GameRoomState). A cada atualização (tick), o servidor envia um dicionário de estado aos clientes contendo as seguintes variáveis que controlam o jogo:
-
Gestão da Sala (
room)room_name(String): Nome da sala de jogo.creator_id(String): Identificador (IP:Porta) do líder da sala, que tem a permissão de iniciar o jogo.status(String): Estado atual da sala ("waiting","playing","game_over").
-
Jogadores (
jogadores) Um dicionário contendo os dados em tempo real de cada jogador presente na sala:id(String): Endereço (IP:Porta) único do jogador.nome(String): O nickname escolhido pelo jogador.posicao(Tuplo(x, y)): Coordenadas de posição atual do carro no ecrã.vidas(Inteiro): Número de vidas restantes (inicia com 3).pontuacao(Inteiro): O score atual ganho por tempo de sobrevivência.ativo(Booleano): SeTrue, o jogador ainda está em jogo. SeFalse, perdeu todas as vidas e aguarda que o líder reinicie a ronda.hit_flag(Booleano): Sinaliza uma colisão no último instante. Serve para informar o cliente que deve reproduzir o som de colisão (explosão).
-
Obstáculos e Dificuldade (
obstaculos,obstacle_speed,score_tick)obstaculos(Lista de Dicionários): Lista de todos os obstáculos no ecrã. Cada obstáculo contém a sua coordenadax,y, otipo(para escolher o sprite correspondente no cliente) e o seutamanho(para os limites de colisão).obstacle_speed(Inteiro): Velocidade atual a que os obstáculos se deslocam na vertical. Esta variável aumenta periodicamente com o tempo de jogo.score_tick(Inteiro): Temporizador e controlador do tempo do servidor para escalonar a velocidade e dificuldade à medida que a partida avança.
(Nota: Quando os clientes não estão numa sala, o servidor envia um estado do tipo lobby contendo uma lista das salas abertas, criadores, estado da sala e número de jogadores presentes.)
Para que se possa jogar este jogo em sala de aula usando duas máquinas em redes diferentes sem ter que configurar port forwarding no router local, propõe-se a utilização da ferramenta Ngrok, que cria um túnel seguro para o servidor local através da internet.
-
Descarregar e Autenticar o Ngrok:
- Aceder a ngrok.com e criar uma conta gratuita.
- Descarregar e instalar o cliente do Ngrok adequado ao seu sistema operativo.
- Configurar o Authtoken (fornecido no painel de controlo do Ngrok) no terminal da máquina onde o Servidor vai correr:
ngrok config add-authtoken <TOKEN>
-
Iniciar o Servidor Localmente:
- Na máquina do anfitrião (Host), inicie o servidor Python normalmente. Por padrão, o jogo corre na porta
50000(definida no código):python -m servidor
- Na máquina do anfitrião (Host), inicie o servidor Python normalmente. Por padrão, o jogo corre na porta
-
Criar o Túnel TCP com o Ngrok:
- Ainda na máquina do anfitrião, abra um novo terminal e crie um túnel TCP apontado para a porta local
50000:ngrok tcp 50000
- O Ngrok irá gerar um URL de reencaminhamento. No ecrã do terminal, procure por uma linha semelhante a:
Forwarding tcp://0.tcp.eu.ngrok.io:12345 -> localhost:50000
- Ainda na máquina do anfitrião, abra um novo terminal e crie um túnel TCP apontado para a porta local
-
Configurar os Clientes nas Outras Máquinas:
- Nos computadores dos outros colegas (ou na própria máquina para testar), abram o ficheiro
cliente/cliente.py. - Substituam as variáveis
HOSTePORT(por volta da linha 13/14) pelas geradas pelo Ngrok.- Seguindo o exemplo acima, a alteração ficaria:
HOST = '0.tcp.eu.ngrok.io' PORT = 12345
- Seguindo o exemplo acima, a alteração ficaria:
- Gravem o ficheiro e iniciem o cliente:
python -m cliente
- Nos computadores dos outros colegas (ou na própria máquina para testar), abram o ficheiro
Com esta configuração, qualquer colega na sala de aula (ou noutra rede qualquer) conseguirá ligar-se ao servidor.