Suporte no desenvolvimento de jogos


    Evitando lag

    Valentine
    Valentine
    Administrador
    Administrador

    Medalhas : Evitando lag 94JxvEvitando lag ZgLkiRU
    Mensagens : 5025
    Créditos : 1115
    Cash : 0

    Evitando lag Empty Evitando lag

    Mensagem por Valentine em Qui Out 06, 2016 6:30 pm

    Está aí o monstro dos desenvolvedores. O lag. Ele deve ser evitado a todos os custos. Um jogo perfeito em conteúdo, cheio de beleza, cheio de opções, com animações maravilhosas, não será nada divertido se tiver lag. Pode ser o projeto que use os melhores sistemas do mundo, mas se for lento, ninguém joga.

    É para evitar problemas com o lag que irei dar dicas e macetes para evitar este terrível vilão.

    Inicilaize as Variáveis

    Sempre inicialize as suas variáveis. Exemplo:
    Código:
    #Ao invés disso:
    y = x + 1 # Retorno: 1
     
    #Use isso:
    x = 0
    y = 0
    y = x + 1 # Retorno: 1

    Motivo: Performance. O ganho pode ser verificado com o seguinte código RUBY:
    Código:
    require "benchmark"
    include Benchmark
     
    n = 1000000
    bm(12) do |test|
     
      test.report("Normal:") do
        n.times do |x|
          y = x + 1
        end
      end
     
      test.report("Inicializando:") do
        x = y = 0
        n.times do |x|
          y = x + 1
        end
      end
     
    end

    O retorno deste teste (do código acima) é o seguinte:
    Código:
                      user     system      total        real
    Normal:        0.920000   0.000000   0.920000 (  0.978238)
    Inicializando: 0.720000   0.000000   0.720000 (  0.761112)

    Ou seja... Inicializando é mais rápido.

    Complexidade do código nas repetições

    Como determinar a complexidade de uma rotina? Antes de responder esta pergunta vamos ver alguns exemplos:

    Exemplo 1:
    Código:
    p s

    if s = nil
      s = Sprite.new
    end

    c = d + 1

    s.x = c

    Achou complexo? Vamos ver outro exemplo.

    Exemplo 2:
    Código:
    n = 100
    for i in 0...n
      f + = self.uma_string_qualquer(i)
    end

    Pareceu ser menos complexo? Ou ficou mais complexo? Antes da resposta vamos ver outro exemplo.

    Exemplo 3:
    Código:
    n = 100

    for i in 0...n

      for j in 0...n

        for k in 0...n
          self.faz_alguma_coisa(i,j,k)
        end

      end

    end

    E agora? Mais ou menos complexo?

    Se considerarmos que a complexidade depende do número de repetições executadas, então o mais complexo é o exemplo 3. Observe que se n for igual a 2, serão executadas 8 repetições. Se n=3 , serão 27 repetições. Com n=4 serão 64 repetições. Com n=100 será um milhão de repetições.

    Ao criar qualquer rotina é necessário lembrar deste detalhe para evitar repetições desnecessárias.

    Mais um exemplo:
    Código:
    nIdSkill = 1

    #Lento
    for actor in $game_party.actors
      actor.hp -= calcular_dano_da_habilidade(nIdSkill)
    end

    #Rápido
    nDano = calcular_dano_da_habilidade(nIdSkill)
    for actor in $game_party.actors
      actor.hp -= nDano
    end

    Gráficos e Imagens

    Se tem alguma coisa que pode causar lag são as imagens. A chamada de um simples método como o set_pixel, gera uma reação em cadeia. O módulo Graphics gerencia a tela no RGSS. Alterar um pixel usando o método set_pixel irá alterar dados da classe instanciada (window/sprite), que por sua vez irá manipular o bitmap contents. Este por sua vez, avisa ao Graphics que a janela/sprite precisa de um update para redesenhar as alterações. Por isso o Graphics.update é chamado. Por isso, cada janela aberta causa lag. O Graphics.update irá tentar atualizar todas elas.

    Sabendo o que causa o lag, podemos evitar. No RGSS, o lag é causado por janelas abertas/invisíveis ou muitos eventos no mapa. Cada evento possui um sprite associado. Cada sprite cria lag através do procedimento acima.

    É por isso que a maioria dos scripts anti-lag são na verdade scripts Event-Anti-Lag. Eles simplesmente evitam a atualização dos sprites dos eventos que não estão na tela.

    É possível ir além do que procurar um script anti-lag para usar em nossos projetos. Lembre-se de usar o dispose em todas as janelas e sprites que não vai usar. Se depois precisar da janela/sprite, é melhor recriar ele. O código pode ficar um pouco maior ou complexo, mas o lag será reduzido bastante.

    set_pixel    VS    fill_rect

    Agora que têmos uma idéia do lag que o set_pixel pode causar, vamos evitá-lo na prática. Observe os dois exemplos de barras gradientes a seguir:
    Código:
    class bitmap
      def gradient_bar_1(x, y, w, h, fill_rate, c1, c2)
        fill_rect(x, y, , w, h, Color.new(0, 0, 0))
        for i in 0...(w * fill_rate).to_i
          r = c1.red + (c2.red - c1.red) * i / w
          g = c1.green + (c2.green - c1.green) * i / w
          b = c1.blue + (c2.blue - c1.blue) * i / w
          fill_rect( x+i, y, 1, h, Color.new( r, g, b ) )
        end
      end

      def gradient_bar_2(x, y, w, h, fill_rate, c1, c2)
        fill_rect(x, y, , w, h, Color.new(0, 0, 0))
        for i in 0...(w * fill_rate).to_i
          for j in 0...h
            r = (c1.red + (c2.red - c1.red) * i / w) * j  / h
            g = (c1.green + (c2.green - c1.green) * i / w) * j  / h
            b = (c1.blue + (c2.blue - c1.blue) * i / w) * j  / h
            set_pixel( x+i, y+j, Color.new( r, g, b ) )
          end
        end
      end
    end

    Agora observe o resultado das duas barras, nas imagens abaixo:
    Evitando lag Bar1
    Barra 1
    Evitando lag Bar2
    Barra 2

    Qual seria a melhor? A primeira ou a segunda? Muitos pode achar o efeito da segunda, visualmente melhor. Afinal é um efeito mais bonito, mas o lag da segunda barra é muito maior que da primeira. A diferença de tempo de execução chega a superar 40%.

    A beleza é realmente necessária? Se não for, é melhor usar a barra 1 (ao invés da barra 2), pois assim evita-se bastante lag.

    Aspas Simples ou Aspas Duplas?

    No RGSS existem comandos lentos e comandos rápidos. De posse desta informação podemos deixar nosso código mais rápido e com menos lag. A primeira coisa a se ter em mente é o uso das aspas. Observe o exemplo abaixo:
    Código:
    bitmap.draw_text(0, 0, 600, 32,
                     'Esta primeira string é processada mais rapidamente' +
                     " do que esta segunda string.\n")

    Mais exemplos:
    Código:
    #Lento
    bitmap.draw_text(0, 0, 100, 32, "#{$game_party.gold}" )
    bitmap.draw_text(0, 0, 100, 32, "#{$game_party.gold}".to_s )

    #Rápido
    bitmap.draw_text(0, 0, 100, 32, $game_party.gold.to_s )

    Evite usar as aspas duplas. Em grande parte do código podemos usar somente as simples, mas as vezes esquecemos isso. Outras vezes fazemos o famoso CTRL+C CTRL+V e lá vem as aspas duplas. Troque sempre que puder para as asplas simples.

    Mas antes de sair mudando todo o código vamos ver mais um exemplo:
    Código:
    #Exemplo 1
    nums = [0, 1, 2, 3]
    cTexto = "#{nums[0]} #{nums[1]} #{nums[2]} #{nums[3]}"

    #Exemplo 2
    nums = [0, 1, 2, 3]
    cTexto = nums[0].to_s + nums[1].to_s + nums[2].to_s + nums[3].to_s

    E agora? No exemplo anterior, o mais rápido é o exemplo 1 ou o exemplo 2?

    Inicialmente, parece ser o exemplo 2, mas a chamada de to_s 4 vezes e a concatenação destes 4 valores com o operador + também irá gastar tempo. Neste caso pode-se usar qualquer um dos dois. O maior problema é quando se usa os dois ao mesmo tempo. Sempre evite usar os dois ao mesmo tempo.

    Créditos:
    Marcelo Cavaco

    Tópico original:
    http://www.rgss.com.br/dicas_lag.html


    _________________
    Evitando lag AIymW
    Komuro Takashi
    Komuro Takashi
    Colaborador
    Colaborador

    Mensagens : 1034
    Créditos : 131
    Cash : 0

    Evitando lag Empty Re: Evitando lag

    Mensagem por Komuro Takashi em Qui Out 06, 2016 7:45 pm

    Ótimas dicas valeu pela contribuição.


    _________________
    Evitando lag Takashi_komuro_by_minato8-d51g9o4

      Data/hora atual: Sex Dez 13, 2019 9:54 pm