www.programadoresdejogos.com

[P D J - Programadores e Desenvolvedores de Jogos]
Bem-vindo: Sex Set 10, 2010 12:06 am

Todos os horários são GMT - 3 horas




Criar novo tópico Responder  [ 4 mensagens ] 
Autor Mensagem
 Título: Web Games - Long Polling com PHP
MensagemEnviado: Sáb Mai 01, 2010 1:05 pm 
Offline
Colaborador PDJer
Colaborador PDJer
Avatar do usuário

Registrado em: Sex Jan 18, 2008 4:58 pm
Mensagens: 867
Localização: Brazil
Estava pensando em fazer um jogo (apenas testes) visão top-down (aka, tibia, ragnarok, etc..) , mas pelo proprio navegador usando long-polling.

Mas logo de inicio percebo alguns problemas (talvez até por causa da tecnologia: PHP)

Primeiro teste foi criar um long-polling simples.
No servidor, morria a hora com milesimos.
Tempo de resposta do ajax: 1ms ~ 3ms
Pela rede da empresa 100mbps 11~14ms

Isso fazendo outro ajax assim que o mesmo terminava (delay de 1ms)

Porem, não sei se alguem conhece o que é long-polling, num jogo online de verdade, eu acho, que seria em média uns 3 ajax por segundo. Isso da uns 0.333ms, que é um delay grande, ou seja, a maioria dos pings seriam menor que isso (eu espero)

Localhost, tambem testei e consegui abrir mais de 100 abas no chrome (ubuntu, core2duo 2.4 ou 2.8, nao lembro, 2gb de ram meia boca) e nao chegou no topo. Na verdade, acho que o q tava mais gastando processador era o chrome e nao o apache+php


Em jogos como tibia, ragnarok, temos um servidor. Esse, se eu fosse fazer, seria em c++.
Eu fiz um servidor em Delphi (para cliente parecido com tibia)
Em Windows (e outros SO tambem) os programas podem alocar memoria.
Portanto, o comportamento dos servidores ao iniciar é:

-- ler config
-- ler mapas
-- ler scripts, etc..
-- conectar com o banco
-- abrir conexao com a net

Ao jogador entrar:
-- carregam do banco e enviam as informacoes para o client
-- alocam um pedaço de memoria.
-- relaciona a conexao vs jogador vs memoria alocada

e ao jogador fechar/sair ou o servidor fechar (nao dando erro, é claro)
ele pega essas informações da RAM e jogam em banco de dados novamente

bom, pelo menos é assim que os OTServers funcionam.
Seria muito custoso, atualizar a cada movimento a tabela de jogadores. por isso, eh feita por exemplo a cada 2 horas, ou ao fechar, ou ao player sair.

Porem, em PHP o cenário é diferente. Geralmente os hosts limitam a memoria que pode ser utilizada por um script, um script nao pode rodar por mais de 90 segundos. etc..
Então alocar memoria compartilhada no PHP (http://php.net/manual/en/book.shmop.php) em hosts com baixo custo é relamente dificil. Pois, alem da baixa quantidade (30mb) não é possivel ter scripts rodando sempre.


Então eu estava pensando em usar a sessao de cada jogador + banco de dados.
Porem, acho que teria que limitar os jogadores a 20 online (acho que mais que isso, alem de, na real, acabar com a banda do servidor, iria causar lentidao na maquina) que é bem menos que 700~900 que jogos com conexao Socket conseguem chegar (claro, com pCs com 8gb de ram, xeon, etc..)


O que acham da ideia? é viavel criar um jogo usando banco de dados fazendo updates a cada ação?
pois Ainda assim, pra ficar legal mesmo, precisamos fazer querys a cada ms para verifciar se há outro jogador por perto, e responder isso no ajax.

a estrutura do long polling é basicamente essa:

<?

joga os headers pra o cliente

while (nenhuma informacao nova|| timeout do javascript == false){
usleep(200);
}

captura todas as informacoes nova e envia para o cliente

fim

?>
E no cliente, ao receber a mensagem, faz todas as acoes e faz outro ajax.


Aqui tem um teste:
PHP:
Código:
<?php
ob_start();
header('Content-Type: text/javascript;charset=utf-8');
session_start();

$json = new StdClass;

$json->f = '';
$updatePos = false;
if (! empty( $_GET['name'] ) && empty($_SESSION['name'])) {
   session_destroy();
   session_start();
   $_SESSION['name'] = $_GET['name'];
   $_SESSION['state'] = 1;
   $_SESSION['x'] = 20;
   $_SESSION['y'] = 20;
   $_SESSION['pid'] = uniqid();

   $json->f = 'welcome';
   $json->pid = $_SESSION['pid'];
   $updatePos = true;
}
if( !empty( $_SESSION['pid']) ) {
   $delay = 0;
   while (true){
      $_SESSION['a'] ++;
      if ($_SESSION['a'] > 100){
         $updatePos = true;
         $_SESSION['a'] = 0;
      }
      if (!(empty($_GET['want_x'])) || $updatePos){
         
         $_SESSION['x'] = $_SESSION['x'] + 5;
         if($_SESSION['x'] > 500) $_SESSION['x'] = 0;
         $json->x = $_SESSION['x'];
         $json->f .= ',updatePos';
         break;

      }else{

         if($delay >= 1000 * 1000 * 5){ // 5 segundos
            $json->f .= ',idle';
            break;
         }
         $delay += 5000;
         usleep(5000);
      }
   }

}else{
   $json->error = 1;
   $json->message = 'Player not found.';
}

if($json->error === 0){
   unset($json->error);
}

die( json_encode( $json ) );
?>

HTML:
Código:
<html>
<head>
    <title>MMO teste</title>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js" type="text/javascript" charset="utf-8"></script>

    <style type="text/css" media="screen">
      body{ background:#000;color:#fff;font-size:.9em; }
      .msg{ background:#aaa;padding:.2em; border-bottom:1px #000 solid}
      .old{ background-color:#246499;}
      .new{ background-color:#3B9957;}
    .error{ background-color:#992E36;}
      #player { height: 100px; background-color: white; width: 60px; position: relative;color:black; }
    </style>

    <script type="text/javascript" charset="utf-8">
   var game = {
      playerName : '',
      loading    : 1,
      state      : 0,
      
   };
    function addmsg(type, msg){
       
        $("#messages").append(
            "<div class='msg "+ type +"'>"+ msg +"</div>"
        );
    }

   var gameFunctions = {
      idle : function (o){
         console.log(o);
      },
      welcome: function (o){
         game.state = 3;
         game.pid   = o.pid;
         addmsg('new','Welcome to the world! Your PID is '  + game.pid);
         $('#player_name').text(game.playerName);
      },
      updatePos: function (o){

         $('#player').css('left', o.x + 'px');

      }
   };

    function waitForMsg(){
      if (game.loading) return;
      var get = '?any=x';

      if(game.state == 1){
         game.state = 2;
         get += '&name=' + game.playerName;
      }
      if(game.move_right){
         get += '&name=' + game.playerName;
      }

        $.ajax({
            type: "GET",
            url: "./ajax_mmo.php" + get,
            async: true,
            cache: false,
            timeout: 50000,
         dataType: 'json',
            success: function(o){ /* called when request to barge.php completes */
                if(+(o.error)){
               alert('Erro ' + o.message);
            }else{
               var af = o.f.split(',');
               for(var i in af){
                  if(gameFunctions[af[i]])
                     gameFunctions[af[i]](o);
               }
            }
                setTimeout(
                    'waitForMsg()', /* Request next message */
                    1
                );
            },
            error: function(XMLHttpRequest, textStatus, errorThrown){
            if (textStatus.toLowerCase() == 'timeout'){
               alert();
               setTimeout(
                  'waitForMsg()', /* Request next message */
                  1
               );
            }else{
               addmsg("error", textStatus + " (" + errorThrown + ")");
            }
            },
        });
    };

   function gameStart(e){
      game.playerName = $('#nm_player').val();
      $('#frmlogin').slideUp('slow');
      addmsg('new', 'Loading...');
      game.loading = 0;
      game.state   = 1;
      waitForMsg();
   }
    $(document).ready(function(){
        waitForMsg();
    });
    </script>
</head>
<body>
   <form id="frmlogin">
      <label>Name: <input style="-moz-border-radius: 4px;background:black none repeat scroll 0 0;border:1px solid blue;color:white;"  id="nm_player"/></label>
      <button type="button" onclick="gameStart(this)" style="-moz-border-radius: 4px;background:black none repeat scroll 0 0;border:1px solid blue;color:white;">Conectar</button>
   </form>
   
    <div id="messages">
       
    </div>
   <div id="player">
      <span id="player_name"></span>
    </div>
   
</body>
</html>

_________________
Procurando por artigos?
Imagem
http://www.desenvolvedoresonline.com

Imagem
http://www.renatocron.com/


Voltar ao topo
 Perfil  
 
 Título: Re: Web Games - Long Polling com PHP
MensagemEnviado: Dom Mai 02, 2010 9:10 pm 
Offline
Colaborador PDJer
Colaborador PDJer
Avatar do usuário

Registrado em: Sex Jan 18, 2008 4:58 pm
Mensagens: 867
Localização: Brazil
Qualê! Dêêm suas opiniões, mesmo qeu noa tenha nada relacionado a programacao!

_________________
Procurando por artigos?
Imagem
http://www.desenvolvedoresonline.com

Imagem
http://www.renatocron.com/


Voltar ao topo
 Perfil  
 
 Título: Re: Web Games - Long Polling com PHP
MensagemEnviado: Seg Mai 03, 2010 9:07 am 
Offline
Moderador
Moderador
Avatar do usuário

Registrado em: Seg Jun 02, 2003 10:00 am
Mensagens: 1387
Localização: São Paulo -SP
Então cara, eu já tentei fazer algo parecido, mas era em turnos, e não real-time. Mesmo assim foi complicado, porque em HTTP não existe um esquema de o servidor mandar coisas pro browser sem que ele faça o request. Eu tava estudando um esquema de ajax reverso pra conseguir isso, um negócio chamado cometd, mas eu acabei largando pq tava complexo demais e não tinha nenhuma lib pronta que fizesse isso decentemente. Ah, eu tava usando Java.

Mas cara, sinceramente, acho que pra fazer um jogo desses hoje, ou você usa a unity (ou flash), ou espera o html 5 se consolidar.

_________________
Framework C++ OpenSource para jogos 2D:
http://easy2d.sourceforge.net


Voltar ao topo
 Perfil  
 
 Título: Re: Web Games - Long Polling com PHP
MensagemEnviado: Seg Mai 03, 2010 6:57 pm 
Offline
Colaborador PDJer
Colaborador PDJer
Avatar do usuário

Registrado em: Sex Jan 18, 2008 4:58 pm
Mensagens: 867
Localização: Brazil
è isso que eu postei o codigo ai em cima, é cometd usando long-polling.
Push é mais complicado em PHP, long-polling são rapidos tambem.

_________________
Procurando por artigos?
Imagem
http://www.desenvolvedoresonline.com

Imagem
http://www.renatocron.com/


Voltar ao topo
 Perfil  
 
Exibir mensagens anteriores:  Ordenar por  
Criar novo tópico Responder  [ 4 mensagens ] 

Todos os horários são GMT - 3 horas


Quem está online

Usuários navegando neste fórum: Nenhum usuário registrado e 1 visitante


Enviar mensagens: Proibido
Responder mensagens: Proibido
Editar mensagens: Proibido
Excluir mensagens: Proibido
Enviar anexos: Proibido

Procurar por:
Ir para:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
Traduzido por: Suporte phpBB