terça-feira, 11 de janeiro de 2011

Usando o BMP writer num processor paralelo

BMP writer é um script que criei com a função de escrever imagens do tipo BMP true color de 24 bits a partir do objeto Bitmap do RGSS. Mais detalhes visite:

BMP writer

O script não utliza bibliotecas externas. Foi escrito totalmente em Ruby baseando-se no objeto Bitmap usado em RGSS/2. Mesmo sendo feito para ter um bom desempenho com relação ao tempo de escrita de arquivo, para empregá-lo em jogos o tempo de escrita pode acabar sendo longo. Por exemplo, em uma máquina com Core 2 Duo o script levou 2 segundos para gravar um bitmap de 640x480, o que parece rápidos, mas pode ser um incmodo no meio de um jogo.

Então resolvi usar o metodo de escrita em um processo paralelo para não ocorrer aquela pausa no jogo enquanto a gravação do arquivo está em andamento. O problema é que leva mais tempo para o arquivo ser salvo(seguindo mesmo exemplo anterior, levou 1 minuto e meio para a gravação), isso significa que não é possível visualizar/utilizar o arquivo gerao enquanto não terminar essa gravação, e também caso o jogo seja fechado antes do término o arquivo fica corrompido.

Para criar nosso processo paralelo usaremos uma Thread. Basicamente uma thread é um bloco de código que é executado em paralelo com o programa principal. A técnica não é muito complicada nem ocupa muito espaço. Primeiro vamos carregar um Bitmap para usar na gravação:

data_system = load_data("Data/System.rxdata")
aBitmap_obj = RPG::Cache.title(data_system.title_name)


As linhas acima irão carregar a imagem de título na variável aBitmap_obj.

Agora vamos à Thread:

thread_bmp = Thread.new(aBitmap_obj) do
begin
file = File.new('image.bmp','wb')
file.bmp_write(aBitmap_obj)
file.close
rescue
print 'Erro ao gravar um bitmap'
end
end


a linha:

thread_bmp = Thread.new(aBitmap_obj) do

Cria nossa Thread. Observe que já passamos como argumentoda Thread o Bitmap que criamos antes. O "do" define o nosso bloco de código que termina no último "end".

O "begin" é um outro bloco que criei dentro da threadsó para poder usar o tratamentos de exceções(erros) da clausula "rescue". Isso porque quando ocorre um erro dentro da Thread o Game.exe fecha sem nem um aviso. Então se acontecer algum erro na Thread o que está entre o recue e o end será executado. No exemplo só cooquei uma mensagem, o que não é muito correto, porque se aconteceu algum erro a thread para mas o programa continua sem tratar do problema.

Entre o begin e o rescue deve entrar aquelas três linhas que já usavamos para gravar o arquivo antes.

file = File.new('image.bmp','wb')
file.bmp_write(aBitmap_obj)
file.close


Abre o arquivo para leitura, escreve o BMP no arquivo e fecha o arquivo quando terminar a escrita.

Basicamente é isso. Teste a técnica e qualquer dúvida fique a vontade.

2 comentários:

  1. Bem interessante sua ideia. Tem lá as desvantagens, mas é bom não interromper o jogo. E é até bem simples.

    ResponderExcluir
  2. Pois é. Sem dúvida o processo é mais lento, mas pelo menos não atrapalha no jogo.

    Eu ainda não entendi porque deu uma diferença tão grande no tempo. Vou estudar melhor sobre as prioridades pra ver se consigo fazer alguma coisa pra "dozar" melhor isso aí.

    ResponderExcluir