Ir ao conteúdo
  • Comunicados

    • Gabriel Torres

      Seja um moderador do Clube do Hardware!   12-02-2016

      Prezados membros do Clube do Hardware, Está aberto o processo de seleção de novos moderadores para diversos setores ou áreas do Clube do Hardware. Os requisitos são:   Pelo menos 500 posts e um ano de cadastro; Boa frequência de participação; Ser respeitoso, cordial e educado com os demais membros; Ter bom nível de português; Ter razoável conhecimento da área em que pretende atuar; Saber trabalhar em equipe (com os moderadores, coordenadores e administradores).   Os interessados deverão enviar uma mensagem privada para o usuário @Equipe Clube do Hardware com o título "Candidato a moderador". A mensagem deverá conter respostas às perguntas abaixo:   Qual o seu nome completo? Qual sua data de nascimento? Qual sua formação/profissão? Já atuou como moderador em algo outro fórum, se sim, qual? De forma sucinta, explique o porquê de querer ser moderador do fórum e conte-nos um pouco sobre você.   OBS: Não se trata de função remunerada. Todos que fazem parte do staff são voluntários.
    • DiF

      Poste seus códigos corretamente!   21-05-2016

      Prezados membros do Fórum do Clube do Hardware, O Fórum oferece um recurso chamado CODE, onde o ícone no painel do editor é  <>     O uso deste recurso é  imprescindível para uma melhor leitura, manter a organização, diferenciar de texto comum e principalmente evitar que os compiladores e IDEs acusem erro ao colar um código copiado daqui. Portanto convido-lhes para ler as instruções de como usar este recurso CODE neste tópico:  
Iury Benites

Sprites usando Allegro no C

Recommended Posts

Oi, pessoal. Comecei a fazer um jogo point&click, que achei que seria um bom começo pra aprender a usar o Allegro. Quando o usuário clicasse na margem esquerda ou direita da tela, iria pra tela seguinte (como seria esperado). Entretanto, quando fui implementar uma seta pra indicar isso pro usuário, o background fica piscando. Tentei usar a função al_set_target_bitmap() pro background, mas o programa fecha na hora.

 

Como faço então pra carregar um sprite sobre um background?

  • Curtir 1

Compartilhar este post


Link para o post
Compartilhar em outros sites

qual a versão do allegro que você ta usando? E acho que se postar o código fica mais fácil. E se for um projeto de codeblocks lhe garanto a ajuda >_<.

  • Curtir 1

Compartilhar este post


Link para o post
Compartilhar em outros sites
  • Autor do tópico
  • @vangodp tô usando o allegro 5.0 no DevC++.

    Sobre o código, não tem nada muito complicado (o que me faz questionar porque não dá certo).

    void CarregarBackground(ALLEGRO_BITMAP *background, char NomeDoBackground[], ALLEGRO_DISPLAY_MODE disp_data)
    {
      	 //já tinha testado essa função antes, somente carregando e alternando backgrounds, e tava funcionando do jeito esperado
         background = al_load_bitmap(NomeDoBackground);
         al_draw_scaled_bitmap(background,0,0,XBKG,YBKG,0,0,disp_data.width,disp_data.height,0);	//XBKG e YBKG são macros definindo o tamanho do arquivo de background, pra ampliar do tamanho certo
         al_flip_display();
         al_destroy_bitmap(background);	//Isso realmente soa muito estranho, mas se eu não destruísse o background imediatamente, ele não desocupava a memória, e com algumas mudanças de tela já travava tudo
    }
    
    void DesenharSeta(ALLEGRO_BITMAP *seta, ALLEGRO_DISPLAY_MODE disp_data)
    {
         al_draw_bitmap(seta, (disp_data.width)/2, (disp_data.height)/2, 0);
         al_flip_display();
         al_destroy_bitmap(seta);
    }

     

    • Curtir 1

    Compartilhar este post


    Link para o post
    Compartilhar em outros sites
    Postado (editado)

    @Iury Benites
    1 - Não se destrói um bitmap a não ser que você tenha certeza de que não irá mais utiliza-lo.

     

    2 - Quando você tem uma função pra carregar algum bitmap, nunca coloque um comando que descarrega o bitmap dentro dessa função "al_destroy_bitmap(background);". Toda vez que você chama a função para carregar o bitmap ele carregava, desenhava e depois destruía.

     

    3 -  O problema do crescimento de memória ocorre porque você está colocando a função de carregar o bitmap em loop, só necessita carregar o bitmap 1 vez, em loop você coloca as funções de limpar a tela e desenhar os bitmaps na tela novamente.

     

    4 - Separe suas funções:

    --  "Carregar todas as bitmaps que você vai utilizar no jogo todo(1 vez)"

    --  "desenhar bitmaps na tela(em loop)"

    --  "destruir bitmaps da memória(1 vez no final do programa ou ao sair)".

    5 - Poste o código completo, assim da pra te ajudar melhor.


    Espero ter ajudado, bons estudos...

    Editado por CiroboyBR
    • Curtir 3

    Compartilhar este post


    Link para o post
    Compartilhar em outros sites
  • Autor do tópico
  • @CiroboyBR sim, faz bastante sentido, na verdade. O problema é que me baseei num tutorial que ensinava simplesmente a desenhar uma imagem e deu, e daí tentei expandir (a base de muita gambiarra, admito :v). Encontrava pouca coisa sobre allegro 5, muito menos bem explicado.

    Acredito que isso resolva tudo. Assim que eu implementar, eu posto aqui.

    • Curtir 1

    Compartilhar este post


    Link para o post
    Compartilhar em outros sites
  • Autor do tópico
  • Ok, separei as funções entre "Carregar Background", "Exibir Background" e "Destruir Background". O problema é na hora de exibir. Essa demo que estou fazendo se trata de quatro backgrounds, como se fossem as paredes de uma sala. Quando o usuário coloca o cursor na margem esquerda ou direita, e clica, vai para a tela correspondente (e isso dá certo tranquilo).
    O problema é na hora de exibir uma seta para o usuário, indicando que ele está na posição correta. Segue o código:

    void DesenharSala(ALLEGRO_BITMAP *background1, ALLEGRO_BITMAP *background2, ALLEGRO_BITMAP *background3, ALLEGRO_BITMAP *background4, int numero, ALLEGRO_DISPLAY_MODE disp_data)
    {
         if(numero == 0)
                   al_draw_scaled_bitmap(background1,0,0,XBKG,YBKG,0,0,disp_data.width,disp_data.height,0);
         else
         if(numero == 1)
                   al_draw_scaled_bitmap(background2,0,0,XBKG,YBKG,0,0,disp_data.width,disp_data.height,0);
         else
         if(numero == 2)
                   al_draw_scaled_bitmap(background3,0,0,XBKG,YBKG,0,0,disp_data.width,disp_data.height,0);
         else
             al_draw_scaled_bitmap(background4,0,0,XBKG,YBKG,0,0,disp_data.width,disp_data.height,0);
    }
    
    void DesenharSeta(ALLEGRO_BITMAP *seta, ALLEGRO_DISPLAY_MODE disp_data, int lugar)
    {
         if(lugar == DIREITA)
                  al_draw_bitmap(seta, disp_data.width - 130, disp_data.height / 2, ALLEGRO_FLIP_HORIZONTAL);
         else
             al_draw_bitmap(seta, 0, disp_data.height / 2, 0);
    }

    O problema parece ser onde colocar a função "al_flip_display()". Se coloco antes da seta, ela não aparece, se coloco depois, o background some e fica só a seta.

    Editado por Iury Benites
    • Curtir 1

    Compartilhar este post


    Link para o post
    Compartilhar em outros sites

    pense nesses elementos como se fosse na vida real. você está desenhando em um buffer todas essas imagens, se for fazer uma analogia o buffer seria a mesa de trabalho, na qual colocamos fotos em cima. O background seria a primeira imagem a por sobre a mesa(buffer) pois ela fica no fundo, logo colocaríamos a seta acima do fundo, pense como se fossem capas do fotoshop. A ordem correta é desenhar o fundo e posteriormente a seta, e por ultimo mostrar com o flip, essa seria a ordem correta.

    Posso lhe deixar um código feito as pressas:
     

    #include <allegro5/allegro.h> // Librería inicial de Allegro
    #include <allegro5/allegro_image.h>
    #include <allegro5/allegro_primitives.h> // Addon de primitivas (figuras)
    #include <allegro5/allegro_font.h>
    #include <allegro5/allegro_native_dialog.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    #include <windows.h>
    #define VENTANA_X 800
    #define VENTANA_Y 600
    #define DIREITA 1
    
    
    // Funciones
    void inicializar ( ALLEGRO_DISPLAY **display ) {
        // Inicializar los addons
        if ( !al_init() ) {
            fprintf ( stderr, "Error al inicializar Allegro." ); // Imprimir errores en stream STDERR
            exit ( -1 );
        }
    
        //Inicializando capacidade para manejo de imagenes
    //    if ( !al_init_image_addon() ) {
    //        al_show_native_message_box ( *display, "Error", "Error", "Failed to initialize al_init_image_addon!", NULL, ALLEGRO_MESSAGEBOX_ERROR );
    //        //return 0;
    //        exit ( -1 );
    //    }    
        
        //Inicializando capacidade para manejo de primitivas
        if ( !al_init_primitives_addon() ) {
            fprintf ( stderr, "Error al inicializar el addon de primitivas." ); // Imprimir errores en stream STDERR
            exit ( -2 );
        }
        
    
        *display = al_create_display ( VENTANA_X, VENTANA_Y ); // Crear el display de tamaño 500x300 píxeles
        
        al_set_window_title ( *display, "Ejemplo Allegro 5 - www.multiaportes.com" ); // Establecer el título de la ventana
    }
    
    void finalizar ( ALLEGRO_DISPLAY **display ) {
        al_shutdown_primitives_addon(); // Finalizar el addon de primitivas
        al_destroy_display ( *display ); // Destruir la ventana
    }
    
    
    void DesenharEscena ( ALLEGRO_BITMAP *background[4], int indice ) {
    
    }
    
    void DesenharSeta ( ALLEGRO_BITMAP *seta, ALLEGRO_DISPLAY_MODE disp_data, int dst ) {
        if ( dst == DIREITA )
            al_draw_bitmap ( seta, disp_data.width - 130, disp_data.height / 2, ALLEGRO_FLIP_HORIZONTAL );
        else
            al_draw_bitmap ( seta, 0, disp_data.height / 2, 0 );
    }
    
    int main ( void ) {
        
    
    /* Our window. */
    ALLEGRO_DISPLAY *display = NULL;
    /* Our tiles atlas. */
    //ALLEGRO_BITMAP *tiles;
    /* Our tilemap. */
    //int tile_map[100 * 100];
    /* Keep track of pressed mouse button. */
    int mouse;
    /* Camera parameters. */
    float zoom = 1.0, rotate;
    float scroll_x, scroll_y;
    /* Our icon font and background. */
    ALLEGRO_BITMAP *icon;
    ALLEGRO_FONT *font;
    ALLEGRO_BITMAP  *image[5] = {0};    
    /* Simple FPS counter. */
    int fps, fps_accum;
    double fps_time;
    /*cola de eventos*/    
    ALLEGRO_EVENT_QUEUE *queue;
    /*Usaremos para gestionar el tiempo. */
    ALLEGRO_TIMER *timer;
    /*usaremos para redeseñar la pagina. */
    bool redraw = true;
        
        //srand(time(NULL));
    
        /* Init Allegro 5 + addons. */
        al_init();
        al_init_image_addon();
        al_init_primitives_addon();
        al_init_font_addon();
        al_install_mouse();
        al_install_keyboard();
        
        inicializar ( &display );
    
        
        
        char path[100];
        for ( int i=0; i < 4 ; i++ ) {
            sprintf(path, "imagen/img%d.png", i);
            image[i] = al_load_bitmap ( path );
            if ( image[i] == NULL ) {
                al_show_native_message_box ( display, "Error", "Error", "Falhou ao carregar as imagens!", NULL, ALLEGRO_MESSAGEBOX_ERROR );
                al_destroy_display ( display );
                return 0;
            }    
        }
        
        
    
        
        /* The example will work without those, but there will be no
         * FPS display and no icon.
         */
        
        
       font = al_load_font("imagen/fixed_font.tga", 0, 0);
       if (!font) {
          printf("imagen/fixed_font.tga not found.\n");
          exit(-7);
       } 
        
        icon = al_load_bitmap("image/icon.tga");
        printf("%d", icon);
        if (icon) al_set_display_icon(display, icon);
    
        timer = al_create_timer(1.0 / 60);
        queue = al_create_event_queue();
        al_register_event_source(queue, al_get_keyboard_event_source());
        al_register_event_source(queue, al_get_mouse_event_source());
        al_register_event_source(queue, al_get_display_event_source(display));
        al_register_event_source(queue, al_get_timer_event_source(timer));
        al_start_timer(timer);
    
        while (1) {
            ALLEGRO_EVENT event;
            al_wait_for_event(queue, &event);
    
            if (event.type == ALLEGRO_EVENT_DISPLAY_CLOSE)
                break;
            if (event.type == ALLEGRO_EVENT_KEY_DOWN) {
                if (event.keyboard.keycode == ALLEGRO_KEY_ESCAPE)
                    break;
            }
            if (event.type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN) {
                mouse = event.mouse.button;
            }
            if (event.type == ALLEGRO_EVENT_MOUSE_BUTTON_UP) {
                mouse = 0;
            }
            if (event.type == ALLEGRO_EVENT_MOUSE_AXES) {
                //Left button scrolls.
                if (mouse == 1) {
                    float x = event.mouse.dx / zoom;
                    float y = event.mouse.dy / zoom;
                    scroll_x -= x * cos(rotate) + y * sin(rotate);
                    scroll_y -= y * cos(rotate) - x * sin(rotate);
                }
                //Right button zooms/rotates.
                if (mouse == 2) {
                    rotate += event.mouse.dx * 0.01;
                    zoom += event.mouse.dy * 0.01 * zoom;
                }
                zoom += event.mouse.dz * 0.1 * zoom;
                if (zoom < 0.1) zoom = 0.1;
                if (zoom > 10) zoom = 10;
    
            }
            if (event.type == ALLEGRO_EVENT_TIMER) redraw = true;
            if (event.type == ALLEGRO_EVENT_DISPLAY_RESIZE) {
                al_acknowledge_resize(display);
                redraw = true;
            }
    
            if (redraw && al_is_event_queue_empty(queue)) {
                redraw = false;
                double t = al_get_time();
                
                //draw here
                //tile_map_draw();
                al_draw_bitmap(image[0],0,0,0);
                al_draw_bitmap(image[3],600,300,0);
                
                if (font) {
                    al_draw_filled_rounded_rectangle(4, 4, 100, 30, 8, 8, al_map_rgba(255, 0, 0, 0));
                    al_draw_textf(font, al_map_rgb(255, 0, 0), 54, 8, ALLEGRO_ALIGN_CENTRE, "FPS: %d", fps);
                }
                al_flip_display();
                fps_accum++;
                if (t - fps_time >= 1) {
                    fps = fps_accum;
                    fps_accum = 0;
                    fps_time = t;
                }
            }
        }    
    
        for (int i=0; i<4 ; i++) {
            al_destroy_bitmap ( image[i] );
        }
        
        
        finalizar ( &display );
        return 0;
    }

    Não lhe servirá mais que como exemplo para ilustrar a ideia. Tem muita coisa errada nesse código mas também tem muitas idéias interessantes. Por exemplo podemos carregar imagens por lotes e seria possivel desenhar da mesma forma automatizando tudo.

    Um dos grandes erros que tem esse programa é o seguinte. Pense que você tem que carregar 4 imagens, você teria que fazer algo como:
    ALLEGRO_BITMAP  *image1 = al_load_bitmap ( "img1.png" );
    ALLEGRO_BITMAP  *image2 = al_load_bitmap ( "img2.png" );
    ....
    e assim por diante com cada uma delas. Qual o problema disso? Pois imagine que você teve sorte ao carregar 3 imagens, e justo na ultima o programa não encontra a 4ª imagem.... Que acontece? Consegue ver o erro?  Pois que se você usou return para sair do programa você criou um buraco na memória, pois você saiu sem liberar as 3 primeiras imagens pois a função al_load_bitmap () reserva memória dinamicamente e lhe retorna um ponteiro, e ja sabemos que tudo o que for dinâmico tem que ser liberado antes de sair, si não você tem um bonito vazamento de memória. Pois bem a coisa n4ao termina aí... imagina que depois de carregar 3 mil imagens e 500 musicas falha na hora da carga de uma fonte, se você acha que é só fazer um return você ta enganado, melhor seria você apagar o pc hahahaha. você precisa fazer um inventario de tudo o que foi carregado na memória de forma correta para ser liberado em caso de falho, e também em caso de sair do programa.

    em fim... se quiser o projeto completo para codeblocks para dar uma olhada é só dizer >_<

    fui

     

    • Curtir 1

    Compartilhar este post


    Link para o post
    Compartilhar em outros sites
  • Autor do tópico
  • @vangodp Lendo teu comentário em voz alta eu percebi meu erro (bem simples de resolver, inclusive). Na função que chamava a próxima tela (se o cursor estava numa das margens e clicava com o botão esquerdo), desenhava a imagem e já chamava al_flip_display(). Então quando eu desenhava a seta e usava al_flip_display(), ficava só a seta (erro de principiante, suponho).

    Sobre o código que tu postou, vou aproveitar com certeza o uso de vetores (considerando que todas as salas sempre terão 4 lados, posso usar um vetor estático sem problemas). Eu tinha tentado antes, mas esqueci que é um vetor de ponteiros.
    Acho que agora tenho o que é preciso pra terminar o jogo (mas antes, dar uma boa "limpa" no código, que tá cheio de coisas que não preciso mais)

    • Curtir 1

    Compartilhar este post


    Link para o post
    Compartilhar em outros sites
  • Autor do tópico
  • Caso alguém venha nesse post com a mesma dúvida, tá aqui um fluxograma bem simples da ordem a seguir.

    Map1.bmp

    • Curtir 2

    Compartilhar este post


    Link para o post
    Compartilhar em outros sites

    Crie uma conta ou entre para comentar

    Você precisar ser um membro para fazer um comentário






    Sobre o Clube do Hardware

    No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas publicações sobre tecnologia do Brasil. Leia mais

    Direitos autorais

    Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

    ×