Screen Refresh, Frameskip e Doublebuffer no Game Maker

Ver o tópico anterior Ver o tópico seguinte Ir em baixo

Screen Refresh, Frameskip e Doublebuffer no Game Maker

Mensagem por Convidad em Qui 19 Nov 2009, 22:06

Título: Screen Refresh, Frameskip e Doublebuffer no Game Maker
Versão do GM: 6.3, 7, 8 e 8.1.
Dificuldade: Intermediário
Link para download da Engine: ENGINE
Requer Extensões: Não
Requer DLLs: Não
Tags: Screen Refresh, Frameskip,Doublebuffer

Não é incomum, ocorrer umas "travadinhas" no jogo. Em alguns casos, isso pode ocorrer devido à sobrecara de programas e processos em execução, que comprometem a performance do PC. Mas há casos, em que, mesmo quando o sistema está "levinho", o jogo não tem seu desempenho total.

Essa "travadinha" dá a impressão de que os objetos "pularam" de um lugar pra outro. Por mais estranho que possa parecer, isso decorre de um problema que se origina no cérebro do observador: ele antecipa o movimento o objeto. O cérebro "calcula" onde o objeto deverá estar no próximo instante. Como o salto é muito grande, fica-se com a impressão de que o objeto "sumiu" e "reapareceu" em outro lugar.

Alguns jogos resolvem isso carregando a visão do jogador com tantos elementos se movendo, que mesmo um observador muito atento não consegue antecipar tudo. O fato é que esse problema tem uma origem, que é o refresh de vídeo, que também tem solução.

Nesse tutorial, vamos falar um pouco sobre o refresh de vídeo e como podemos trabalhar com ele para amenizar esses problemas. Também vamos aprender a fazer um frameskip no jogo, mas isso requer algumas mudanças no seu projeto, então...

Boa leitura!



O Buffer de Vídeo


Toda estrutura de vídeo é baseada em uma memória à parte da memória principal do computador, que chamamos de "memória de vídeo" ou simplesmente "VRAM". Quanto mais memória de vídeo o nosso PC dispõe, mais fácil fica o trabalho do processador
ao lidar com elementos gráficos, uma vez que ele pode operar diretamente nesta memória.

Embora seja muito simples, nem sempre isso significa "mais velocidade". Por mais rápido que nosso processador seja, ou por mais processadores que se tenha, dois deles não podem acessar o mesmo endereço de memória ao mesmo tempo, e, toda imagem que nos é mostrada no monitor, parte da memória principal para a memória de vídeo.

Mesmo que a placa de vídeo tenha um processador próprio, utilize portas ultra rápidas ou outro recursos técnicos (que o vendedor provavelmente usou pra te convercer a comprá-la), no momento em que a informação gráfica está sendo transferida,
o processador não pode usar aqueles endereços e "fica esperando" até que o serviço de transferência termine.

Esse "serviço" é justamente o refresh. Quando esse "serviço" termina, a tela é atualizada e mostrada pra gente.

É verdade que todos os dias novas tecnologias aparecem para solucionar todo tipo de problema. Os fabricantes de hardware estão cada dia mais engajados em criar novas placas de vídeo com super desempenho. Mas ao mesmo tempo em que "ganhamos"
(até doeu o bolso, agora) mais velocidade de processamento, as informações que são mostradas no monitor também aumentaram.

Diga-se de passagem, os jogos com gráficos de "cair o queixo". E não tem perdão: essa Skin alienígena que você está usando no seu novíssimo Windows Vista, também faz parte da brincadeira. [Z¬)]

Voltando ao assunto, vamos então, experimentar uma das funções do Game Maker que trabalha justamente com o serviço refresh de vídeo: a função screen_refresh(). Também vamos aprender a fazer um Frameskip pra tentar contornar os problemas
de velocidade do jogo... o que eu vou explicar mais adiante. Por enquanto, vamos nos manter no refresh de vídeo e como ele funciona na nossa ferramenta de programação, o Game Maker é claro.

Toda vez que o o nosso jogo "executa", há uma atualização constante da tela, através de um sistema chamado Doublebuffer. Basicamente, essa atualização da tela do jogo funciona como se fosse um relógio num "tique-taque". Tique: pega as informações com os objetos (aquilo que será desenhado). Taque: desenha tudo na tela. Tique: pega, taque: desenha. E a medida que essas condições de vão sendo satisfeitas (enquanto nosso joguinho "tá rodando"), o Doublebuffer vai trabalhando com tique e taque, faça chuva ou faça sol.

Pra você entender o que é realmente o Doublebuffer, ele funciona assim: o DirectX prepara uma área idêntica à área correspondente do vídeo, porém, essa área é acessada única e exclusivamente pelo processador. Daí, o processador pode
trabalhar nela de forma "tranquila", sem padecer de problemas com o refresh. Ele só vai fazê-lo quando chegar a hora, ou seja, quando processar toda a informação daquela área.

Em resumo, quando desenhamos algo no evento Draw, há uma "espera" para que o desenho seja "jogado na tela", uma vez que isso só vai se realizar no final do passo do relógio, e não "naquela hora".

O que acontece quando usamos a função screen_fresh(), é na realidade, uma atualização "antes da hora". Sempre que instruímos o Game Maker para que ele desenhe algo no Canvas (Canvas é como se chama a área da memória onde estão os pixels que compõem toda a imagem da tela do jogo), a imagem é atualizada no final da execução do "tique" do relógio, e não  imediatamente como gostaríamos. Com screen_refresh(), ela é atualizada imediatamente, antes do "taque".

Usar a função não tem segredo. É só "botar" um screen_refresh() e pronto! A atualização é feita. É por isso que é importante saber como o refresh de vídeo funciona. [Z¬)]

É legal saber, que essa função é bastante usada também, dentro de loops ou situações que "esperam" que algo aconteça.

Código:
screen_refresh();

Simulando o Frameskip



Frameskip significa "salto de quadros". Pra que a gente entenda o que significa isso, vamos assimilar a palavra "quadro" ao termo animação. Embora na prática seja diferente, o raciocínio é praticamente o mesmo. Em uma animação, cada elemento do
conjunto de imagens que a compõe é um "quadro", ou "frame". Esses "quadros de animação", são exibidos de forma exclusiva e sequencial.

A mesma coisa acontence com o Doublebuffer. A cada momento a tela é atualizada para um novo quadro, como se fosse uma animação (o que de fato é [Z¬)]). Mas, quando há muitos quadros a serem exibidos, ou no caso do Doublebuffer, quando há
muita informação a ser processada, o desempenho do jogo cai, tornando a experiência de "jogar" bem frustrante, certo?

Aí é que entra o "salto de quadros". Quem é fanático por emuladores, já conhece bem.

Esse salto, pode e vai "aliviar" o trabalho do Doublebuffer que não precisará processar todos os quadros, tornando o jogo mais rápido, porém, com menos "perfeição de movimentos". A sensação é exatamente igual à quando a gente "apaga" alguns quadros de um sprite, deixando-o com a animação mais rápida. Isso vai tornar a taxa de fps, ou seja, Frames per second (quandros por segundo), maior, e consequentemente um jogo mais rápido.

Pra gente fazer o Frameskip, vamos precisar de duas funções dentro do Game Maker. São elas:

Código:
set_automatic_draw(true/false)
Nós ja sabemos como funciona o Doublebuffer, certo? No Game Maker, por padrão, a tela ja é processada automaticamente, sem nossa intervenção. Com a função set_automatic_draw(), vamos intervir e "desligar" esse processamento do Doublebuffer automático, e vamos fazê-lo de forma manual. A premissa do Frameskip é muito simples: vamos racionar quais quadros serão processados com a função screen_redraw(), e ignorar os demais.

Código:
screen_redraw()
Essa função faz a atualização dos eventos Draw das instâncias que estão dentro da room, ou se preferir, do primeiro buffer que eu havia comentado.

Muita atenção:

Há um fator importante que tem que ser abordado antes implementarmos o Frameskip, o que o tornará viável ou inviável, dependendo exclusivamente de como você programou seu jogo. Isso que eu vou escrever agora é importante, então fique atento!

Toda informação presente nos eventos Draw dos objetos atenderão à velocidade em que os quadros são processados pelo Doublebuffer! Em outras palavras, se você usar uma rotina para checar o status do mouse ou do teclado dentro do evento Draw, ela só "acontecerá" quando a tela for atualizada por nós!

Isso também acontencerá com valores atribuídos à variáveis e transições de room! Por isso, não custa lembrar que eu estou ensinando à você o método. Você deve adaptá-lo para o seu jogo e trabalhar nele, pois ninguém melhor do que você para conhecer seu projeto. [Z¬D]


Montando:

Se você estiver com muita preguiça, baixe o exemplo clicando aqui.



Crie um objeto chamado FrameSkipMonitor, defina-o como persistente, com depth bem baixo (para que fique à frente das outras instâncias) e coloque-o na primeira room do jogo. No evento Create deste objeto, coloque o código abaixo:

Código:
set_automatic_draw(false);

global.FrameSkip := 1;

alarm[0] := global.FrameSkip;

Info := ('Fps = ' + string(fps) + '#Frameskip = ' + string(global.FrameSkip));

ShowInfo := 1;
No evento Step, coloque o código abaixo:

Código:
if keyboard_check_pressed(vk_f2) then ShowInfo *= (-1);

if keyboard_check_pressed(vk_f3) then global.FrameSkip -= 1;

if keyboard_check_pressed(vk_f4) then global.FrameSkip += 1;

if global.FrameSkip < 0  then global.FrameSkip := 0;

if global.FrameSkip > 10 then global.FrameSkip := 10;

Info := ('Fps = ' + string(fps) + '#Frameskip = ');

if global.FrameSkip = 0 then
begin

    set_automatic_draw(true);
    Info += 'Auto';

end
else
begin

    set_automatic_draw(false);
    Info += string(global.FrameSkip);

end;
Crie um relógio, o alarm0, e coloque este código nele:

Código:
if global.FrameSkip = 0 then { alarm[0] := 1; exit; }

alarm[0] := global.FrameSkip;

screen_redraw();
Agora, por último, no evento Draw deste objeto, coloque o código:

Código:
if ShowInfo <> 1 then exit;

draw_set_halign(fa_left);

draw_set_valign(fa_top);

draw_set_alpha(1);

draw_set_color(c_black);

draw_rectangle(0, 0, string_width(Info), string_height(Info), false);

draw_set_color(c_lime);

draw_text(0, 0, Info);

Coloque o objeto na room e divirta-se com um frameskip no seu jogo. [Z¬)]. A tecla F2 mostra as informações sobre Fps, as teclas F3 e F4 diminuem e aumentam a taxa, respectivamente. Basicamente é isso. Uma dica bem legal é assimilar a velocidade da room com o frameskip, mas, isso vai depender de como é o seu jogo e de como ele foi feito...

Espero que tenham gostado da matéria. Boa sorte pra vocês!
Capitão Commando.


Última edição por Capitão Commando em Sab 21 Nov 2009, 07:08, editado 6 vez(es)

Convidad
Convidado


Voltar ao Topo Ir em baixo

Re: Screen Refresh, Frameskip e Doublebuffer no Game Maker

Mensagem por RodrigoM. em Qui 19 Nov 2009, 22:11

AAAA, Fantástico!
Cara... Incrível... Não podia esperar menos de meu Fã! =D

-----------------------------

Capitão Commando, Meu mestre! *---*

Estou boquiaberto, de quão fantástico fico isso!

RodrigoM.

Número de Mensagens : 569
Idade : 21
Data de inscrição : 06/08/2009
Reputação : 5
Insignia 1 x 0 Insignia 2 x 0 Insignia 3 x 0
Prêmios
   :
   :
   :

Voltar ao Topo Ir em baixo

Re: Screen Refresh, Frameskip e Doublebuffer no Game Maker

Mensagem por fonetico em Qui 19 Nov 2009, 22:13

Nossa cara, seu tutorial é nota 1000, na boa, você sabe fazer jogos muito bons, e também sabe fazer tutoriais super bons! Olha, vou te transformar em um fã também. Very Happy Você é demais!

fonetico

Número de Mensagens : 1830
Idade : 21
Data de inscrição : 05/10/2009
Reputação : 7
Insignia 1 x 0 Insignia 2 x 0 Insignia 3 x 0
Prêmios
   :
   :
   :

Voltar ao Topo Ir em baixo

Re: Screen Refresh, Frameskip e Doublebuffer no Game Maker

Mensagem por shatterhand2 em Qui 19 Nov 2009, 22:45

CyraxX escreveu:AAAA, Fantástico!
Cara... Incrível... Não podia esperar menos de meu Fã! =D

-----------------------------

Capitão Commando, Meu mestre! *---*

Estou boquiaberto, de quão fantástico fico isso!


Acho q vc quis dizer q você é fã dele, e não q ele é seu fã.

Voce poderia falar "meu ídolo".

Very Happy

shatterhand2

Número de Mensagens : 645
Idade : 33
Data de inscrição : 21/10/2009
Reputação : 11
Insignia 1 x 0 Insignia 2 x 0 Insignia 3 x 0
Prêmios
   : 1
   : 0
   : 0

http://shatterhand.beatthegame.net

Voltar ao Topo Ir em baixo

Re: Screen Refresh, Frameskip e Doublebuffer no Game Maker

Mensagem por Convidad em Qui 19 Nov 2009, 22:48

Valeu por comentar moçada! Espero que tenham gostado da matéria. [Z¬D]

Convidad
Convidado


Voltar ao Topo Ir em baixo

Re: Screen Refresh, Frameskip e Doublebuffer no Game Maker

Mensagem por RodrigoM. em Qui 19 Nov 2009, 22:53

Bem shatterhand2, Minha intenção foi falar
que ele é meu maior, Fã.

Mais isso não é o assunto do Tópico, Né?! =D

---------------------
è shatterhand2 VocÊ estava certo... ASHSUAHUASHUAS

Capitão Commando meu ídolo! aSHUASHU


Última edição por CyraxX em Sex 20 Nov 2009, 10:15, editado 1 vez(es)

RodrigoM.

Número de Mensagens : 569
Idade : 21
Data de inscrição : 06/08/2009
Reputação : 5
Insignia 1 x 0 Insignia 2 x 0 Insignia 3 x 0
Prêmios
   :
   :
   :

Voltar ao Topo Ir em baixo

Re: Screen Refresh, Frameskip e Doublebuffer no Game Maker

Mensagem por vinians em Qui 19 Nov 2009, 23:03

Como sempre um ótimo tutorial! É bom saber usar isso pois, as vezes fazendo um jogo com uma necessidade grande atualizações utilizando essa técnica da pra minimizar bastante o peso do freresh no game. Creio que para um jogo de maior porte esse técnica seja fundamental, elém de ser uma oportunidade boa de aprender mais sobre "os misterios" do GM. Muito bom!

vinians

Ranking : Nota B
Número de Mensagens : 2490
Idade : 27
Data de inscrição : 18/09/2008
Notas recebidas : B-C-A-C
Reputação : 52
Insignia 1 x 0 Insignia 2 x 1 Insignia 3 x 0
Prêmios
   : 0
   : 2
   : 1

http://xcreatorgames.weebly.com/

Voltar ao Topo Ir em baixo

Re: Screen Refresh, Frameskip e Doublebuffer no Game Maker

Mensagem por Conteúdo patrocinado Hoje à(s) 09:40


Conteúdo patrocinado


Voltar ao Topo Ir em baixo

Ver o tópico anterior Ver o tópico seguinte Voltar ao Topo

- Tópicos similares

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