Arena RPG Maker
Olá, visitante!
Seja bem-vindo ao fórum Arena RPG Maker, caso queira aprender sobre criação de jogos, está no fórum certo. Esperamos que possa aprender tanto quanto possa nos ensinar aqui.

Atenciosamente,
Equipe Arena RPG Maker.
Arena RPG Maker

Estamos de volta o/ ... Ou não.Eu amo a -Dark
Doações para o fórum abertas, clique aqui e saiba mais.
Últimos assuntos
» Pokémon Genesis Online! (PGO)
Qua 05 Jul 2017, 17:08 por Lexar

» Tileset Converter to MV
Sex 12 Maio 2017, 13:07 por Douggi

» [Dúvida] Como tirar a porcentagem de esquiva
Ter 09 Maio 2017, 22:15 por Neil Flame Runner

» Pack Resources, Sprites e etc
Qua 23 Dez 2015, 09:30 por raydengv

» Download RPG Maker 2003 + RTP em português
Ter 22 Dez 2015, 08:14 por ::KimMax::

» Fantasy Art Online
Dom 18 Out 2015, 16:42 por daviih123

» Você vai ter medo do Nerve gear?
Sab 25 Jul 2015, 16:02 por Kirito-kun

» O Barato é louco
Sab 27 Jun 2015, 15:26 por Halt

» Download RPG Maker 2000 + RTP em português
Qui 21 Maio 2015, 19:28 por Wismael

» Divulgando meu grupo e página do Facebook
Ter 19 Maio 2015, 13:06 por Halt


Você não está conectado. Conecte-se ou registre-se

Ver o tópico anterior Ver o tópico seguinte Ir em baixo  Mensagem [Página 1 de 1]

Halt

avatar
Administrador
Administrador
Tutorial – Como fazer um jogo multiplayer online
Por Janx
Parte II: Fazendo um Jogo
Antes de iniciar:

Na primeira parte já aprendemos bem como é o conceito para fazer um jogo online, agora iremos ver a parte pratica. Usaremos a 39Dll e o Game Maker 7 PRO.
É necessário saber GML em nível intermediário ou superior para completar o tutorial sem grandes dificuldades. Todo o código é explicado em maior parte direto nos comentários, apenas alguns detalhes são explicados fora do código.

Um novo projeto:
Para fazer o jogo, vamos precisar importar alguns scrips, mas como são vários e o Game Maker não importa eles separando por pastas vou disponibilizar um projeto com os scripts já prontos.

Primeiramente precisaremos desse pacote: [Você precisa estar registrado e conectado para ver este link.] [Contem: Projeto.gmk e 39Dll.dll]
Depois de baixá-lo, extraia para uma pasta qualquer. Serão extraídos dois arquivos:

Projeto.gmk: Projeto já iniciado contendo apenas as funções da 39Dll.

39Dll.dll: A DLL deve estar sempre acompanhada do executável do jogo, é nela que o jogo encontra as funções a serem executadas.

Abra o Projeto e de uma olhada nos scripts, são vários não é mesmo? A maioria nós nem iremos usar, mas não iremos apagar nenhum porque não sabemos se vamos precisar deles no futuro.

O menu:
Antes de qualquer coisa, vamos fazer um menu bem simples só para testar mesmo. Faça 2 objetos: obj_btmHost e obj_btmClient e crie uma sprite para cada um. Para isso você talvez queira saber o que eles farão então aqui vai uma pequena explicação:

obj_btmHost: Esse botão será usado para criar um Servidor, fazer um Host. Lembra da primeira aula? O Servidor é onde os jogadores conectam.

obj_btmClient: Agora ficou fácil, esse é o Client, ao clicar nesse botão será possível conectar em algum servidor.

Esses são apenas botões, não terão funções muito complexas. Antes de começarmos a adicionar código, crie mais 2 objetos (Esses não precisam de sprites) e marque-os como Persistent:
obj_Host
obj_Client


Marcar/Desmarcar multi-citação
Responder com citação
Enviar um alerta desta mensagem a um administrador ou moderador
Bloquear os alertas deste post

Qualidade Tutorial - Como fazer um jogo multiplayer online - Parte II

Mensagem por Janx em Ter Jan 25, 2011 2:22 pm
Tutorial – Como fazer um jogo multiplayer online
Por Janx

Parte II: Fazendo um Jogo

Antes de iniciar:
Na primeira parte já aprendemos bem como é o conceito para fazer um jogo online, agora iremos ver a parte pratica. Usaremos a 39Dll e o Game Maker 7 PRO.
É necessário saber GML em nível intermediário ou superior para completar o tutorial sem grandes dificuldades. Todo o código é explicado em maior parte direto nos comentários, apenas alguns detalhes são explicados fora do código.

Um novo projeto:
Para fazer o jogo, vamos precisar importar alguns scrips, mas como são vários e o Game Maker não importa eles separando por pastas vou disponibilizar um projeto com os scripts já prontos.

Primeiramente precisaremos desse pacote: Download [Contem: Projeto.gmk e 39Dll.dll]
Depois de baixá-lo, extraia para uma pasta qualquer. Serão extraídos dois arquivos:

Projeto.gmk: Projeto já iniciado contendo apenas as funções da 39Dll.

39Dll.dll: A DLL deve estar sempre acompanhada do executável do jogo, é nela que o jogo encontra as funções a serem executadas.

Abra o Projeto e de uma olhada nos scripts, são vários não é mesmo? A maioria nós nem iremos usar, mas não iremos apagar nenhum porque não sabemos se vamos precisar deles no futuro.

O menu:
Antes de qualquer coisa, vamos fazer um menu bem simples só para testar mesmo. Faça 2 objetos: obj_btmHost e obj_btmClient e crie uma sprite para cada um. Para isso você talvez queira saber o que eles farão então aqui vai uma pequena explicação:

obj_btmHost: Esse botão será usado para criar um Servidor, fazer um Host. Lembra da primeira aula? O Servidor é onde os jogadores conectam.

obj_btmClient: Agora ficou fácil, esse é o Client, ao clicar nesse botão será possível conectar em algum servidor.

Esses são apenas botões, não terão funções muito complexas. Antes de começarmos a adicionar código, crie mais 2 objetos (Esses não precisam de sprites) e marque-os como Persistent:
obj_Host
obj_Client


Vamos começar pelo botão de host:
Faça um evento “Mouse Left Released” e nele adicione um “Execute a piece of Code”.
Escreva o seguinte:

//Botão para fazer um Servidor
global.ServerName = get_string("Digite o nome do Servidor","");
instance_create(0,0,obj_Host);
Não tem muito segredo, é um código bem simples. Não vou explicar, pois se você não entendeu o que foi feito aqui você deve estudar mais GML antes de querer fazer um jogo online.
O botão do Client é praticamente a mesma coisa, só mude o código dele para o seguinte:

//Botão para conectar em um Servidor
global.connectIP = get_string("Digite o IP do Servidor","127.0.0.1");
instance_create(0,0,obj_Client);
Simples também.
Agora crie um outro objeto “Controlador” de sua preferência, eu gosto de chamá-lo de GAME (Deixe ele como Persistent). Nesse novo objeto, adicione um evento Create e coloque o seguinte código:

global.Nick = get_string("Digite seu Nick: ",""); //Pegar o nick do jogador
global.Server = 0; //Guarda o Socket do Servidor.
global.MyID = -1; //ID online do jogador
global.MaxPlayers = 0;

dllinit("39dll.dll",1); //Inicializar funções de Sockets da DLL.
O código junto dos comentários já está explicado, não vou entrar em mais detalhes aqui.
Feito isso coloque esse objeto na PRIMEIRA room do jogo, se você ainda não criou nenhuma, faça-o agora, vou usar ela como menu então a minha vai ter nome rm_Menu. O GAME deve ser o primeiro objeto a ser criado. Aproveite e monte o seu menu como quiser o meu ficou assim:


Já estamos prontos para iniciar a programar o Servidor.

Iniciando o Servidor:
Vamos para o objeto obj_Host. No evento Create adicione o seguinte:

//Criar servidor
global.Server = tcplisten(5068,5,1); //Inicializa o Servidor, fica em espera por conexões na porta 5068.
//Você pode mudar os argumentos dessa função como preferir.
//tcplisten(PORTA,CONEXÕES SIMUNTANEAS, MODO);
//PORTA -> Porta para conectar
//CONEXÕES SIMUNTANEAS -> Antes do jogador entrar mesmo no jogo, sua conexão deve ser aceita, enquanto isso ele ficara na "espera".
//Isso é para quantos você quer deixar na espera. Não é preciso um valor muito alto.
//MODO -> deixe o valor em 1, senão seu servidor ficará travado até alguem conectar

if (!global.Server) //Caso não tenha inicializado corretamente passar uma mensagem de erro.
{instance_destroy();
show_message("Erro ao criar o servidor");
exit;}

global.MaxPlayers = 10; //Limite de jogadores

//Criar lista de Jogadores.
for (i = 0; i < global.MaxPlayers; i += 1)
{
players[i,PL_SOCK] = -3; //Socket do player [Só usado no Host]
players[i,PL_NICK] = ""; //Nick do player
}

//Adicionar informações do servidor na lista [Servidor sempre é o 0]
players[0,PL_SOCK] = global.Server;
players[0,PL_NICK] = global.Nick;
global.MyID = 0;

room_goto(rm_WaitingRoom); //Depois de inicializar tudo corretamente ir para a tela de espera.
//Esse objeto é "Persistent", pois isso não será destruido na troca de rooms.
Comentei bastante o código para ficar fácil de entender. Mas temos que adicionar algumas Constantes ao nosso jogo, repare que ao criar a lista de jogadores foram usados os seguintes valores: PL_SOCK e PL_NICK, esses são Constantes e devem ser declarados para o Game Maker.
Vá em Global Game Settings, aba Constants. Insira os 3 valores da seguinte forma:
Name (Nome) Value (Valor)
PL_NICK 1
PL_SOCK 0

Muito bem, o evento Create está completo.

Conectando no Servidor:
Vamos para o obj_Client para iniciar a conexão, no Create coloque o código:
global.Server = tcpconnect(global.connectIP,5068,1);

if (!global.Server) //Se não conectarmos sair e exibir mensagem de erro
{instance_destroy();
show_message("Erro ao conectar");
exit;}

room_goto(rm_WaitingRoom);
Esse é bem curto, apenas conectamos no servidor e verificamos se foi possível a conexão. Se conectar vamos para a próxima tela, senão ficamos por aqui e exibimos uma mensagem de erro.

A estrutura de uma mensagem:
Antes de seguirmos para o próximo item, é preciso saber como é a estrutura das mensagens trocadas entre Client e Servidor. Na verdade é muito simples, mas sempre varia de mensagem para mensagem. A estrutura básica é assim:

Primeiros dois bytes = Tamanho da mensagem em bytes.
Terceiro byte = ID da mensagem. Serve para identificar qual o tipo de mensagem é essa, para que possamos manipulá-la corretamente.
Restantes = “Mensagem”.

Vamos ver um exemplo em que eu envio uma String “Testando” que tem ID de mensagem 5:

clearbuffer(); //Limpa o buffer interno, aqui é como uma Carta que vamos enviar, primeiro precisamos de um papel em branco, não é?
writebyte(5); //ID
writestring(“Testando”); //Mensagem
sendmessage(SOCKET); //Envia a mensagem para o Socket

Ué, mas cade os dois primeiros bytes de tamanho?
Esses são adicionados automaticamente pela DLL. Você não precisa se preocupar com eles.

Mas eles não são inúteis? Vou usar eles só para deixar a mensagem maior?
2 Bytes é pouca coisa, eles não vão te atrapalhar, eles também são lidos automaticamente. Se você acha que esses 2 bytes vão causar lags, está enganado. Esses bytes são necessários, é com eles que a DLL pode saber qual é o tamanho da mensagem para poder escrevê-la no buffer (Para podermos manipular depois). Imagine a mensagem recebida:

[Tamanho Total = 11 bytes]
Byte1 Valor: 9 (11 bytes contando esses 2, mas para o buffer eles não são contados)
Byte2

Os seguintes são carregados no buffer:
Byte3 ---- Valor: 5
Byte4 até Byte 11 ---- Valor: “Testando”

Nosso buffer ficaria assim:
Byte1 = 5
Byte2 = T
Byte3 = e
Byte4 = s
Byte5 = t
Byte6 = a
Byte7 = n
Byte8 = d
Byte9 = o

A leitura do buffer seria dessa forma:
IDdaMensagem = readbyte(); //Le o primeiro byte
Mensagem = readstring(); //Le todo o resto

No final teríamos os valores:

IDdaMensagem = 5
Mensagem = “Testando”

Ao usar o readbyte, readshort ou qualquer outra função de leitura os bytes são lidos e RETIRADOS do buffer (As funções retornam esses bytes removidos do buffer).
Então em muitos casos é preciso guardar esses bytes em alguma variável, mesmo que temporária.

Aceitando novas conexões:
Para aceitar novas conexões não é muito difícil, o código é bem curto. Vamos para o evento Step do objeto obj_Host e adicione o seguinte código:
//Aceitar novas conexões
var i, sock, newPL;
sock = tcpaccept(global.Server, 1);
if (!sock) //Se não existirem novas conexões
{exit;} //sair do script

for (i = 0; i < global.MaxPlayers; i+=1)
{
if (!players[i,PL_SOCK])
{
newPL = i;
break;
}
}

if newPL //Tem vagas no servidor
{
players[newPL,PL_SOCK] = sock;

//Enviar uma mensagem para o jogador, falando que ele foi aceito
clearbuffer(); //Limpar o buffer
writebyte(MSG_CONEXAO_ACEITA); //Byte identificador da mensagem
writebyte(newPL); //Enviar o ID do jogador
writebyte(global.MaxPlayers); //Enviar quantidade maxima de jogadores
sendmessage(sock); //Enviar mensagem
}
else //Servidor cheio
{
//Enviar uma mensagem para o jogador, falando que o servidor já está cheio e ele não pode se conectar.
clearbuffer(); //Limpar o buffer
writebyte(MSG_SERVIDOR_CHEIO); //Byte identificador da mensagem
sendmessage(sock); //Enviar mensagem

closesocket(sock);
}
Esse código é um pouquinho mais complicado. Agora nós recebemos a conexão do jogador e se houver espaço no servidor permitimos que ele entre, caso contrário enviamos uma mensagem falando que o servidor está cheio e terminamos a conexão com ele.
Note que aqui temos mais duas constantes:
MSG_CONEXAO_ACEITA
MSG_SERVIDOR_CHEIO

Crie elas também, os valores você que escolhe, mas eles NÃO podem ser maiores que 255 nem menores do que 0! Ou seja, são valores entre 0 e 255. Perceba que essas constantes tem um prefixo diferente das outras duas, elas começam com um “MSG_”, fizemos isso para identificar o tipo de uso para ela. Então para identificar as mensagens vamos usar constantes com prefixo MSG_. Logo não faz diferença se elas possuem o mesmo valor de outra constante, contando que não seja uma constante do tipo MSG_. Criei as minhas assim:
Nome Valor
MSG_CONEXAO_ACEITA 0
MSG_SERVIDOR_CHEIO 255


Recebendo as mensagens iniciais:

Ok, agora precisamos programar para o Client receber as mensagens do servidor, no evento Step do obj_Client coloque o seguinte:
//Receber mensagens do servidor
var size, msgID;
size = 1;

while (size)
{
size = receivemessage(global.Server); //Retorna a quantidade de bytes recebidos

if (!size) //Se não recebermos nada, sair desse script.
{exit;}

msgID = readbyte(); //Lemos o primeiro byte da mensagem, ou seja o ID da mensagem.

switch (msgID)
{
case MSG_CONEXAO_ACEITA: //Fui aceito no servidor
global.MyID = readbyte(); //Pegamos o meu ID
global.MaxPlayers = readbyte(); //Lemos a quantidade de jogadores maxima no servidor

//Criar lista de Jogadores.
for (i = 0; i < global.MaxPlayers; i += 1)
{
//players[i,PL_SOCK] = -3; //Socket do player [Só usado no Host]
players[i,PL_NICK] = ""; //Nick do player
}
players[global.MyID,PL_NICK] = global.Nick;

//Para dar continuidade agora vamos enviar o meu nick para o servidor
//e ele retornara com o nick de todos os jogadores
clearbuffer();
writebyte(MSG_PLDATA);
writestring(global.Nick);
sendmessage(global.Server);
break;

case MSG_SERVIDOR_CHEIO:
closesocket(global.Servidor); //Fechamos a conexão
show_message("Servidor lotado"); //Exibimos o erro
instance_destroy();
room_goto(rm_Menu); //Voltamos para o menu
exit;
break;
}
}
Lembre-se de adicionar a constante: MSG_PLDATA.
Agora já temos o sistema inicial pronto, agora é só troca de mensagens. Ainda precisamos fazer para o Servidor receber as mensagens, mas é bem parecido com o sistema do Client, possui apenas algumas mudanças.

Recebendo as mensagem do Client:
Para receber as mensagens do client vamos usar o obj_Host, no step adicione outro execute a piece of code, para não deixar o primeiro muito comprido e facilitar a procura de partes especificas no código depois se for necessário.
Assim como o do client, adicionando apenas um loop for e editando a mensagem recebida como necessário:
//Receber mensagens do Client
var size, msgID;

for (iPL = 1; iPL < global.MaxPlayers; iPL += 1) //Precisamos receber a mensagem de cada jogador
{ //Usamos "iPL" pois depois serão feitos outros loops e usar a variavel "i" pode gerar conflitos
size = 1;
while (size)
{
size = receivemessage(players[iPL,PL_SOCK]); //Receber a mensagem do socket de cada player

if (!size) //Se não recebermos nada, sair desse script e passar para o próximo player
{break;}

msgID = readbyte(); //Lemos o primeiro byte da mensagem, ou seja o ID da mensagem.

switch (msgID)
{
case MSG_PLDATA: //Pegar dados do jogador
var nick;
nick = readstring(); //Ler o nick do jogador.

//Agora guardamos o nick na variavel do jogador:
players[iPL, PL_NICK] = nick;
//Não precisamos guardar o ID porque isso já foi feito quando ele se conectou!

//Agora vamos repassar para os outros jogadores:
clearbuffer();
writebyte(MSG_PLDATA);
writebyte(iPL); //Os outros jogadores só recebem dados do servidor, então precisam saber o ID de qual player são esses dados
writestring(nick);
for (i=1; i < global.MaxPlayers; i+=1) //Como são varios jogadores, precisamos enviar para todos eles
{ //Usando um loop for isso fica bem facil! Repare que começamos do 1, porque o 0 é sempre o servidor.
if (i != iPL) //Não precisamos repassar a mensagem para quem a enviou
{sendmessage(players[i,PL_SOCK]);}
}

//O Hoster possui os dados de todos os jogadores então ele mesmo pode repassar os nicks dos demais players
for (i = 0; i < global.MaxPlayers; i += 1)
{
if (i != iPL) //Não enviar o nick do proprio jogador para ele mesmo
{
clearbuffer();
writebyte(MSG_PLDATA);
writebyte(i);
writestring(players[i,PL_NICK]);
sendmessage(players[iPL,PL_SOCK]);
}
}
break;
}
}
}
Agora precisamos fazer os Clients receberem essa mensagem, vamos voltar para o obj_Client e adicionar uma outra mensagem a ser recebida, dessa vez vou passar apenas a parte que será adicionada:

case MSG_PLDATA:
players[readbyte(), PL_NICK] = readstring();
break;

Esse é bem curto, não é? Acho que nem precisamos de explicação. Apenas pegamos o ID de quem enviou a mensagem e usamos o valor na posição da array, depois lemos o Nick enviado par atribuir o valor na array.

A partir desse momento já são recebidos todos os dados de cada jogador e a base está pronta. Vamos adicionar um evento Draw no objeto GAME apenas para visualizar a lista e testarmos o código:

if room = rm_WaitingRoom
{
draw_text(200,16,"Tela de Espera");
}

if instance_exists(obj_Client)
{
for (i=0; i < global.MaxPlayers; i += 1)
{
draw_text(5,32+i*16, string(i)+" "+obj_Client.players[i,PL_NICK]);
}
}
else if instance_exists(obj_Host)
{
for (i=0; i < global.MaxPlayers; i += 1)
{
draw_text(5,32+i*16, string(i)+" Sock: "+string(obj_Host.players[i,PL_SOCK])+" Nick: "+obj_Host.players[i,PL_NICK]);
}
}

Para testar, crie o executável do jogo, copie ele e a DLL para outra pasta, de forma que você tenha duas cópias do jogo. Abra as 2, em cada uma você coloca um Nick diferente, em uma das telas você Cria um servidor, na outra Conecta com o IP 127.0.0.1.
Se tudo correr bem você verá uma lista nas duas telas, na do servidor contendo o valor do socket e Nick de cada jogador, na do client uma lista contendo apenas os Nicks. Se você recebeu algum erro, volte o tutorial e confira todos os códigos novamente.


Vou terminar essa aula por aqui. Na próxima colocaremos um chat e um botão na sala para começarmos o “jogo”, que será apenas um circulo de cada jogador se movendo pela tela. Finalizando o tutorial por completo.

Recomendo que você leia as descrições das funções dos scripts Buffer -> Writing e Reading. Para entender melhor como funciona cada um dos tipos de dados.

Você não vai postar uma engine do tutorial?


__________________________________________
[Você precisa estar registrado e conectado para ver este link.]
Ei Convidado, sim você mesmo! Ajude o fórum à crescer postando coisas úteis, dê sugestões para melhorar-mos e divulgue o fórum.

Step inside, see the devil in I.

Gifts-
[Você precisa estar registrado e conectado para ver este link.] - [Você precisa estar registrado e conectado para ver este link.] - [Você precisa estar registrado e conectado para ver este link.] - [Você precisa estar registrado e conectado para ver este link.] - [Você precisa estar registrado e conectado para ver este link.]

Zerei a internet
Ver perfil do usuário http://arenarpgmaker.eclipserpg.com

~Razor

avatar
Membro de Honra
Membro de Honra
boa , pra quem prentende fazer jogos on , vou ver as outras partes da tuto vlw por disponibilizar L Death Note


__________________________________________


Principal Engine :Game Maker
Especialidade : Roteirista
Jogos: The old mine (Game Maker)
Site(Fórum): [Você precisa estar registrado e conectado para ver este link.]
Ver perfil do usuário http://lostmakers.web-rpg.com/

Ver o tópico anterior Ver o tópico seguinte Voltar ao Topo  Mensagem [Página 1 de 1]

Permissão deste fórum:
Você não pode responder aos tópicos neste fórum