Imprimir tabuleiro de 80x25, muito lento, tem como acelerar?

1. Imprimir tabuleiro de 80x25, muito lento, tem como acelerar?

João Matheus Rugeri Murdiga
jomarumu

(usa Ubuntu)

Enviado em 06/07/2012 - 22:01h

Fiz um jogo em um trabalho para a faculdade, coisa simples, um lig4, sem interface gráfica, bem basicão.

Resolvi modificar bem o jogo, criei um tipo de um jogo de tabuleiro com ele, onde você move seu personagem, e após isso a tela é impressa.

Ai está o problema, são 2000 caracteres a serem escritos, são 9 possibilidades diferentes, isso faz a impressão ficar lenta, dando até para que você veja as últimas linhas serem impressas.


Por enquanto não utilizarei bibliotecas para impressão gráfica, antes acabarei o desenvolvimento desse jogo e depois penso em aprender SDL, então preciso de uma solução para uma impressão rápida que seja só mesmo em linhas de texto.


Edit: Fiz umas verificações aqui e percebi que mesmo com 18000 ifs ou 2000, a velocidade é muito próxima, o que acontece mesmo é que o sistema demora de mais para imprimir as linhas. Tem como melhorar?

Alguma dica?



  


2. Re: Imprimir tabuleiro de 80x25, muito lento, tem como acelerar?

Perfil removido
removido

(usa Nenhuma)

Enviado em 06/07/2012 - 23:52h

Tem como mostrar o código?

Quanto menos loops ou quanto menos vezes a execução se mantiver num loop, melhor poderá ser a velocidade do programa.

É claro que se tiver que repetir um comando 20 vezes vai ser melhor um loop de 20 vezes que 20 linhas do mesmo comando.


3. Re: Imprimir tabuleiro de 80x25, muito lento, tem como acelerar?

João Matheus Rugeri Murdiga
jomarumu

(usa Ubuntu)

Enviado em 07/07/2012 - 00:10h

Listeiro 037 escreveu:

Tem como mostrar o código?

Quanto menos loops ou quanto menos vezes a execução se mantiver num loop, melhor poderá ser a velocidade do programa.

É claro que se tiver que repetir um comando 20 vezes vai ser melhor um loop de 20 vezes que 20 linhas do mesmo comando.


Logo enviarei o código para o banco de scripts do VOL, só falta resolver esse problema e terminar de implementar algumas funções novas, será GPL, entretanto ainda não está pronto, tem partes do código realmente zoados apenas para que ele funcione enquanto não termino de fazer todas as funções, então por enquanto vai só a impressão:

Mostrarei apenas o laço, é isso:
"
for (i = 0; i < nlin; ){
i++;
for (j = 0; j<ncol; )
{
j++;
if(i == linha && j == coluna){printf (" /*Aqui não aparece, mas é o personagem*/");}
else
if(tabuleiro[ i][j] == CHAO){printf (" ");}
else
if(tabuleiro[ i][j] == MURO_CIMA){printf ("=");}
else
if(tabuleiro[ i][j] == MURO_LADO){printf ("|");}
else
if(tabuleiro[ i][j] == FOGO){printf ("^");}
else
if(tabuleiro[ i][j] == PORTAL_CIMA){printf ("_");}
else
if(tabuleiro[ i][j] == PORTAL_LADO){printf ("!");}
else
if(tabuleiro[ i][j] == PORTAL){printf (" ");}


else {{printf (" ");}} /*Imprime o espaço*/
}

}
"
Pensei em dividir 3 e 4, depois fazer subdivisões, mas o "chao" é impresso em média de 60% a 95% das vezes, acho que nem compensa mudar.


Mesmo assim não muda muita coisa, troquei todas as verificações por uma impressão direta "printf("%c",tabuleiro[ i][j]);", não percebi nenhuma melhoria na velocidade.


Valeu.


4. Re: Imprimir tabuleiro de 80x25, muito lento, tem como acelerar?

jarlisson moreira
jarlisson

(usa Fedora)

Enviado em 07/07/2012 - 00:30h

Já ouviu falar da 'ncurses'?
Acho que ajuda, pois todo jogo em terminal usa.


5. Re: Imprimir tabuleiro de 80x25, muito lento, tem como acelerar?

Perfil removido
removido

(usa Nenhuma)

Enviado em 07/07/2012 - 07:53h

Comentários sobre o trecho:

Você pode copiar o código do seu editor de texto e colar na área de escrever postagem no fórum e colocar duas tags para código: [ code ] e [/ code ]. Deste modo ele fica melhor de se ler.

Esses espaços em branco são para aparecerem escritas aqui.

É só você clicar no botão quote e você verá como fica o código.

Voltando:

for (i = 0; i < nlin; ){
i++;
for (j = 0; j<ncol; )
{
j++;


Isso também pode ser escrito como:

for (i=0; i<nlin;i++;){
for (j=0;j<ncol;j++;)
{


Quando só aparece ***um único comando*** após o "if()" não é necessário o par de chaves.
Como a função "printf()" só está servindo prá um único caracter, pode ser usada a função "putc()", de acordo com Linux:

if(tabuleiro[i][j] == MURO_LADO) putc ('|',stdout);  


A função "putc()" é mais simples. A "printf()" vem com um monte de tralha prá formatar número, sequência de escape, ponteiro etc. que neste caso não é usada. "putc()" é mais simples e mais direta.

Se há uma coisa que deixa programa lento é loop. Aqui ocorrem dois loops, um de 25 e outro de 80.

Se você quer modificar a tela a cada vez que alguma coisa acontece e apenas em um único lugar, a melhor coisa a se fazer é trabalhar com escrita exatamente em cima da coordenada que você quer modificar.

Neste caso não precisaria passar pelas 2000 repetições.

Eu tenho até um trecho desse código aqui, mas não estou encontrando neste momento.

As suas verificações se restringiriam a saber qual caracter seria impresso no local.

Ainda pode ser usada uma outra estrutura de C chamada switch().


switch (tabuleiro[i][j]) {

CHAO:
putc (' ',stdout);
break;
MURO_CIMA:
putc ('=',stdout);
break;
MURO_LADO:
putc ('|',stdout);
break;
FOGO:
putc ('^',stdout);
break;
PORTAL_CIMA:
putc ('_',stdout);
break;
PORTAL_LADO:
putc ('!',stdout);
break;
PORTAL:
putc (' ',stdout);
break;
default:
putc (' ',stdout);

}



Uma outra hipótese seria você não imprimir toda a tela a cada mudança nas 2000 repetições.

Seria impressa apenas a linha inteira modificada armazenada na matriz (no caso é 80x25), copiada para uma string do tamanho da quantidade de caracteres por linha acrescido de uma posição.

String que seria uma cópia de uma linha da tabela, que é a linha modificada, acrescida de mais uma posição com um '\ 0' ao fim prá não aparecer qualquer coisa estranha.

Imprimir a linha inteira não faz o programa perder tempo executando 80 vezez printf, puts, putc etc. Essas chamadas caem em subrotinas adicionadas na compilação e sem querer acaba virando algo um pouco parecido com um loop.

*** ADD ***

Mais uma coisa:

Neste caso vou supor que os valores nesse comando "switch() {...}" aí em cima são constantes inteiras em ordem crescente.

CHAO=0; MURO_CIMA=1; MURO_BAIXO=2; // ... não importa como estes números foram escolhidos. Veja o exemplo a seguir. 


Agora seja a seguinte string de caracteres do programa:

char *string = " =|^_!  "; 


Agora no caso se for solicitada a execução do seguinte comando:

putc (string[MURO_BAIXO],stdout); 


Simplesmente será impresso o caracter correspondente ao índice 2 da string que também é o caracter para "MURO_BAIXO".

Sem precisar de executar a verificação item a item.

Evitou-se meia-dúzia de verificações.







6. Re: Imprimir tabuleiro de 80x25, muito lento, tem como acelerar?

Sergio Teixeira - Linux User # 499126
Teixeira

(usa Linux Mint)

Enviado em 07/07/2012 - 08:52h

Fazer constantes "refreshs" de uma tela com tais dimensões tende a ficar demorado mesmo.
Como na maioria das vezes não é necessário reimprimir a tela toda, veja se existe a possibilidade de reimprimir apenas a parte que deverá sofrer modificações, ou ainda, trabalhar com sprites.
Esta última solução me parece ser a melhor, e é a que geralmente é usada pelos desenvolvedores comerciais.


7. Re: Imprimir tabuleiro de 80x25, muito lento, tem como acelerar?

Perfil removido
removido

(usa Nenhuma)

Enviado em 07/07/2012 - 09:02h

Se sprite for o que estou pensando, só conheci uma única linguagem de programação modo texto que faz isso com um pé e as duas mãos nas costas e ainda por cima é dita comercial.

Já estou há um tempo atrás de semenlhante em C, mas um dos headers da Linux API é interminável.


8. Re: Imprimir tabuleiro de 80x25, muito lento, tem como acelerar?

João Matheus Rugeri Murdiga
jomarumu

(usa Ubuntu)

Enviado em 07/07/2012 - 10:36h

jarlisson

Não conhecia não, mas pelo que vi parece que pode ajudar sim.



Listeiro 037

for (i=0; i<nlin;i++) - Assim teria que começar com i = 1, não sei porque não fiz isso, acho que daria problema na última execução no lig4, então ficou do modo que está.

putc() - Isso parece que pode ajudar mesmo, valeu.

Quanto ao loop, como eu disse, não é ele que deixa lento, fiz uma impressão direta, sem verificação nenhuma, imprime o que está na matriz, continuou na mesma velocidade.


Teixeira

Era meio isso que eu buscava, reimprimir só o que foi mudado, mas achei que não tinha como. Fui informado em outro site que tem sim, com um comando "gotoxy(x,y);", vou testa-lo, pois ai acho que seria bem mais rápido.


Sam L.

Então Sam, é como eu disse, não há uma melhoria significativa em tentar mudar a forma que será impresso, na impressão direta ficou a mesma coisa, o grande problema está na demora da impressão mesmo.
Ainda não sei se é melhor imprimir do modo que você sugeriu, estou modificando o código para ver se é. Edit: Há também um problema em imprimir assim, o tabuleiro tem uma moldura de zeros na linha 0, na coluna 0, na linha 25 (ou 26), e na coluna 81.

A movimentação já está pronta, ele se movimenta independente de poder ou não, mando então para um a função que verifica se ali é possível estar, se não é, a função desfaz o que foi feito.
Pensei em fazer isso de virar chão, o personagem ficaria na matriz, mas não achei que seria a melhor solução, o mapa agora é fixo, ou seja, a matriz não muda, a não ser que você entre em um portal, o que muda é o personagem, esse possui duas coordenadas (int linha, int coluna), se apertar w ou W o linha--; e assim por diante.


Obrigado a todo.


9. Re: Imprimir tabuleiro de 80x25, muito lento, tem como acelerar?

João Matheus Rugeri Murdiga
jomarumu

(usa Ubuntu)

Enviado em 07/07/2012 - 11:29h

Sam L. escreveu:


Então Sam, é como eu disse, não há uma melhoria significativa em tentar mudar a forma que será impresso, na impressão direta ficou a mesma coisa, o grande problema está na demora da impressão mesmo.


Cara me envia o codigo por email pra eu ajudar melhor.

Enviado.
Valeu.



Acredito que a melhor solução seria mesmo o gotoxy(x,y); para alterar o que for necessário, pois a matriz é fixa.
Estou procurando mais sobre isso, mas só encontro tal função na windows.h, encontrei também gente dizendo que tem na Conio, mas ainda estou procurando.

Edit: Pelo que vi, a ncurses deve ter isso.


Edit2: Parece que encontrei a solução, a Conio realmente faz isso, mas tem que ser a versão da conio da borland, agora está funcionando bem.


10. Re: Imprimir tabuleiro de 80x25, muito lento, tem como acelerar?

João Matheus Rugeri Murdiga
jomarumu

(usa Ubuntu)

Enviado em 07/07/2012 - 11:55h

Sam L. escreveu:

Eu testei aqui e não fica lento pra mostrar a matriz.

Então, mas tenta jogar mesmo, sair "correndo", dá um problema ao imprimir as últimas linhas.

Com o gotoxy ficou perfeito, estou trabalhando como se houvesse duas camadas, a matriz tabuleiro é o fundo, já que será fixa, você é a parte de cima, você pode andar sem ter que reimprimir tudo, agora ficou ótimo.
O único problema é que do modo que eu fiz vai apagando e deixando CHAO nas que você passou anteriormente assim passar pelo FOGO por exemplo, o transforma em CHAO, depois vejo se é necessário corrigir isso.

De qualquer forma está tudo pronto, funcionando muito bem, a solução está aqui: http://www.adaobraga.com.br/como-usar-o-gotoxy-no-dev-c/


Obrigado a todos.


11. Re: Imprimir tabuleiro de 80x25, muito lento, tem como acelerar?

darlan
darlan56

(usa Debian)

Enviado em 07/07/2012 - 12:32h

se eu entendi direito tu ta usando essa função gotoxy() pra posiciona o cursor na tele e escreve o caracter, so q ela e so pra windows não funcionaria em linux, uma alternativa é usa assim

void posiciona_cursor(int x, int y) {
printf("\_0_33[%d;%dH",y, x);// retira os _ do inicio
}


essa função faz a mesma coisa q a gotoxy() e e funcional no windows e linux e depois da um imprime o caracter que tu que, e assim por diante



12. Re: Imprimir tabuleiro de 80x25, muito lento, tem como acelerar?

João Matheus Rugeri Murdiga
jomarumu

(usa Ubuntu)

Enviado em 07/07/2012 - 13:25h

darlan56 escreveu:

se eu entendi direito tu ta usando essa função gotoxy() pra posiciona o cursor na tele e escreve o caracter, so q ela e so pra windows não funcionaria em linux, uma alternativa é usa assim

void posiciona_cursor(int x, int y) {
printf("\_0_33[%d;%dH",y, x);// retira os _ do inicio
}


essa função faz a mesma coisa q a gotoxy() e e funcional no windows e linux e depois da um imprime o caracter que tu que, e assim por diante

Tentei o código, mas o que acontece é que ele imprime na frente do local atual uma flecha, o número da linha e o da coluna.


Ainda não testei como ficará no linux, preguiça de reiniciar o PC :D



01 02



Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts