Como Fazer um Jogo Multiplayer no GameMaker

Entenda como fazer um jogo multiplayer no GameMaker: modelo host/cliente, sockets, evento Async Networking e buffers explicados de forma direta.
Como Fazer um Jogo Multiplayer no GameMaker
Se você chegou aqui querendo saber como fazer um jogo multiplayer no GameMaker, a primeira coisa honesta que preciso dizer é: o GameMaker te entrega as ferramentas de rede, mas não te entrega o multiplayer pronto. Existe uma diferença enorme entre as duas coisas, e entender essa diferença agora vai te poupar semanas de frustração. O motor te dá sockets, um evento que avisa quando dados chegam e uma forma de empacotar informação para mandar pela rede. A lógica de "quando o jogador A anda, o jogador B precisa ver isso acontecer" é você que escreve, linha por linha.
Este post é conceitual. Não vou colar código aqui, porque o objetivo é você sair entendendo o fluxo de rede na cabeça. Depois de entender o fluxo, a documentação oficial das funções faz muito mais sentido, e você para de copiar tutorial sem saber o que cada linha faz. Vamos do começo, do jeito que um iniciante realmente pensa quando encara isso pela primeira vez.
O modelo mental: servidor e cliente
Antes de qualquer função, você precisa de um modelo mental. O mais comum, e o mais fácil de raciocinar, é o modelo servidor/cliente. Nele, uma das partes é o servidor (muita gente chama de host) e as outras são clientes.
O servidor é quem manda. Ele mantém a versão "oficial" do jogo: onde cada jogador está, quem tomou dano, quem pegou o item, quem ganhou. Os clientes são as janelas do jogo que cada pessoa vê. Um cliente não decide nada sozinho de forma definitiva. Ele diz ao servidor "quero andar para a direita" e espera o servidor confirmar. Quando o servidor responde com o novo estado, o cliente desenha aquilo na tela.
Pode parecer burocrático fazer o cliente "pedir permissão" para tudo, mas existe um motivo forte para isso, e vamos chegar nele quando falar de autoridade. Por ora, guarde a imagem: um servidor no centro, vários clientes conversando com ele, e o servidor como fonte da verdade.
Existe uma variação muito usada por quem está começando, que é o host ser também um jogador. Ou seja, a mesma pessoa roda o servidor e um cliente na mesma máquina. Isso simplifica a vida no início e é exatamente o que você vai fazer nos primeiros testes.
Abrir o socket e conectar
Agora a parte que faz a rede existir de fato: o socket. Um socket é a "tomada" por onde os dados entram e saem. No GameMaker, o servidor cria um socket e fica escutando numa porta, esperando alguém se conectar. A função que faz isso é a família network_create_socket, onde você define o tipo de conexão (TCP ou UDP, e já falo da diferença) e a porta em que o servidor vai ouvir.
Do lado do cliente, o passo é diferente: em vez de escutar, ele se conecta a um endereço. A função network_connect recebe o IP do servidor e a porta, e tenta estabelecer a ligação. Se der certo, existe um canal aberto entre os dois.
Sobre TCP e UDP, o resumo prático: TCP é a conexão que garante entrega e ordem dos dados, ao custo de ser um pouco mais lenta e menos flexível. UDP é mais rápido e leve, mas não garante que tudo chega nem que chega na ordem. Para o seu primeiro multiplayer, TCP costuma ser mais tranquilo de raciocinar, porque você não precisa lidar com pacote perdido ainda. Jogos de ação rápida geralmente migram para UDP depois, quando latência importa muito, mas isso é otimização de quem já tem o básico rodando. Não comece por aí.
Um detalhe que confunde iniciante: o IP. Quando servidor e cliente estão na mesma máquina, o endereço é o endereço local da própria máquina. Quando estão em máquinas diferentes na mesma casa, é o IP local da rede. Quando estão em casas diferentes, aí a conversa vira redirecionamento de porta ou um servidor na nuvem, e é um assunto à parte que você não precisa resolver no primeiro dia.
O evento Async Networking: onde os dados chegam
Aqui está o coração do multiplayer no GameMaker, e é o ponto que mais gente demora a entender. A rede é assíncrona. Isso significa que você não "pergunta" à rede se chegou algo dentro do passo normal do jogo. Em vez disso, o GameMaker te avisa quando algo aconteceu, através do evento Async Networking.
Pense assim: sempre que um cliente se conecta, se desconecta, ou manda dados, o motor dispara esse evento no objeto responsável pela rede. Dentro do evento, você recebe um pacote de informações descrevendo o que aconteceu (foi uma nova conexão? foi uma mensagem com dados? foi uma queda?). É ali, e só ali, que você trata o que chegou da rede.
Essa é uma mudança de mentalidade importante. Muita gente que vem de single player pensa em código que roda "de cima para baixo" a cada passo. Na rede, boa parte da sua lógica de recebimento vive dentro desse evento reativo, esperando ser chamada. O servidor, por exemplo, vai tratar dentro do Async Networking a chegada de "o cliente 2 quer se mover", processar isso e, em seguida, avisar todo mundo do novo estado.
Mandar e receber pacotes com buffers
Se o socket é o cano, os buffers são as caixas que você coloca dentro do cano. Você não manda "o objeto jogador" pela rede. Você manda números e textos crus, empacotados numa ordem que os dois lados combinaram.
O fluxo, em prosa, é assim. Do lado de quem envia: você cria um espaço de memória com buffer_create, escreve os valores nele com buffer_write (por exemplo, um número dizendo "isto é uma atualização de posição", depois o id do jogador, depois o x, depois o y) e manda esse buffer pela rede. Do lado de quem recebe, dentro do evento Async Networking, você lê os valores com buffer_read na mesma ordem exata em que foram escritos. Se a ordem ou o tipo dos valores não baterem, você lê lixo, e o bug é silencioso e chato de achar.
Por isso, o conselho é: defina desde cedo um "cabeçalho" para cada mensagem. Um número no começo de cada pacote que diz que tipo de mensagem é aquela. Assim, ao ler, a primeira coisa que você faz é olhar esse número e decidir como interpretar o resto. "É tipo 1? Então é posição, leia id, x e y. É tipo 2? Então é dano, leia id e valor." Esse pequeno protocolo caseiro é o que segura o multiplayer inteiro.
E aqui aparece de novo o aviso honesto: esse desenho de mensagens é seu. O GameMaker não adivinha o que você quer sincronizar. Você é quem decide o que cabe em cada pacote, com que frequência mandar e como o outro lado reage. É trabalhoso e é por isso que multiplayer tem fama de difícil. A boa notícia é que, uma vez que você tem um tipo de mensagem funcionando de ponta a ponta, os outros seguem o mesmo molde.
Autoridade: o servidor é quem decide
Voltando à ideia de "pedir permissão". Autoridade é o conceito de quem tem a palavra final sobre o estado do jogo. Numa arquitetura sã, essa palavra é do servidor.
Por quê? Porque se cada cliente decidir sozinho a própria posição, seu placar, seu dano, você abre a porta para trapaça e para inconsistência. Dois clientes podem discordar sobre quem pegou o item. Alguém pode editar o cliente para dizer "tenho 999 de vida". Com o servidor como autoridade, o cliente só envia intenções ("quero andar", "quero atirar") e o servidor valida, aplica no estado oficial e devolve o resultado para todos. Se o cliente disser uma bobagem, o servidor simplesmente ignora.
Para o seu primeiro projeto, você não precisa de anti-trapaça sofisticado. Mas adotar desde já o hábito de deixar o servidor decidir as coisas importantes vai te economizar uma refatoração dolorosa lá na frente. Comece pequeno, mas comece com a autoridade no lugar certo.
O conselho mais útil: teste local com duas instâncias
Antes de sonhar com servidor na nuvem, com muitos jogadores, com salas e login, faça a coisa mais simples que prova que sua rede funciona: rode duas instâncias do jogo na mesma máquina. Uma vira host, a outra conecta no endereço local. Se você conseguir ver o movimento de uma janela refletido na outra, você tem um multiplayer de verdade, mesmo que feio e minúsculo.
Esse teste local é ouro por dois motivos. Primeiro, ele elimina a nuvem, a internet, o firewall e mil variáveis externas da equação, então quando algo quebra você sabe que o problema está na sua lógica, não na infraestrutura. Segundo, ele é rápido de iterar: mudou o código, roda de novo, testa. A nuvem entra só depois, quando o local já está sólido, e quando entra você vai querer entender o custo de servidor de um jogo online com calma antes de assinar qualquer coisa.
E siga o conselho que mais gente ignora: sincronize pouca coisa no começo. Não tente sincronizar animação, física, inventário e chat no primeiro dia. Sincronize a posição de um quadrado que se move. Só isso. Quando um quadrado anda numa janela e você vê na outra, você validou o pipeline inteiro (socket, conexão, evento assíncrono, buffer de ida e de volta). A partir daí, cada novo dado é uma variação do que você já fez.
Onde isso se encaixa no seu aprendizado
Multiplayer é um tema que atravessa qualquer motor, não só o GameMaker. O modelo servidor/cliente, a ideia de autoridade e o empacotamento de dados são os mesmos conceitos que você veria ao fazer um jogo multiplayer na Unity, só que com outras ferramentas. Se você quiser a visão geral de rede antes de ir fundo em qualquer engine, vale ler o guia pilar sobre como fazer um jogo multiplayer, que amarra esses conceitos sem prender você a uma tecnologia.
Uma última reflexão honesta. Rede é uma daquelas áreas em que aprender solto, no tutorial avulso, costuma render horas perdidas em bugs bobos de ordem de buffer e de quem tem autoridade. Se você percebe que trava sozinho nesse tipo de fundamento, talvez valha comparar o caminho de aprender a criar jogos sozinho ou com um curso, porque ter alguém apontando o erro conceitual no momento certo muda bastante a velocidade.
Resumindo o caminho: escolha o modelo servidor/cliente, abra o socket e conecte, trate tudo que chega dentro do evento Async Networking, empacote seus dados em buffers com um cabeçalho claro, deixe o servidor decidir o que importa e teste local com duas instâncias antes de qualquer nuvem. Comece com um quadrado que anda. O resto é repetição do mesmo padrão, e você chega lá.
Perguntas frequentes
O GameMaker tem funções nativas de rede?
Tem. O GameMaker traz funções de baixo nível para criar sockets TCP e UDP, abrir conexões e enviar dados. Ele também dispara um evento assíncrono de rede quando algo chega. O que ele não traz pronto é a lógica de sincronização, que você monta na mão.
Preciso de um servidor na nuvem para começar?
Não para começar. Você consegue rodar o servidor e o cliente na mesma máquina, em duas instâncias, e testar tudo local. A nuvem só entra quando você quer que pessoas de casas diferentes joguem juntas, e isso é um passo depois.
Qual a diferença entre servidor e cliente aqui?
O servidor (ou host) é quem abre o socket e espera conexões. O cliente é quem se conecta a esse endereço. Numa arquitetura comum, o servidor decide o estado do jogo e os clientes só mandam intenções e desenham o que recebem.
Por que dizem que multiplayer no GameMaker é trabalhoso?
Porque o GameMaker te dá o cano por onde os dados passam, mas não a lógica. Você define o que enviar, como empacotar em buffers, como ler do outro lado e como resolver conflitos. Essa parte é sua e é onde mora o trabalho.
O que são os buffers na rede do GameMaker?
Buffers são blocos de memória onde você escreve os dados antes de enviar e de onde você lê os dados que chegam. Você escolhe a ordem e o tipo de cada valor, e o outro lado precisa ler exatamente na mesma ordem para entender.
Por quantos jogadores devo começar?
Comece por dois. Um host e um cliente já te forçam a resolver conexão, envio, recebimento e autoridade. Depois que dois funcionam de forma estável, aumentar o número é mais uma questão de organização do que de conceito novo.


