segunda-feira, 13 de outubro de 2014

Jogo da cobrinha v 1.0 ...

Boa noite XD
Ontem a noite eu resolvir tentar programa um jogo... sim depois de muito tempo. XD
O jogo é da cobrinha no estilo mini game... Aqueles 50K jogos em 1.


Um imagem do jogo funcionando:


Você pode baixar o código fonte aqui:

https://drive.google.com/?tab=wo&authuser=0#folders/0Byb1BMOhtavhTXI1WmxLM3BFb0U


Eu meio q super exageradamente dividir o código em varios arquivos:



allegro.h:
/*

 * allegro.h
 *
 *  Created on: 12/10/2014
 *      Author: paulo
 *
#ifndef ALLEGRO_H_
#define ALLEGRO_H_

#include 
#include 
#include 
#include 
#include 
#include 


//Inicializa a biblioteca allegro
void allegro_inicializar(ALLEGRO_DISPLAY **janela, ALLEGRO_EVENT_QUEUE **fila_eventos, ALLEGRO_FONT **fonte);
//Fecha a bibliote allegro
void allegro_fechar(ALLEGRO_DISPLAY *janela, ALLEGRO_EVENT_QUEUE *fila_eventos, ALLEGRO_FONT *fonte);
#endif /* ALLEGRO_H_ *
allegro.c :
/*
 * allegro.c
 *
 *  Created on: 12/10/201
 *      Author: paulo
 *

#include "allegro.h"
//Inicializa a biblioteca allegro
void allegro_inicializar(ALLEGRO_DISPLAY **janela, ALLEGRO_EVENT_QUEUE **fila_eventos, ALLEGRO_FONT **fonte)
{
    if (!al_init())
    {
        fprintf(stderr, "Falha ao inicializar a biblioteca Allegro.\n");
        exit(-1);
    }
    if (!al_init_primitives_addon())
    {
        fprintf(stderr, "Falha ao inicializar add-on de primitivas.\n");
        exit(-1);
    }
    al_init_font_addon();


    if (!al_init_ttf_addon())
    {
        fprintf(stderr, "Falha ao inicializar add-on allegro_ttf.\n");
        exit(-1);
    }
    if (!al_install_keyboard())
    {
        fprintf(stderr, "Falha ao inicializar o teclado.\n");
        exit(-1);
    }

    *janela = al_create_display(480, 640);
    if (!(*janela))
    {
        fprintf(stderr, "Falha ao criar janela.\n");
        exit(-1);
    }

    *fila_eventos = al_create_event_queue();
    if (!(*fila_eventos))
    {
        fprintf(stderr, "Falha ao criar fila de eventos.\n");
        al_destroy_display((*janela));
        exit(-1);
    }


    al_register_event_source((*fila_eventos), al_get_keyboard_event_source());
    al_register_event_source((*fila_eventos), al_get_display_event_source((*janela)));

    *fonte = al_load_font("Action Man Bold.ttf", 16, 0);
    if (!(*fonte))
    {
        fprintf(stderr, "Falha ao carregar \"Action Man Bold.ttf\".\n");
        al_destroy_display((*janela));
        al_destroy_event_queue((*fila_eventos));
        exit(-1);
    }
    al_set_window_title((*janela), "Cobra (Snake)");

}

//Fecha a bibliote allegro
void allegro_fechar(ALLEGRO_DISPLAY *janela, ALLEGRO_EVENT_QUEUE *fila_eventos, ALLEGRO_FONT *fonte)
{
     al_destroy_display(janela);
     al_destroy_event_queue(fila_eventos);
     al_destroy_font(fonte);
}
desenho.h
/*
 * desenhos.h
 *
 *  Created on: 12/10/2014
 *      Author: paulo
 */

#ifndef DESENHOS_H_
#define DESENHOS_H_

#include 
#include 

//Desenha "pixel" de um LCD grafico de um mini-game
void desenha_pixel(int _x, int _y, ALLEGRO_COLOR cor, ALLEGRO_COLOR cor_fundo);

#endif /* DESENHOS_H_ */
desenho.c:
/*
 * desenhos.c
 *
 *  Created on: 12/10/2014
 *      Author: paulo
 */

#include "desenhos.h"


//Desenha "pixel" de um LCD grafico de um mini-game
void desenha_pixel(int _x, int _y, ALLEGRO_COLOR cor, ALLEGRO_COLOR cor_fundo)
{
 int x = 32 * _x;
 int y = 32 * _y;

 // Retângulo preenchido: x1, y1, x2, y2, cor
 al_draw_filled_rectangle(x, y, x + 32, y + 32, cor);
 al_draw_filled_rectangle(x + 4, y + 4, x + 28, y + 28, cor_fundo);
 al_draw_filled_rectangle(x + 8, y + 8, x + 24, y + 24, cor);

}
coord_int.h
/*

 * TAD que simula uma coordenada inteira
 *  Created on: 12/10/2014
 *      Author: paulo
 */

#ifndef COORD_INT_H_
#define COORD_INT_H_

#include <stdbool.h>

typedef struct tipo_coord_int
{
    int x; //0 - 9

    int y; //0 - 19

} tipo_coord_int;

tipo_coord_int coord_int(int x, int y);
//Compara duas coordenadas
bool coord_int_comp(tipo_coord_int A, tipo_coord_int B);

#endif /* COORD_INT_H_ *

coord_int.c
/*
 * coord_int.c
 *
 *  Created on: 12/10/2014
 *      Author: paulo
 *
#include "coord_int.h"

tipo_coord_int coord_int(int x, int y)
{
 tipo_coord_int novo;
 novo.x = x;
 novo.y = y;
 return novo;
}

//Compara duas coordenadas

bool coord_int_comp(tipo_coord_int A, tipo_coord_int B)
{
 return ((A.x == B.x) && (A.y == B.y));
}
cobra.h :
/*
 * TAD para manipulação da cobra do jogo

 *
 *  Created on: 12/10/2014
 *      Author: paulo
 */

#include <stdbool.h&gt


#include "desenhos.h"
#include "coord_int.h"


#ifndef COBRA_H_
#define COBRA_H_

typedef enum direcao {CIMA, BAIXO, ESQUERDA, DIREITA, NENHUM} direcao;

//Estrutura da cobra
typedef struct tipo_cobra
{
    int tamanho;
    direcao dir;
    tipo_coord_int coord[200]; // 20 x 10

} tipo_cobra;

//Inicializa a cobra
void cobra_inicializa(tipo_cobra *c);

//Atualiza a cobra
void cobra_atualiza(tipo_cobra *c);

//Aumenta o tamanho da cobra
void cobra_cresce(tipo_cobra *c);

//Desenha a cobra
void cobra_desenha(tipo_cobra *c, ALLEGRO_COLOR cor_fundo);

//Verifica se a cobra esta em uma determinada coordenada começando p
bool cobra_ver_coord(tipo_cobra *c, tipo_coord_int p, bool cabeca);

//Altera a direcao da cobra
void cobra_direcao(tipo_cobra *c, direcao dir);


//Retorna a coordenada da cabeça da cobra
tipo_coord_int cobra_coord (tipo_cobra *c);

#endif /* COBRA_H_ *

comida.h :
/*
 * comida.h
 *
 *  Created on: 12/10/2014
 *      Author: paulo
 */

#ifndef COMIDA_H_
#define COMIDA_H_

#include "coord_int.h"
#include "cobra.h"
#include "desenhos.h"

typedef struct tipo_comida
{
 tipo_coord_int coord;

} tipo_comida;

//Muda a posicao da comida (Onde não tem a cobra)
void comida_novo(tipo_comida *comida, tipo_cobra *cobra);

//Desenha a comida
void comida_desenha(tipo_comida *comida, ALLEGRO_COLOR cor_fundo);

//Coordenada  da comida
tipo_coord_int comida_coord(tipo_comida *comida);


#endif /* COMIDA_H_ */
comida.c :
/*
 * comida.c
 *
 *  Created on: 12/10/2014
 *      Author: paulo
 */

#include "comida.h"

//Muda a posicao da comida
void comida_novo(tipo_comida *comida, tipo_cobra *cobra)
{
 //De maneira aleatoira escolhe um local para a comida
 //Esse local não pode esta com a cobra

 int x = rand()%10;
 int y = rand()%20;

 while(cobra_ver_coord(cobra, coord_int(x,y), false))
 {
  x = rand()%10;
  y = rand()%20;
 }


 comida->coord.x = x;
 comida->coord.y = y;
}

void comida_desenha(tipo_comida *comida, ALLEGRO_COLOR cor_fundo)
{
 desenha_pixel(comida->coord.x, comida->coord.y, al_map_rgb(0,127,0), cor_fundo);
}

//Coordenada  da comida
tipo_coord_int comida_coord(tipo_comida *comida)
{
 return comida->coord;
}

jcobra_colisao.h:
/*
 * jcobra_colisao.h
 *
 *  Created on: 12/10/2014
 *      Author: paulo
 */

#ifndef JCOBRA_COLISAO_H_
#define JCOBRA_COLISAO_H_

#include "cobra.h"
#include "comida.h"

bool colisao_cobra_comida(tipo_cobra *cobra, tipo_comida *comida);

bool colisao_cobra_cobra (tipo_cobra *cobra);

#endif /* JCOBRA_COLISAO_H_ */

jcobra_colisao.c:
/*
 * jcobra_colisao.c
 *
 *  Created on: 12/10/2014
 *      Author: paulo
 */
#include "jcobra_colisao.h"

bool colisao_cobra_comida(tipo_cobra *cobra, tipo_comida *comida)
{
 return coord_int_comp(cobra_coord(cobra), comida_coord(comida));
}

bool colisao_cobra_cobra (tipo_cobra *cobra)
{
 return cobra_ver_coord(cobra, cobra_coord(cobra), true);
}

main.c:
/*
 * File:   main.c
 * Author: paulo
 *
 * Created on 12 de Outubro de 2014, 13:08
 */

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <time.h>
#include <math.h>
#include "allegro.h"
#include "cobra.h"
#include "comida.h"
#include "jcobra_colisao.h"

#define cor_fundo al_map_rgb(236, 236, 236)




//Modo classico do jogo da cobra
void jcobra_classico(ALLEGRO_EVENT_QUEUE *fila_eventos, ALLEGRO_FONT *fonte, int nivel);

int main()
{
 ALLEGRO_DISPLAY *janela = NULL;
 ALLEGRO_EVENT_QUEUE *fila_eventos = NULL;
 ALLEGRO_FONT *fonte = NULL;

 allegro_inicializar(&janela, &fila_eventos, &fonte);

 jcobra_classico( fila_eventos, fonte, 2);

 allegro_fechar(janela, fila_eventos, fonte);
    return 0;

}



void jcobra_desenha_dados(ALLEGRO_FONT *fonte,float pontos, int nivel)
{
/*
 * Desenhas os dados do jogo: Ponto, nivel
 * Desenha o retangulo
 */
 al_draw_rectangle(0, 0, 320, 640, al_map_rgb(0, 0, 0), 2);
 al_draw_textf(fonte, al_map_rgb(0, 0, 0), 324, 4, ALLEGRO_ALIGN_LEFT, "Pontos: %.2f", pontos);
 al_draw_textf(fonte, al_map_rgb(0, 0, 0), 324, 24, ALLEGRO_ALIGN_LEFT, "Nivel: %i", nivel);

}

direcao jcobra_direcao(ALLEGRO_EVENT evento)
{
 switch(evento.keyboard.keycode)
 {
  case ALLEGRO_KEY_UP:
   return CIMA;
  case ALLEGRO_KEY_DOWN:
   return BAIXO;
  case ALLEGRO_KEY_LEFT:
   return ESQUERDA;
  case ALLEGRO_KEY_RIGHT:
   return DIREITA;
  case ALLEGRO_KEY_P: //Pausa o jogo
   //parado = true;
   return NENHUM;
  }
 return NENHUM;
}

void jcobra_pause(ALLEGRO_EVENT_QUEUE *fila_eventos, ALLEGRO_FONT *fonte)
{

 ALLEGRO_EVENT evento;

 al_draw_text(fonte, al_map_rgb(0, 0, 0), 360, 320, ALLEGRO_ALIGN_LEFT, "PAUSE");
  al_flip_display();
 for(;;)
 {
  if(!al_event_queue_is_empty(fila_eventos))
  {
   al_wait_for_event(fila_eventos, &evento);
   if(evento.type == ALLEGRO_EVENT_KEY_DOWN)
   {
    if(evento.type == ALLEGRO_EVENT_KEY_DOWN)
    {
     if(evento.keyboard.keycode == ALLEGRO_KEY_P)
     {
      //parado = false;
      return;
     }
    }
   }
   else if (evento.type == ALLEGRO_EVENT_DISPLAY_CLOSE)
         {
          exit(0);
         }
  }
  al_rest(0.01);
 }
}

void jcobra_classico(ALLEGRO_EVENT_QUEUE *fila_eventos, ALLEGRO_FONT *fonte, int nivel)
{
 ALLEGRO_EVENT evento;
 tipo_cobra cobra;
 tipo_comida comida;
 cobra_inicializa(&cobra);
 comida_novo(&comida, &cobra);
 direcao dir_novo = NENHUM;
 float pontos = 0;
 float velocidade = 1/(pow(2,nivel));
 al_clear_to_color(cor_fundo); //Preenche com a cor do fundo

 srand(time(NULL)); //Chave aleatoria

    while (1)
    {
        if(!al_event_queue_is_empty(fila_eventos))
        {
         al_wait_for_event(fila_eventos, &evento);

         if(evento.type == ALLEGRO_EVENT_KEY_DOWN)
         {
          switch(evento.keyboard.keycode)
          {
          case ALLEGRO_KEY_UP:
           dir_novo = CIMA;
           break;
          case ALLEGRO_KEY_DOWN:
           dir_novo = BAIXO;
           break;
          case ALLEGRO_KEY_LEFT:
           dir_novo = ESQUERDA;
           break;
          case ALLEGRO_KEY_RIGHT:
           dir_novo = DIREITA;
           break;
          case ALLEGRO_KEY_P:
           jcobra_pause(fila_eventos, fonte); //Pausa o jogo
           break;
          }
            }
         if (evento.type == ALLEGRO_EVENT_DISPLAY_CLOSE)
         {
          break;
         }

        }
        else
        {
         cobra_direcao(&cobra, dir_novo);

         dir_novo = NENHUM;
         al_clear_to_color(cor_fundo); //Preenche com a cor do fundo


         cobra_atualiza(&cobra);

            if(colisao_cobra_comida(&cobra, &comida))
            {
             pontos+=(pow(2,nivel));
             comida_novo(&comida, &cobra);
             cobra_cresce(&cobra);
            }
            else if(colisao_cobra_cobra(&cobra))
            {
          pontos = 0;
             cobra_inicializa(&cobra);
            }

            cobra_desenha(&cobra,cor_fundo);
            comida_desenha(&comida, cor_fundo);

            jcobra_desenha_dados(fonte, pontos, nivel);
            al_flip_display();
            al_rest(velocidade); //Pausa
        }
    }

}



No proximo post comento sobre a implementação. Ate mais pessoas XD

sexta-feira, 10 de outubro de 2014

Enfim o primeiro jogo: Carro 1.00

Antes de mais nada estou usando a IDE Eclipse (vontade de apagar ela) pq a configuração dela para usar o Allegro 5 no WIN é (na minha opinião) mais fácil. Estou mais acostumado com o code::blocks mais fiquei com preguiça de configurar ele. A configuração no code::blocks não é coisa de outro mundo, pois tenho ela configurada no meu notebook. A configuração da biblioteca Allegro 5 no Linux é milagrosamente fácil (Eu uso o code::blocks também no Linux =P ).

Chega de enrolação vamos fala do primeiro jogo. Como falei antes eu me baseei no código feito pelo Marcos Romeiro usando o MRDX



A imagem acima mostra o jogo feito no MRDX.
O primeiro dilema que tive foi como fazer o código,  faço tudo em um arquivo carro.c ou divido em mais parte. faço tudo na main.c ou crio outras funções?... A minha escolha foi divide o código em 3 arquivos  estruturas.h, estruturas.c e main.c.

As estruturas iriam conter as funções, para manipular o jogador, os carros inimigos e a bandeira. E o main.c ia ter funções para inicializar o allegro e a criação das variáveis do jogo. Eu criei 3 estruturas:
tipo_carro_inimigo,  tipo_bandeira e tipo_jogador.

Eu achei legal desse código, pois me lembro de certa vez, ter lido em um site a seguinte pergunta: "Como faço no GameMaker ficar aparecendo as Naves inimigas" (algo do tipo)... O cara estava tentando fazer um jogo de nave. Não sei se a solução de ficar aparecendo os carros inimigos resolveria o problema dele. Vou tentar depois criar um jogo de nave XD....

Continuando...
Tinha que resolver os seguintes casos.
1) Como fazer os movimentos dos carros inimigos
2) Como fazer o movimento do personagem.
3) Como fazer o movimento da bandeira
4) Colisões
5) Escolhas dos pontos, e niveis.

Como fazer os movimentos dos carros inimigos

0 movimento do carro na vertical foi o mais simples de escolher. Escolhi simplesmente aumentar o valor do y do carro inimigo com base na velocidade (d = v * t kkkkkkkkkk... )...
E o movimento na horizontal que tive que escolher um método. Então a minha escolha foi movimentar aleatoriamente... com probabilidade de 1/3 para cada um dos seguintes movimento: no mover na vertical, mover para esquerda e para direita... Como pode ser visto no video essa escolha de movimento não foi muito legal.

Como fazer o movimento do personagem

A escolha do movimento do personagem. Foi algo bem tranquilo, as setas de direção move o personagem. Só que tive uma grande dificuldade para fazer essa parte. A ideia original era usar eventos. Usando evento eu não conseguir fazer os movimentos nas diagonais (segundo a internet, esse problema rola por causa da "matriz do teclado" , é utilizado esse método para economizar na produção dos teclados)...

A ideia original era o seguinte:

 void atualiza_jogador(tipo_jogador *jogador, int tecla)  
 {  
   switch(tecla)  
   {  
     case ALLEGRO_KEY_UP:  
       if(jogador->y - 8 > 0)  
       {  
         jogador->y -= 8;  
       }  
       else  
       {  
         jogador->y = 0;  
       }  
       break;  
     case ALLEGRO_KEY_DOWN:  
       if(jogador->y + 8 < 416)  
       {  
         jogador->y += 8;  
       }  
       else  
       {  
         jogador->y = 416;  
       }  
       break;  
     case ALLEGRO_KEY_RIGHT:  
       if(jogador->x + 8 < 440)  
       {  
         jogador->x += 8;  
       }  
       else  
       {  
         jogador->x = 440;  
       }  
       break;  
     case ALLEGRO_KEY_LEFT:  
       if(jogador->x - 8 > 160)  
       {  
         jogador->x -= 8;  
       }  
       else  
       {  
         jogador->x = 160;  
       }  
      }  
     break;  
 }  

 E na funcao jogo_main
 (...)  
                while(!al_is_event_queue_empty(fila_eventos)) //Verifica se tem eventos  
                {  
                     al_wait_for_event(fila_eventos, &evento);  
                     if (evento.type == ALLEGRO_EVENT_DISPLAY_CLOSE) //Fecha a janela  
                     {  
                          return;  
                     }  
                      if (evento.type == ALLEGRO_EVENT_KEY_DOWN)  
                     {  
                       atualiza_jogador(&jogador, evento.keyboard.keycode);            
                     }  
                 }  
 (...)  

Mais infelizmente não deu certo se alguém tiver uma solução para "Como usar eventos para reconhecer 2 teclas pressionadas"  eu aceito... A solução foi pesquisar... E pesquisar...  No Allegro 4 (eu nunca programei e nem estudei a biblioteca do Allegro 4, só vi alguns exemplos) tinha uma maneira legal de ver se uma tecla estava ativa. Então achei algo "semelhante": ALLEGRO_KEYBOARD_STATE *key_state,  al_get_keyboard_state(key_state) e al_key_down(key_state, ALLEGRO_KEY_UP)... A ultima funcao retorna 1 se a tecla estiver pressionada... bem legal neh...

Como fazer o movimento da bandeira

O movimento da bandeira é bem simples, equivale ao movimento dos carros inimigos na vertical só que com o dobro de velocidade...  

Colisões

A colisão escolhida foi o modelo mais simples... Usando colisão por retângulo. Mais por algum motivo desconhecido ainda não esta 100%funcional... pretendo melhorar isso...

Escolhas dos pontos, e niveis

Toda vez que é pego uma bandeira... Aumenta 1 ponto... Toda vez q estiver em multiplos de 5 o numero de pontos aumenta 1 nível e a velocidade... Simples neh? Mais tem uma pequena valha nesse método... Quanto os ponto com um valor múltiplo de 5... os níveis vão aumenta infinitamente... Ate que o jogador pegue uma outra bandeira... A solução para isso foi da 1 ponto, toda vez q o jogador muda de nivel... Mais quero mudar isso... =]

Outras rotinas e melhorias vou explicar na próxima postagem.  A versão 1.04 ja esta pronta...  XD
E na minha opinião ela esta muito boa...

Imagens do jogo


               


Para baixar o código e o programa:

https://drive.google.com/?tab=wo&authuser=0#folders/0Bw2jEGZIlh-4RllBT3lnUFkzYmc


estruturas.h:
1:  #include <stdio.h>  
2:  // Inclui o cabeçalho da bibilioteca Allegro 5  
3:  #include <allegro5/allegro.h>  
4:  #include <allegro5/allegro_image.h>  
5:  //Definicoes  
6:  #define MAX_CARROS 4  
7:  //-------------------------------------------------Carro inimigo--------------------------------------  
8:  typedef struct tipo_carro_inimigo  
9:  {  
10:       ALLEGRO_BITMAP *imagem;  
11:       short ativo;  
12:       int x;  
13:       int y;  
14:  } tipo_carro_inimigo;  
15:  //Carrega a imagem do carro  
16:  void carrega_carro_inimigo (tipo_carro_inimigo* carro_inimigo, char endereco[100]);  
17:  //Atualiza a posicao do carro  
18:  void atualiza_carro_inimigo (tipo_carro_inimigo* carro_inimigo, int velocidade);  
19:  //Desenha o carro na tela  
20:  void desenha_carro_inimigo (tipo_carro_inimigo* carro_inimigo);  
21:  //Verifica se o carro esta ativo  
22:  int status_carro_inimigo (tipo_carro_inimigo* carro_inimigo);  
23:  //Adiciona um carro no "jogo"  
24:  void add_carro_inimigo (tipo_carro_inimigo* carro_inimigo);  
25:  //-------------------------------------------------------bandeira------------------------------------ 
26:  typedef struct tipo_bandeira  
27:  {  
28:       ALLEGRO_BITMAP *imagem;  
29:       int x;  
30:       int y;  
31:  } tipo_bandeira;  
32:  //Carrega a imagem da bandeira  
33:  void carrega_bandeira(tipo_bandeira *bandeira, char endereco[100]);  
34:  //Atualiza a posicao da bandeira  
35:  void atualiza_bandeira(tipo_bandeira *bandeira, int velocidade);  
36:  //Desenha bandeira  
37:  void desenha_bandeira(tipo_bandeira *bandeira);  
38:  //-------------------------------------------------------jogador------------------------------------- 
39:  typedef struct tipo_jogador  
40:  {  
41:       ALLEGRO_BITMAP *imagem;  
42:       int x;  
43:       int y;  
44:  } tipo_jogador;  
45:  //Carrega a imagem do jogador  
46:  void carrega_jogador(tipo_jogador *jogador, char endereco[100]);  
47:  //Atualiza a posicao do jogador  
48:  void atualiza_jogador(tipo_jogador *jogador, ALLEGRO_KEYBOARD_STATE *key_state);  
49:  //Desenha o jogador na tela  
50:  void desenha_jogador(tipo_jogador *jogador);  
51:  //verifica se o jogador colidiu com algum carro  
52:  int colicao_jogador_carro_inimigo (tipo_jogador *jogador, tipo_carro_inimigo* carro_inimigo);  
53:  //verifica se o jogador colidiu com a bandeira  
54:  int colicao_jogador_bandeira (tipo_jogador *jogador, tipo_bandeira *bandeira);  

estruturas.c:
1:  #include "estruturas.h"  
2:  void carrega_carro_inimigo (tipo_carro_inimigo* carro_inimigo, char endereco[100])  
3:  {  
4:       //Carrega a imagem do carro  
5:       carro_inimigo->imagem = al_load_bitmap(endereco);  
6:       if(!(carro_inimigo->imagem))  
7:       {  
8:            fprintf(stderr, "Falha ao carregar a imagem %s\n", endereco);  
9:            exit(-1);  
10:       }  
11:       carro_inimigo->ativo = 0;  
12:  }  
13:  void atualiza_carro_inimigo (tipo_carro_inimigo* carro_inimigo, int velocidade)  
14:  {  
15:       carro_inimigo->y += velocidade;  
16:       if(carro_inimigo->y > 640)  
17:       {  
18:            carro_inimigo->ativo = 0;  
19:            return;  
20:       }  
21:       switch(rand()%3) //Move para esquerda ou direita  
22:       {  
23:            case 0:  
24:                 break;  
25:            case 1:  
26:                 carro_inimigo->x += velocidade;  
27:                 break;  
28:            case 2:  
29:                 carro_inimigo->x -= velocidade;  
30:       }  
31:       if(carro_inimigo->x > 440)  
32:       {  
33:            carro_inimigo->x = 440;  
34:       }  
35:       else if(carro_inimigo->x < 160)  
36:       {  
37:            carro_inimigo->x = 160;  
38:       }  
39:  }  
40:  //Desenha o carro na tela  
41:  void desenha_carro_inimigo (tipo_carro_inimigo* carro_inimigo)  
42:  {  
43:       al_draw_bitmap(carro_inimigo->imagem, carro_inimigo->x, carro_inimigo->y, 0);  
44:  }  
45:  void carrega_jogador(tipo_jogador *jogador, char endereco[100])  
46:  {  
47:       //Carrega a imagem  
48:       jogador->imagem = al_load_bitmap(endereco);  
49:       if(!(jogador->imagem))  
50:       {  
51:            fprintf(stderr, "Falha ao carregar a imagem %s\n", endereco);  
52:            exit(-1);  
53:       }  
54:       //Coloca a posição inicial do jogador  
55:       jogador->x = 208;  
56:       jogador->y = 400;  
57:  }  
58:  //Verifica se o carro esta ativo  
59:  int status_carro_inimigo (tipo_carro_inimigo* carro_inimigo)  
60:  {  
61:       return carro_inimigo->ativo;  
62:  }  
63:  //Adiciona um carro no "jogo"  
64:  void add_carro_inimigo (tipo_carro_inimigo* carro_inimigo)  
65:  {  
66:       carro_inimigo->y = -60;  
67:       carro_inimigo->x = rand()%280 + 160;  
68:       carro_inimigo->ativo = 1;  
69:  }  
70:  void atualiza_jogador(tipo_jogador *jogador, ALLEGRO_KEYBOARD_STATE *key_state)  
71:  {  
72:       al_get_keyboard_state(key_state);  
73:       if (al_key_down(key_state, ALLEGRO_KEY_UP))  
74:       {  
75:      if(jogador->y - 8 > 0)  
76:      {  
77:           jogador->y -= 8;  
78:      }  
79:      else  
80:      {  
81:           jogador->y = 0;  
82:      }  
83:       }  
84:       if (al_key_down(key_state, ALLEGRO_KEY_DOWN))  
85:       {  
86:      if(jogador->y + 8 < 416)  
87:      {  
88:           jogador->y += 8;  
89:      }  
90:      else  
91:      {  
92:           jogador->y = 416;  
93:      }  
94:       }  
95:       if (al_key_down(key_state, ALLEGRO_KEY_LEFT))  
96:       {  
97:      if(jogador->x - 8 > 160)  
98:      {  
99:           jogador->x -= 8;  
100:      }  
101:      else  
102:      {  
103:           jogador->x = 160;  
104:      }  
105:       }  
106:       if (al_key_down(key_state, ALLEGRO_KEY_RIGHT))  
107:       {  
108:      if(jogador->x + 8 < 440)  
109:      {  
110:           jogador->x += 8;  
111:      }  
112:      else  
113:      {  
114:           jogador->x = 440;  
115:      }  
116:       }  
117:  }  
118:  void desenha_jogador(tipo_jogador *jogador)  
119:  {  
120:       al_draw_bitmap(jogador->imagem, jogador->x, jogador->y, 0);  
121:  }  
122:  //verifica se o jogador colidiu com algum carro  
123:  int colicao_jogador_carro_inimigo (tipo_jogador *jogador, tipo_carro_inimigo* carro_inimigo)  
124:  {  
125:       if(jogador->x >= carro_inimigo->x + 40)  
126:       {  
127:            return 0;  
128:       }  
129:       if (jogador->x + 40 <= carro_inimigo->x)  
130:       {  
131:            return 0;  
132:       }  
133:       if(jogador->y >= carro_inimigo->y + 40)  
134:       {  
135:            return 0;  
136:       }  
137:       if (jogador->y + 40 <= carro_inimigo->y)  
138:       {  
139:            return 0;  
140:       }  
141:       return 1;  
142:  }  
143:  int colicao_jogador_bandeira (tipo_jogador *jogador, tipo_bandeira *bandeira)  
144:  {  
145:       if(jogador->x >= bandeira->x + 32)  
146:       {  
147:            return 0;  
148:       }  
149:       if (jogador->x + 40 <= bandeira->x)  
150:       {  
151:            return 0;  
152:       }  
153:       if(jogador->y >= bandeira->y + 32)  
154:       {  
155:            return 0;  
156:       }  
157:       if (jogador->y + 40 <= bandeira->y)  
158:       {  
159:            return 0;  
160:       }  
161:       bandeira->y = -60;  
162:       bandeira->x = rand()%280 + 160;  
163:       return 1;  
164:  }  
165:  //Carrega a imagem da bandeira  
166:  void carrega_bandeira(tipo_bandeira *bandeira, char endereco[100])  
167:  {  
168:       bandeira->imagem = al_load_bitmap(endereco);  
169:       if(!(bandeira->imagem))  
170:       {  
171:            fprintf(stderr, "Falha ao carregar a imagem %s\n", endereco);  
172:            exit(-1);  
173:       }  
174:       bandeira->y = -60;  
175:       bandeira->x = rand()%280 + 160;  
176:  }  
177:  //Atualiza a posicao da bandeira  
178:  void atualiza_bandeira(tipo_bandeira *bandeira, int velocidade)  
179:  {  
180:       bandeira->y += velocidade;  
181:       if(bandeira->y > 480)  
182:       {  
183:            bandeira->y = -60;  
184:            bandeira->x = rand()%280 + 160;  
185:       }  
186:  }  
187:  void desenha_bandeira(tipo_bandeira *bandeira)  
188:  {  
189:       al_draw_bitmap(bandeira->imagem, bandeira->x, bandeira->y, 0);  
190:  }  


main.c :

1:  //allegro 5  
2:  #include <allegro5/allegro.h>  
3:  #include <allegro5/allegro_image.h>  
4:  #include <allegro5/allegro_primitives.h>  
5:  #include <allegro5/allegro_font.h>  
6:  #include <allegro5/allegro_ttf.h>  
7:  #include <stdio.h>  
8:  #include <stdlib.h>  
9:  #include <time.h>  
10:  #include "estruturas.h"  
11:  //protótipos  
12:  //Inicializa a biblioteca Allegro  
13:  void inicializa_allegro(int LARGURA_TELA, int ALTURA_TELA, ALLEGRO_DISPLAY **janela, ALLEGRO_EVENT_QUEUE **fila_eventos);  
14:  //Principal funcao do jogo  
15:  void jogo_main (ALLEGRO_DISPLAY *janela, ALLEGRO_EVENT_QUEUE *fila_eventos);  
16:  int jogo_menu(ALLEGRO_DISPLAY *janela, ALLEGRO_EVENT_QUEUE *fila_eventos, ALLEGRO_FONT *fonte, int recorde);  
17:  int main ()  
18:  {  
19:       ALLEGRO_DISPLAY *janela = NULL;  
20:       ALLEGRO_EVENT_QUEUE *fila_eventos = NULL;  
21:       //Tamanho da tela  
22:       int LARGURA_TELA = 640;  
23:       int ALTURA_TELA = 480;  
24:       inicializa_allegro( LARGURA_TELA, ALTURA_TELA, &janela, &fila_eventos);  
25:       //Muda o titulo da janela  
26:       al_set_window_title(janela, "Carros");  
27:       //Gera uma chave aleatoria;  
28:       srand(time(NULL));  
29:       jogo_main(janela, fila_eventos);  
30:       return 0;  
31:  }  
32:  void inicializa_allegro(int LARGURA_TELA, int ALTURA_TELA, ALLEGRO_DISPLAY **janela, ALLEGRO_EVENT_QUEUE **fila_eventos)  
33:  {  
34:       // Inicializa a Allegro  
35:       if (!al_init())  
36:    {  
37:      fprintf(stderr, "Falha ao inicializar a Allegro.\n");  
38:      exit (-1);  
39:    }  
40:       // Inicializa o add-on para utilização de imagens  
41:    if (!(al_init_image_addon()))  
42:    {  
43:      fprintf(stderr, "Falha ao inicializar add-on allegro_image.\n");  
44:      exit (-1);  
45:    }  
46:    //Cria a janela  
47:    *janela = al_create_display(LARGURA_TELA, ALTURA_TELA);  
48:    if (!(*janela))  
49:    {  
50:      fprintf(stderr, "Falha ao criar janela.\n");  
51:      exit (-1);  
52:    }  
53:    //Cria uma fila de eventos  
54:    *fila_eventos = al_create_event_queue();  
55:    if (!(*fila_eventos))  
56:    {  
57:      fprintf(stderr, "Falha ao criar fila de eventos.\n");  
58:      al_destroy_display(*janela);  
59:      exit (-1);  
60:    }  
61:    //Inicia o teclado  
62:    if (!al_install_keyboard())  
63:    {  
64:      fprintf(stderr, "Falha ao inicializar o teclado.\n");  
65:      exit(-1);  
66:    }  
67:    if (!al_init_primitives_addon())  
68:    {  
69:      fprintf(stderr, "Falha ao inicializar add-on de primitivas.\n");  
70:      exit(-1);  
71:    }  
72:    // Inicialização do add-on para uso de fontes  
73:    al_init_font_addon();  
74:    // Inicialização do add-on para uso de fontes True Type  
75:    if (!al_init_ttf_addon())  
76:    {  
77:      fprintf(stderr, "Falha ao inicializar add-on allegro_ttf.\n");  
78:      exit(-1);  
79:    }  
80:  }  
81:  void jogo_main (ALLEGRO_DISPLAY *janela, ALLEGRO_EVENT_QUEUE *fila_eventos)  
82:  {  
83:       ALLEGRO_FONT *fonte;  
84:       int velocidade;  
85:       int pontuacao;  
86:       int nivel;  
87:       int recorde = 0;  
88:       int distancia;  
89:       int i;  
90:       int indicie_carro;  
91:       int menu = 0;  
92:       const int CARRO_MAX = 4; //Numero maximo de carro  
93:       tipo_jogador jogador;  
94:       tipo_carro_inimigo carro_inimigo[CARRO_MAX];  
95:       tipo_bandeira bandeira;  
96:       ALLEGRO_EVENT evento;  
97:       ALLEGRO_KEYBOARD_STATE key_state;  
98:       //inicia o jogador  
99:       carrega_jogador(&jogador, "jogador.png");  
100:       //Carrega inimigos  
101:       for(i = 0; i < CARRO_MAX; i++)  
102:       {  
103:            carrega_carro_inimigo(&carro_inimigo[i], "inimigo.png");  
104:       }  
105:       //Carrega a bandeira  
106:       carrega_bandeira(&bandeira, "bandeira.png");  
107:       //Regista evento da janela  
108:    al_register_event_source(fila_eventos, al_get_display_event_source(janela));  
109:    al_register_event_source(fila_eventos, al_get_keyboard_event_source());  
110:    //Carrega a fonte usada  
111:    fonte = al_load_font("Ubahn.ttf", 24, 0);  
112:    if(!fonte)  
113:    {  
114:         fprintf(stderr ,"Falha ao carregar a fonte\n");  
115:         exit(-1);  
116:    }  
117:    while(1)  
118:       {  
119:            velocidade = 4;  
120:            pontuacao = 0;  
121:            nivel = 0;  
122:            distancia = 0;  
123:            indicie_carro = 0;  
124:            menu = 0;  
125:            //inicia o menu;  
126:            if(!jogo_menu(janela, fila_eventos, fonte, recorde))  
127:            {  
128:                 return;  
129:            }  
130:            while(1)  
131:            {  
132:                 while(!al_is_event_queue_empty(fila_eventos)) //Verifica se tem eventos  
133:                 {  
134:                      al_wait_for_event(fila_eventos, &evento);  
135:                      if (evento.type == ALLEGRO_EVENT_DISPLAY_CLOSE) //Fecha a janela  
136:                      {  
137:                           return;  
138:                      }  
139:                 }  
140:                 //Atualiza jogador  
141:                 atualiza_jogador(&jogador, &key_state);  
142:                 //Adiciona carros  
143:                 if(distancia >= 200)  
144:                 {  
145:                      add_carro_inimigo(&carro_inimigo[indicie_carro]);  
146:                      indicie_carro++;  
147:                      indicie_carro %= CARRO_MAX;  
148:                      distancia = 0;  
149:                 }  
150:                 else  
151:                 {  
152:                      distancia += velocidade;  
153:                 }  
154:                 //Limpa a tela  
155:                 al_clear_to_color(al_map_rgb(0, 0, 0));  
156:                 //Desenha um retangulo  
157:                 al_draw_filled_rectangle(160, 0, 480, 480, al_map_rgb(125, 125, 125));  
158:                 //Atualiza os carros inimigos  
159:                 for(i = 0; i < CARRO_MAX; i++)  
160:                 {  
161:                      if(status_carro_inimigo(&carro_inimigo[i]))  
162:                      {  
163:                           atualiza_carro_inimigo(&carro_inimigo[i], velocidade);  
164:                           //Desenha o carro  
165:                           desenha_carro_inimigo(&carro_inimigo[i]);  
166:                           if(colicao_jogador_carro_inimigo(&jogador, &carro_inimigo[i]))  
167:                           {  
168:                                menu = 1; //Volta para o menu inicial  
169:                           }  
170:                      }  
171:                 }  
172:                 if(menu) break; //Volta para o menu inicial  
173:                 //Atualiza a bandeira  
174:                 atualiza_bandeira(&bandeira, 2 * velocidade);  
175:                 desenha_bandeira(&bandeira);  
176:                 if(colicao_jogador_bandeira(&jogador, &bandeira))  
177:                 {  
178:                      pontuacao++;  
179:                      printf("%i ", nivel);  
180:                 }  
181:                 if(pontuacao%5 == 0) //Mudar isso  
182:                 {  
183:                      pontuacao++;  
184:                      nivel++;  
185:                      velocidade++;  
186:                 }  
187:                 //Desenha o jogador  
188:                 desenha_jogador(&jogador);  
189:                 //Atualiza a tela  
190:                 al_draw_textf(fonte, al_map_rgb(255, 0, 0), 10, 10, ALLEGRO_ALIGN_LEFT, "Nivel: %i", nivel);  
191:                 al_draw_textf(fonte, al_map_rgb(255, 0, 0), 10, 34, ALLEGRO_ALIGN_LEFT, "pontuacao: %i", pontuacao);  
192:                 al_flip_display();  
193:                 al_rest(0.08);  
194:            }  
195:            //Muda o record  
196:            if(recorde < pontuacao)  
197:            {  
198:                 recorde = pontuacao;  
199:            }  
200:       }  
201:  }  
202:  int jogo_menu(ALLEGRO_DISPLAY *janela, ALLEGRO_EVENT_QUEUE *fila_eventos, ALLEGRO_FONT * fonte, int recorde)  
203:  {  
204:       //Limpa a tela  
205:       al_clear_to_color(al_map_rgb(0, 0, 0));  
206:       al_draw_text(fonte, al_map_rgb(255, 0, 0), 220, 120, ALLEGRO_ALIGN_LEFT, "Enter - Novo Jogo");  
207:       al_draw_text(fonte, al_map_rgb(255, 0, 0), 220, 144, ALLEGRO_ALIGN_LEFT, "ESC - sair");  
208:       al_draw_textf(fonte, al_map_rgb(255, 0, 0), 220, 168, ALLEGRO_ALIGN_LEFT, "Recorde: %i", recorde);  
209:       al_flip_display();  
210:       ALLEGRO_EVENT evento;  
211:       while(1) //Verifica se tem eventos  
212:       {  
213:            if(!al_is_event_queue_empty(fila_eventos))  
214:            {  
215:                 al_wait_for_event(fila_eventos, &evento);  
216:                 if(evento.keyboard.keycode == ALLEGRO_KEY_ESCAPE)  
217:                 {  
218:                      return 0;  
219:                 }  
220:                 if (evento.keyboard.keycode == ALLEGRO_KEY_ENTER)  
221:                 {  
222:                      return 1;  
223:                 }  
224:                 if (evento.type == ALLEGRO_EVENT_DISPLAY_CLOSE) //Fecha a janela  
225:                 {  
226:                      return 0;  
227:                 }  
228:            }  
229:       }  
230:       return 0;  
231:  }  

Tiled com Camada

Hj eu melhorei um pouco a logica do TilesMap, e agora criei uma rotina para tratar de camadas... Permitindo, assim... Mapas mais elaborados...
Novamente o programa que usei foi o  Tiled para fazer o mapa...






Primeiramente antes de sair programando, vou novamente definir o padrão da entrada... Exportando do Tiled... temos algo assim:




 [header]  
 width=13  
 height=10  
 tilewidth=64  
 tileheight=64  
 [tilesets]  
 tileset=../Pictures/Desenhos vetores/BLOCOS.png,64,64,0,0  
 tileset=../Pictures/Desenhos vetores/pipes.png,64,64,0,0  
 tileset=../Pictures/Desenhos vetores/Terreno.png,64,64,0,0  
 tileset=../Pictures/Desenhos vetores/simples1.png,64,64,0,0  
 [layer]  
 type=FUNDO  
 data=  
 338,338,338,338,338,338,338,338,338,338,338,338,338,  
 338,338,338,338,338,338,338,338,338,338,338,338,338,  
 338,338,338,338,338,338,338,338,338,338,338,338,338,  
 338,338,338,338,338,338,338,338,338,338,338,338,338,  
 338,338,338,338,338,338,338,338,338,338,338,338,338,  
 338,338,338,338,338,338,338,338,338,338,338,338,338,  
 338,338,338,338,338,338,338,338,338,338,338,338,338,  
 340,340,340,340,340,340,340,340,340,340,340,340,340,  
 340,340,340,340,340,340,340,340,340,340,340,340,340,  
 340,340,340,340,340,340,340,340,340,340,340,340,340  
 [layer]  
 type=MAIN  
 data=  
 0,0,0,0,0,0,0,0,0,0,0,0,0,  
 2,2,2,0,0,0,0,0,0,0,0,366,0,  
 0,0,2,0,0,0,0,0,0,0,0,0,0,  
 2,2,2,0,0,0,0,101,102,0,0,366,0,  
 2,0,0,0,0,0,0,107,108,0,0,0,0,  
 2,2,2,0,0,97,98,107,108,0,0,365,0,  
 0,0,0,0,0,103,104,107,108,0,364,363,364,  
 194,194,194,195,0,103,104,107,108,0,193,194,194,  
 200,200,200,201,0,103,104,107,108,0,199,200,200,  
 200,200,200,201,0,103,104,107,108,0,199,200,200  
 [layer]  
 type=SUPERIOR  
 data=  
 0,0,291,0,0,291,0,0,0,0,293,0,0,  
 0,0,0,0,293,0,0,293,0,0,0,0,0,  
 0,0,0,0,0,0,0,0,0,291,0,0,0,  
 0,0,0,0,0,293,0,0,0,0,0,0,0,  
 0,0,0,293,0,0,0,0,0,0,0,0,0,  
 0,0,0,0,0,0,0,0,0,0,0,0,0,  
 0,0,0,0,0,0,0,0,0,0,0,0,0,  
 0,0,0,0,0,358,358,358,358,0,0,0,0,  
 0,0,0,0,0,358,358,358,358,0,0,0,0,  
 0,0,0,0,0,358,358,358,358,0,0,0,0  
 [layer]  
 type=SUPERIOR 2  
 data=  
 0,0,312,0,0,0,0,0,0,0,0,0,0,  
 0,0,0,0,312,0,0,306,0,0,0,0,0,  
 0,0,0,0,0,0,0,0,0,0,0,0,0,  
 0,0,0,0,0,306,0,0,0,0,0,0,0,  
 0,0,0,306,0,0,0,0,0,0,0,0,0,  
 0,0,0,0,0,0,0,0,0,0,0,0,0,  
 0,0,0,0,0,0,0,0,0,0,0,0,0,  
 0,0,0,0,0,0,0,0,0,0,0,0,0,  
 0,0,0,0,317,317,317,317,317,317,0,0,0,  
 0,0,0,0,0,0,0,0,0,0,0,0,0  


O que eu modifiquei para:
 [FUNDO]  
 1  
 13 10 0 0  
 338 338 338 338 338 338 338 338 338 338 338 338 338   
 338 338 338 338 338 338 338 338 338 338 338 338 338   
 338 338 338 338 338 338 338 338 338 338 338 338 338   
 338 338 338 338 338 338 338 338 338 338 338 338 338   
 338 338 338 338 338 338 338 338 338 338 338 338 338   
 338 338 338 338 338 338 338 338 338 338 338 338 338   
 338 338 338 338 338 338 338 338 338 338 338 338 338   
 340 340 340 340 340 340 340 340 340 340 340 340 340   
 340 340 340 340 340 340 340 340 340 340 340 340 340   
 340 340 340 340 340 340 340 340 340 340 340 340 340  
 [PRINCIPAL]  
 13 10 0 0  
 0 0 0 0 0 0 0 0 0 0 0 0 0   
 2 2 2 0 0 0 0 0 0 0 0 366 0   
 0 0 2 0 0 0 0 0 0 0 0 0 0   
 2 2 2 0 0 0 0 101 102 0 0 366 0   
 2 0 0 0 0 0 0 107 108 0 0 0 0   
 2 2 2 0 0 97 98 107 108 0 0 365 0   
 0 0 0 0 0 103 104 107 108 0 364 363 364   
 194 194 194 195 0 103 104 107 108 0 193 194 194   
 200 200 200 201 0 103 104 107 108 0 199 200 200   
 200 200 200 201 0 103 104 107 108 0 199 200 200  
 [SUPERIOR]  
 2  
 13 10 0 0  
 0 0 291 0 0 291 0 0 0 0 293 0 0   
 0 0 0 0 293 0 0 293 0 0 0 0 0   
 0 0 0 0 0 0 0 0 0 291 0 0 0   
 0 0 0 0 0 293 0 0 0 0 0 0 0   
 0 0 0 293 0 0 0 0 0 0 0 0 0   
 0 0 0 0 0 0 0 0 0 0 0 0 0   
 0 0 0 0 0 0 0 0 0 0 0 0 0   
 0 0 0 0 0 358 358 358 358 0 0 0 0   
 0 0 0 0 0 358 358 358 358 0 0 0 0   
 0 0 0 0 0 358 358 358 358 0 0 0 0  
 13 10 0 0  
 0 0 312 0 0 0 0 0 0 0 0 0 0   
 0 0 0 0 312 0 0 306 0 0 0 0 0   
 0 0 0 0 0 0 0 0 0 0 0 0 0   
 0 0 0 0 0 306 0 0 0 0 0 0 0   
 0 0 0 306 0 0 0 0 0 0 0 0 0   
 0 0 0 0 0 0 0 0 0 0 0 0 0   
 0 0 0 0 0 0 0 0 0 0 0 0 0   
 0 0 0 0 0 0 0 0 0 0 0 0 0   
 0 0 0 0 317 317 317 317 317 317 0 0 0   
 0 0 0 0 0 0 0 0 0 0 0 0 0  


O arquivo de entrada tem as seguintes maracao [FUNDO], [PRINCIPAL] e [SUPERIOR]...  Estas marcação estão no arquivo e são ignoradas no programa... A camada principal so existe 1, ja as camadas superir e fundo pode existe mais de uma, ou ate mesmo nenhuma. No inicio da descrição da camada temos o seu tamanho e a sua coordenada de origem (que pretendo usar isso no futuro, ou simplesmente retirar kkk... )

O código pode ser baixado aqui:
https://drive.google.com/?tab=wo&authuser=0#folders/0Bw2jEGZIlh-4OV9xOUlhV0FjS0E





#include "mapa.h"

int main()
{
 tipo_allegro5 DATA;
 tipo_mapa mapa;

 //Inicializa o Allegro e cria uma janela 800 x 600
 allegro_inicializa(&DATA, 800, 600);
 al_clear_to_color(al_map_rgb(0, 0, 0)); //Limpa a tela


 inicializa_tipo_mapa(&mapa); //Inicializa a variavel mapa para que ela possar ser usada
 load_mapa(&mapa, "./level/level1.txt"); //Carrega o Mapa
 desenha_level_all(&mapa,0,0); // Desenha o Mapa na tela
 al_flip_display(); //Atualiza a tela
 al_rest(5); //Aguarde 5segundos
 free_tipo_mapa(&mapa); //Libera memoria do Mapa

 al_clear_to_color(al_map_rgb(0, 0, 0)); //Limpa a tela

 load_mapa(&mapa, "./level/level2.txt"); //Carrega o Mapa
 desenha_level_all(&mapa,0,0); // Desenha o Mapa na tela
 al_flip_display(); //Atualiza a tela
 al_rest(5); //Aguarde 5segundos
 free_tipo_mapa(&mapa); //Libera memoria do Mapa

 return 0;
}



#include "mapa.h"


//Inicializa a variavel
void inicializa_tipo_mapa (tipo_mapa *mapa)
{
 mapa->camada_fundo = NULL;
 mapa->camada_superior = NULL;
 mapa->num_camada_fundo = 0;
 mapa->num_camada_superior = 0;
}


void load_mapa(tipo_mapa *mapa, char endereco[100])
{
 int num_de_camadas;
 int num_tiles_vert;
 int num_tiles_horizontal;
 int x_inicial;
 int y_inicial;
 int i, j, k;
 FILE *level;
 int valor;

 add_tileset(mapa, "./imagem/tileset/64/BLOCOS.png", 0);
 add_tileset(mapa, "./imagem/tileset/64/pipes.png", 1);
 add_tileset(mapa, "./imagem/tileset/64/Terreno.png", 2);
 add_tileset(mapa, "./imagem/tileset/64/simples1.png", 3);

 //Abri o arquivo com o mapa
 level = fopen(endereco, "r");

 //Ler as camadas do fundo
 fscanf(level, "%*s"); //Ler a palavra [FUNDO] e nao salva
 fscanf(level, "%i", &num_de_camadas); //Ler o numero de camadas do fundo

 mapa->num_camada_fundo = num_de_camadas;
 if(num_de_camadas > 0)
 {
  mapa->camada_fundo = (tipo_tilemapa *) malloc (sizeof(tipo_tilemapa *) * num_de_camadas);

  for(k = 0; k < num_de_camadas; k++)
  {
   fscanf(level, "%i %i %i %i", &num_tiles_horizontal, &num_tiles_vert, &x_inicial, &y_inicial);
   //Aloca memoria para a camada principal;
   mapa->camada_fundo[k].mapa = (int *) malloc (sizeof(int) * num_tiles_vert * num_tiles_horizontal);
   mapa->camada_fundo[k].num_tiles_horizontal = num_tiles_horizontal;
   mapa->camada_fundo[k].num_tiles_vert = num_tiles_vert;

   //Ler os dados do mapa
   for(i = 0; i < num_tiles_vert; i++)
   {
    for(j = 0; j < num_tiles_horizontal; j++)
    {
     fscanf(level, "%i", &valor);
     valor--;
     mapa->camada_fundo[k].mapa[i * num_tiles_horizontal + j] = valor;

    }
   }
  }
 }

 //Ler as camada principal
 fscanf(level, "%*s"); //Ler a palavra [PRINCIPAL] e nao salva
 fscanf(level, "%i %i %*i %*i", &num_tiles_horizontal, &num_tiles_vert); //Ler o comprimento da camada principal;
 mapa->camada_principal.num_tiles_horizontal = num_tiles_horizontal;
 mapa->camada_principal.num_tiles_vert = num_tiles_vert;
 mapa->camada_principal.x_inicial  = 0; //A camada principal sempre começa no (0,0)
 mapa->camada_principal.y_inicial = 0;

 //Aloca memoria para a camada principal;
 mapa->camada_principal.mapa = (int *) malloc (sizeof(int) * num_tiles_vert * num_tiles_horizontal);
 if(!(mapa->camada_principal.mapa))
 {
  fprintf(stderr, "Erro ao alocar memorica para camada principal, total de memoria solicitada: %in", sizeof(int) * num_tiles_vert * num_tiles_horizontal);
  exit(-1);
 }

 //Ler os dados do mapa
 for(i = 0; i < num_tiles_vert; i++)
 {
  for(j = 0; j < num_tiles_horizontal; j++)
  {
   fscanf(level, "%i", &valor);
   valor--;
   mapa->camada_principal.mapa[i * num_tiles_horizontal + j] = valor;
  }
 }

 //Ler as camadas superiores
 fscanf(level, "%*s"); //Ler a palavra [SUPERIOR] e nao salva
 fscanf(level, "%i", &num_de_camadas); //Ler o numero de camadas do fundo

 mapa->num_camada_superior = num_de_camadas;
 if(num_de_camadas > 0)
 {
  mapa->camada_superior = (tipo_tilemapa *) malloc (sizeof(tipo_tilemapa *) * num_de_camadas);

  for(k = 0; k < num_de_camadas; k++)
  {
   fscanf(level, "%i %i %i %i", &num_tiles_horizontal, &num_tiles_vert, &x_inicial, &y_inicial);
   //Aloca memoria para a camada principal;
   mapa->camada_superior[k].mapa = (int *) malloc (sizeof(int) * num_tiles_vert * num_tiles_horizontal);
   mapa->camada_superior[k].num_tiles_horizontal = num_tiles_horizontal;
   mapa->camada_superior[k].num_tiles_vert = num_tiles_vert;

   //Ler os dados do mapa
   for(i = 0; i < num_tiles_vert; i++)
   {
    for(j = 0; j < num_tiles_horizontal; j++)
    {
     fscanf(level, "%i", &valor);
     valor--;
     mapa->camada_superior[k].mapa[i * num_tiles_horizontal + j] = valor;

    }
   }
  }
 }

 //Fecha o arquivo com o level
 fclose(level);

}

//Desenha o mapa na tela
void desenha_level_all (tipo_mapa *mapa, int x, int y)
{
 desenha_level_fundo(mapa, x, y);
 desenha_level_main(mapa, x, y);
 desenha_level_super(mapa, x, y);
}

void desenha_level_main(tipo_mapa *mapa, int x, int y)
{
 int i, j;

 int num_vert = mapa->camada_principal.num_tiles_vert;
 int num_horiz = mapa->camada_principal.num_tiles_horizontal;
 int * MAPA = mapa->camada_principal.mapa;
 int valor;
 for(i = 0; i < num_vert; i++)
 {
  for(j = 0; j < num_horiz; j++)
  {
   //Por padrão todos os tileset terão 96 tiles distribuido
   //em 6 colunas e 16 linhas. todos os tiles Serão quadrados 64x64

   valor = MAPA[i * num_horiz + j];

   if(valor < 0) continue;
   al_draw_bitmap_region(mapa->tileset[valor/96],64 * (valor%6) , 64 * ((valor%96)/6), 64, 64, j * 64 + x, i * 64 + y, 0);

  }
 }
}

void desenha_level_fundo(tipo_mapa *mapa, int x, int y)
{
 int i, j , k;
 int num_vert;
 int num_horiz;
 int * MAPA;
 int valor;


 for (k = 0; k < mapa->num_camada_fundo; k++)
 {
  num_vert = mapa->camada_fundo[k].num_tiles_vert;
  num_horiz = mapa->camada_fundo[k].num_tiles_horizontal;
  MAPA = mapa->camada_fundo[k].mapa;
  for(i = 0; i < num_vert; i++)
  {
   for(j = 0; j < num_horiz; j++)
   {
    valor = MAPA[i * num_horiz + j];
    if(valor < 0) continue;
    al_draw_bitmap_region(mapa->tileset[valor/96],64 * (valor%6) , 64 * ((valor%96)/6), 64, 64, j * 64 + x, i * 64 + y, 0);
   }
  }
 }
}

void desenha_level_super(tipo_mapa *mapa, int x, int y)
{
 int i, j , k;
 int num_vert;
 int num_horiz;
 int * MAPA;
 int valor;


 for (k = 0; k < mapa->num_camada_superior; k++)
 {
  num_vert = mapa->camada_superior[k].num_tiles_vert;
  num_horiz = mapa->camada_superior[k].num_tiles_horizontal;
  MAPA = mapa->camada_superior[k].mapa;
  for(i = 0; i < num_vert; i++)
  {
   for(j = 0; j < num_horiz; j++)
   {
    valor = MAPA[i * num_horiz + j];
    if(valor < 0) continue;
    al_draw_bitmap_region(mapa->tileset[valor/96],64 * (valor%6) , 64 * ((valor%96)/6), 64, 64, j * 64 + x, i * 64 + y, 0);
   }
  }
 }

}


void add_tileset (tipo_mapa *mapa, char endereco[100], int id)
{

 mapa->tileset[id] = al_load_bitmap(endereco);
 if(!(mapa->tileset[id]))
 {
  fprintf(stderr, "Falha ao carregar a imagem %sn", endereco);
  exit(-1);
 }
}


void free_tipo_mapa (tipo_mapa *mapa)
{
 int i;

 //Libera a memoria da camada do fundo
 if( mapa->num_camada_fundo > 0)
 {
  for(i = 0; i < mapa->num_camada_fundo; i++)
  {
   free(mapa->camada_fundo[i].mapa);
  }
  free(mapa->camada_fundo);
  mapa->camada_fundo = NULL;
  mapa->num_camada_fundo = 0;
 }

 //Libera a memoria da camada principal
 free(mapa->camada_principal.mapa);

 //Libera a memoria da camada fundo
 if( mapa->num_camada_superior  > 0)
 {
  for(i = 0; i < mapa->num_camada_superior; i++)
  {
   free(mapa->camada_superior[i].mapa);
  }
  free(mapa->camada_superior);
  mapa->camada_superior = NULL;
  mapa->num_camada_superior = 0;
 }

 //Libera a memoria do tileset
 for(i = 0; i < TOTAL_TILESET; i++)
 {
  if(mapa->tileset[i])
  {
   al_destroy_bitmap(mapa->tileset[i]);
  }
 }

}



#ifndef MAPA_H_
#define MAPA_H_

#include "allegro5.h"
#define TOTAL_TILESET 4

typedef struct tipo_tilemapa
{
 //Mapa
 int *mapa;
 int num_tiles_vert;
 int num_tiles_horizontal;

 //Posicao inicial
 int x_inicial;
 int y_inicial;

} tipo_tilemapa;

typedef struct tipo_mapa
{
 ALLEGRO_BITMAP *tileset[TOTAL_TILESET];

 //Mapas fixos
 tipo_tilemapa  camada_principal;
 int num_camada_fundo;
 tipo_tilemapa *camada_fundo;
 int num_camada_superior;
 tipo_tilemapa *camada_superior;

} tipo_mapa;

//Inicializa a variavel
void inicializa_tipo_mapa (tipo_mapa *mapa);

//Carrega um mapa
void load_mapa(tipo_mapa *mapa, char endereco[100]);

//Desenha o mapa na tela
void desenha_level_all (tipo_mapa *mapa, int x, int y);
void desenha_level_main(tipo_mapa *mapa, int x, int y);
void desenha_level_fundo(tipo_mapa *mapa, int x, int y);
void desenha_level_super(tipo_mapa *mapa, int x, int y);

//Libera a Memoria e volta para o estado inicial uma variavel do tipo_mapa
void free_tipo_mapa (tipo_mapa *mapa);

void add_tileset (tipo_mapa *mapa, char endereco[100], int id);



#endif /* MAPA_H_ */



Uma coisa que quero destacar aqui é o uso de funções para liberação de memoria... Enrolei essa postagem por um motivo não estou conseguindo imaginar a interação personagem e cenário kkk...

TileMap

Fala Galeria... Quem é vivo sempre aparece... Como o meu roteador queimou, agora apenas 1 pc tem Internet aqui em casa.. E fica complicado eu escrever coisas pois meus irmãos também querem entrar na net..

Já tem um tempo que fiz esse programa, e foi a ultima coisa q eu fiz... Estou tentando pensar em uma lógica que consegue juntar os cenários e os objetos. Mais esta difícil =/...

Bom... A minha ideia de TileMap é o seguinte: Existe um conjunto de tiles (que pode esta em uma imagem ou separados) e um arquivo com os dados de onde deve posicionar os tiles.

Para fazer o arquivo que contem os dados onde cada Tiles vão ficar...  Eu usei o programa Tiled



E exporto para o formato .txt. O que sai um arquivo assim:


 [header]  
 width=10  
 height=7  
 tilewidth=64  
 tileheight=64  
 [tilesets]  
 tileset=../workspace/TilesMap/BLOCOS.png,64,64,0,0  
 tileset=../workspace/TilesMap/pipes.png,64,64,0,0  
 tileset=../workspace/TilesMap/Terreno.png,64,64,0,0  
 [layer]  
 type=Camada de Tiles 1  
 data=  
 1,0,0,2,0,0,107,108,0,0,  
 1,0,2,2,0,0,107,108,1,1,  
 1,0,0,2,0,0,113,114,1,1,  
 1,0,2,2,2,0,0,0,1,1,  
 193,194,194,194,194,195,97,98,1,1,  
 199,200,200,200,200,201,103,104,1,1,  
 199,200,200,200,200,201,103,104,1,1  

Modifiquei um pouco (na verdade muito) para facilitar minha vida...


 10 7 64  
 1 0 0 2 0 0 107 108 0 0   
 1 0 2 2 0 0 107 108 1 1   
 1 0 0 2 0 0 113 114 1 1   
 1 0 2 2 2 0 0 0 1 1   
 193 194 194 194 194 195 97 98 1 1   
 199 200 200 200 200 201 103 104 1 1   
 199 200 200 200 200 201 103 104 1 1  

Bom os 2 primeiros números representam o numero de tiles horizontais e verticais.  O terceiro numero representa o tamanhos dos tiles (é so um pq eu definir que os tiles serão todos quadrados), e na sequencia estão os dados do mapa.

Uma duvida natural seria: Como existe mais de um tileset (é esse o termo?), qual seria a ordem dos números? A Resposta é bem simples, é a ordem que eu add os tileset no Tiled. No caso do nosso exemplo a ordem foi: BLOCOS, pipes, Terreno. Essa ordem é muito importante...  Por isso que essa ordem foi mantido ao abrir os arquivos da imagem no programa.


 add_tileset(mapa, "BLOCOS.png", 0);
 add_tileset(mapa, "pipes.png", 1);
 add_tileset(mapa, "Terreno.png", 2);

Outro detalhe que padronizei é que cada tileset tera dimensão 384 x 1024 (para tiles de tamanho de dimensão 64x64)... Com base nisso podemos fazer um simples calculo para calcular o numeros de tiles que tem em um tileset... (384/64) * (1024/64) = 96... Guarde esse numero pois ele vai aparecer no codigo =P



Mais uma coisa vou usar congruência modular e o Tiled usa 0 para definir espaço vazio, vou diminuir 1 unidade desses valores... E usar -1 para espaço vazio... Isso vai facilitar e muito a logica do código... Sem mais enrolacao o codigo pode ser baixado aqui:



(o arquivo level1.txt é diferente do exemplo mostrado)





main.c:
#include "mapa.h"
int main()
{
 tipo_allegro5 DATA;


 //Inicializa o Allegro e cria uma janela 640 x 480
 tipo_mapa mapa;
 allegro_inicializa(&DATA, 640, 480);
 load_mapa(&mapa, "level1.txt");
        
        desenha_level(&mapa,0,0);
        al_flip_display();

 al_rest(3);
 return 0;
}



mapa.h:
#ifndef MAPA_H_
#define MAPA_H_

#include "allegro5.h"
#define TOTAL_TILESET 3

typedef struct tipo_tilemapa
{
 int *mapa;
 int tamanho_tiles;
 int num_tiles_vert;
 int num_tiles_horizontal;

} tipo_tilemapa;

typedef struct tipo_mapa
{
 ALLEGRO_BITMAP *tileset[TOTAL_TILESET];
 tipo_tilemapa camada_principal;

} tipo_mapa;

//Carrega um mapa
void load_mapa(tipo_mapa *mapa, char endereco[100]);

//Desenha o mapa na tela
void desenha_level(tipo_mapa *mapa, int x, int y);

void add_tileset (tipo_mapa *mapa, char endereco[100], int id);

#endif /* MAPA_H_ */



mapa.c
#include "mapa.h"

void load_mapa(tipo_mapa *mapa, char endereco[100])
{
 int num_tiles_vert;
 int num_tiles_horizontal;
 int tiles_tamanho;
 int i, j;
 FILE *level;
 int valor;

 add_tileset(mapa, "BLOCOS.png", 0);
 add_tileset(mapa, "pipes.png", 1);
 add_tileset(mapa, "Terreno.png", 2);

 //Abri o arquivo com o mapa
 level = fopen(endereco, "r");



 //Ler o tamanho do tilemap
 fscanf(level, "%i %i", &num_tiles_horizontal, &num_tiles_vert);
 mapa->camada_principal.num_tiles_horizontal = num_tiles_horizontal;
 mapa->camada_principal.num_tiles_vert = num_tiles_vert;


 //Ler o tamanho dos tiles
 fscanf(level,"%i", &tiles_tamanho);
 mapa->camada_principal.tamanho_tiles = tiles_tamanho;

 //Aloca memoria para o mapa
 mapa->camada_principal.mapa = (int *) malloc (sizeof(int) * num_tiles_vert * num_tiles_horizontal);

 //Ler os dados do mapa
 for(i = 0; i < num_tiles_vert; i++)
 {
  for(j = 0; j < num_tiles_horizontal; j++)
  {
   fscanf(level, "%i", &valor);
   valor--;
   mapa->camada_principal.mapa[i * num_tiles_horizontal + j] = valor;
  }
 }

 //Fecha o arquivo com o level
 fclose(level);

}

//Desenha o mapa na tela
void desenha_level(tipo_mapa *mapa, int x, int y)
{
 int i, j;

 int num_vert = mapa->camada_principal.num_tiles_vert;
 int num_horiz = mapa->camada_principal.num_tiles_horizontal;
 int * MAPA = mapa->camada_principal.mapa;
 int valor;
 for(i = 0; i < num_vert; i++)
 {
  for(j = 0; j < num_horiz; j++)
  {
   //Por padrão todos os tileset terão 96 tiles distribuido
   //em 6 colunas e 16 linhas. todos os tiles Serão quadrados 64x64

   valor = MAPA[i * num_horiz + j];
   printf("%i ", valor);

   if(valor < 0) continue;
   al_draw_bitmap_region(mapa->tileset[valor/96],64 * ((valor%96)%6) , 64 * ((valor%96)/6), 64, 64, j * 64 + x, i * 64 + y, 0);

  }
 }
}


void add_tileset (tipo_mapa *mapa, char endereco[100], int id)
{

 mapa->tileset[id] = al_load_bitmap(endereco);
 if(!(mapa->tileset[id]))
 {
  fprintf(stderr, "Falha ao carregar a imagem %s\n", endereco);
  exit(-1);
 }
}


 
 
É apenas uma ideia e tem muita coisa ainda para melhorar...

Allegro5.h

Finalmente  (ate parece que foi muito tempo)... Vou mostrar o código da versão 1.04...
A arte de programação em geral tem que ser algo planejado... Principalmente a programação de jogos sejam ele 2D e 3D... Mas como eu não sigo essa filosofia eu so sento no pc e vou escrevendo linhas de codigo e vejo no que vai dar XD

Antes de mostra o código... que não viu a postagem Allegro5.h veja pois o código de muitas funções que vou usar estão lá.

Para fazer o download do código (o que eu recomendo):

DOWNLOAD



estrutuas.h:
#include <stdio.h>
// Inclui o cabeçalho da bibilioteca Allegro 5
#include "allegro5.h"
//Definicoes
#define MAX_CARROS 4

//------------------------Carro inimigo--------------------------------
typedef struct tipo_carro_inimigo
{
 ALLEGRO_BITMAP *imagem;
 short ativo;
 int x;
 int y;
 int dir; // 0 - parado, 1 - Esquerda(left),  2 - direita

} tipo_carro_inimigo;

//Carrega a imagem do carro
void carrega_carro_inimigo (tipo_carro_inimigo* carro_inimigo, char endereco[100]);

//Atualiza a posicao do carro
void atualiza_carro_inimigo (tipo_carro_inimigo* carro_inimigo, int velocidade);

//Desenha o carro na tela
void desenha_carro_inimigo (tipo_carro_inimigo* carro_inimigo);

//Verifica se o carro esta ativo
int status_carro_inimigo  (tipo_carro_inimigo* carro_inimigo);

//Adiciona um carro no "jogo"
void add_carro_inimigo (tipo_carro_inimigo* carro_inimigo);

//Desativa um carro
void des_carro_inimigo (tipo_carro_inimigo* carro_inimigo);


//-------------------------bandeira---------------------------------

typedef struct tipo_bandeira
{
 ALLEGRO_BITMAP *imagem;
 int x;
 int y;

} tipo_bandeira;

//Carrega a imagem da bandeira
void carrega_bandeira(tipo_bandeira *bandeira, char endereco[100]);

//Atualiza a posicao da bandeira
void atualiza_bandeira(tipo_bandeira *bandeira, int velocidade);

//Desenha bandeira
void desenha_bandeira(tipo_bandeira *bandeira);

//Volta a bandeira para sua posição "inicial"
void reset_posicao_inical_bandeira(tipo_bandeira *bandeira);

//-------------------------jogador---------------------------------
typedef struct tipo_jogador
{
 ALLEGRO_BITMAP *imagem;
 int x;
 int y;

} tipo_jogador;

//Carrega a imagem do jogador
void carrega_jogador(tipo_jogador *jogador, char endereco[100]);

//Atualiza a posicao do jogador
void atualiza_jogador(tipo_jogador *jogador, tipo_allegro5 *DATA);
//Desenha o jogador na tela
void desenha_jogador(tipo_jogador *jogador);
//verifica se o jogador colidiu com algum carro
int colicao_jogador_carro_inimigo (tipo_jogador *jogador, tipo_carro_inimigo* carro_inimigo);
//verifica se o jogador colidiu com a bandeira
int colicao_jogador_bandeira (tipo_jogador *jogador, tipo_bandeira *bandeira);

//Volta o jogador para sua posição "inicial"
void reset_posicao_inical_jogador(tipo_jogador *jogador);
estrutuas.c:
#include "estruturas.h"

void carrega_carro_inimigo (tipo_carro_inimigo* carro_inimigo, char endereco[100])
{
 //Carrega a imagem do carro
 carro_inimigo->imagem = al_load_bitmap(endereco);
 if(!(carro_inimigo->imagem))
 {
  fprintf(stderr, "Falha ao carregar a imagem %sn", endereco);
  exit(-1);
 }

 carro_inimigo->ativo = 0;
}

void atualiza_carro_inimigo (tipo_carro_inimigo* carro_inimigo, int velocidade)
{
 //O movimento do carros são aleatorios mais se eles estão se movimentando em uma dada direcao
 //a probabilidade deles continuar nelas é maior

 int numero_rand = rand()%20;
 carro_inimigo->y += velocidade;

 if(carro_inimigo->dir == 0) //O carro não esta com um movimento inclinado
 {
  if(numero_rand < 17) //O carro continua sem um movimento inclinado
  {
   return;
  }
  else if(numero_rand < 19)
  {
   carro_inimigo->dir = 1;
  }
  else
  {
   carro_inimigo->dir = 2;
  }
 }
 else // O carro esta se movimentando para uma direcao
 {
  if (numero_rand < 5) // O carro fica "parado"
  {
   carro_inimigo->dir = 0;
   return;
  }
  else if (numero_rand == 20) // O carro muda de direcao
  {
   if (carro_inimigo->dir == 1)
   {
    carro_inimigo->dir = 2;
   }
   else
   {
    carro_inimigo->dir = 1;
   }
  }
 }

 //Movimenta o carro
 if(carro_inimigo->dir == 1)
 {
  carro_inimigo->x -= velocidade;
  if(carro_inimigo->x < 160) //Limite da pista
  {
   carro_inimigo->x = 160;
   carro_inimigo->dir = 2; //Muda a direcao
  }
 }
 else
 {
  carro_inimigo->x += velocidade;
  if(carro_inimigo->x > 440) //Limite da pista
  {
   carro_inimigo->x = 440;
   carro_inimigo->dir = 1; //Muda a direcao
  }
 }

}

//Desenha o carro na tela
void desenha_carro_inimigo (tipo_carro_inimigo* carro_inimigo)
{
 al_draw_bitmap(carro_inimigo->imagem,  carro_inimigo->x, carro_inimigo->y, 0);
}

void carrega_jogador(tipo_jogador *jogador, char endereco[100])
{
 //Carrega a imagem
 jogador->imagem = al_load_bitmap(endereco);
 if(!(jogador->imagem))
 {
  fprintf(stderr, "Falha ao carregar a imagem %sn", endereco);
  exit(-1);
 }

 //Coloca a posição inicial do jogador
 jogador->x = 208;
 jogador->y = 400;
}


//Verifica se o carro esta ativo
int status_carro_inimigo  (tipo_carro_inimigo* carro_inimigo)
{
 return carro_inimigo->ativo;
}


//Adiciona um carro no "jogo"
void add_carro_inimigo (tipo_carro_inimigo* carro_inimigo)
{

 carro_inimigo->y = -60;
 carro_inimigo->x = rand()%280 + 160;
 carro_inimigo->ativo = 1;
 carro_inimigo->dir = rand()%3; //Direcao inicial aleatoria
}

void des_carro_inimigo (tipo_carro_inimigo* carro_inimigo)
{
 carro_inimigo->ativo = 0;
}

void atualiza_jogador(tipo_jogador *jogador, tipo_allegro5 *DATA)
{
 allegro_atualiza_teclado_estatus (DATA);

 if (allegro_tecla(DATA, ALLEGRO_KEY_UP))
 {
        if(jogador->y - 8 > 0)
        {
         jogador->y -= 8;
        }
        else
        {
         jogador->y = 0;
        }
 }
 if (allegro_tecla(DATA, ALLEGRO_KEY_DOWN))
 {
        if(jogador->y + 8 < 416)
        {
         jogador->y += 8;
        }
        else
        {
         jogador->y = 416;
        }
 }
 if (allegro_tecla(DATA, ALLEGRO_KEY_LEFT))
 {
        if(jogador->x - 8 > 160)
        {
         jogador->x -= 8;
        }
        else
        {
         jogador->x = 160;
        }
 }
 if (allegro_tecla(DATA, ALLEGRO_KEY_RIGHT))
 {
        if(jogador->x + 8 <  440)
        {
         jogador->x += 8;
        }
        else
        {
         jogador->x = 440;
        }
 }


}

void desenha_jogador(tipo_jogador *jogador)
{
 al_draw_bitmap(jogador->imagem, jogador->x, jogador->y, 0);
}

//verifica se o jogador colidiu com algum carro
int colicao_jogador_carro_inimigo (tipo_jogador *jogador, tipo_carro_inimigo* carro_inimigo)
{
 if(jogador->x >= carro_inimigo->x + 40)
 {
  return 0;
 }
 if (jogador->x + 40 <= carro_inimigo->x)
 {
  return 0;
 }
 if(jogador->y >= carro_inimigo->y + 64)
 {
  return 0;
 }
 if (jogador->y + 64 <= carro_inimigo->y)
 {
  return 0;
 }
 return 1;

}

int colicao_jogador_bandeira (tipo_jogador *jogador, tipo_bandeira *bandeira)
{
 if(jogador->x >= bandeira->x + 32)
 {
  return 0;
 }
 if (jogador->x + 40 <= bandeira->x)
 {
  return 0;
 }
 if(jogador->y >= bandeira->y + 32)
 {
  return 0;
 }
 if (jogador->y + 40 <= bandeira->y)
 {
  return 0;
 }

 bandeira->y = -60;
 bandeira->x = rand()%280 + 160;

 return 1;
}

//Carrega a imagem da bandeira
void carrega_bandeira(tipo_bandeira *bandeira, char endereco[100])
{
 bandeira->imagem = al_load_bitmap(endereco);
 if(!(bandeira->imagem))
 {
  fprintf(stderr, "Falha ao carregar a imagem %sn", endereco);
  exit(-1);
 }
 bandeira->y = -60;
 bandeira->x = rand()%280 + 160;
}

//Atualiza a posicao da bandeira
void atualiza_bandeira(tipo_bandeira *bandeira, int velocidade)
{
 bandeira->y += velocidade;

 if(bandeira->y > 480)
 {
  bandeira->y = -60;
  bandeira->x = rand()%280 + 160;
 }
}

void desenha_bandeira(tipo_bandeira *bandeira)
{
 al_draw_bitmap(bandeira->imagem, bandeira->x, bandeira->y, 0);
}


void reset_posicao_inical_bandeira(tipo_bandeira *bandeira)
{
 bandeira->y = -60;
 bandeira->x = rand()%280 + 160;
}

//Volta o jogador para sua posição "inicial"
void reset_posicao_inical_jogador(tipo_jogador *jogador)
{
 //Coloca a posição inicial do jogador
 jogador->x = 208;
 jogador->y = 400;
}

main.c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

//Estruturas usasdas no jogo
#include "estruturas.h"


//Principal funcao do jogo
void jogo_main (tipo_allegro5 *DATA);
int jogo_menu(tipo_allegro5 *DARA,  int recorde);

int main ()
{
 //Cria as estruturas usadas no Allegro 5
 tipo_allegro5 DATA;

 //Inicializa o Allegro
 //Janela de 640 x 480

 allegro_inicializa (&DATA, 640, 480);

 //Carrega a musica ARPE.ogg
 allegro_add_musica(&DATA, 0, "ARPE.ogg");

 //Carrega sample
 allegro_add_sample(&DATA, 0, "Bip.wav");

 //Carrega a fonte adinekir.ttf
 allegro_add_fonte(&DATA, 0, "Ubuntu-L.ttf", 24);

 //Gera uma chave aleatoria;
 srand(time(NULL));

 //Titulo da Janela
 allegro_titulo_janela (&DATA, "Carros 1.04");


 //Inicia o jogo
 jogo_main(&DATA);

 return 0;
}

void jogo_main (tipo_allegro5 *DATA)
{
 char texto[100];
 int velocidade;
 int pontuacao;
 int nivel;
 int recorde = 0;
 int distancia;
 int i;
 int indicie_carro;
 int menu = 0;
 const int CARRO_MAX = 5; //Numero maximo de carro
 ALLEGRO_EVENT evento;

 tipo_jogador jogador;
 tipo_carro_inimigo carro_inimigo[CARRO_MAX];
 tipo_bandeira bandeira;

 //inicia o jogador
 carrega_jogador(&jogador, "jogador.png");

 //Carrega inimigos
 for(i = 0; i < CARRO_MAX; i++)
 {
  carrega_carro_inimigo(&carro_inimigo[i], "inimigo.png");
 }

 //Carrega a bandeira
 carrega_bandeira(&bandeira, "bandeira.png");


    while(1)
 {
     //Configuracao inicial
  velocidade = 0;
  pontuacao = 0;
  nivel = 0;
  distancia = 0;
  indicie_carro = 0;
  menu = 0;

  //Desativa todos os carros do inimigos
  for(i = 0; i < CARRO_MAX; i++)
  {
   des_carro_inimigo(&carro_inimigo[i]);
  }

  //inicia o menu;
  if(!jogo_menu(DATA, recorde))
  {
   return;
  }

  //Toca a musica
  allegro_controle_musica(DATA,0,START);

  while(1)
  {
   while(allegro_novo_evento(DATA, &evento)) //Verifica se tem eventos
   {
    if (evento.type == ALLEGRO_EVENT_DISPLAY_CLOSE) //Fecha a janela
    {
     return;
    }
   }

   //Atualiza jogador
   atualiza_jogador(&jogador, DATA);

   //Adiciona carros
   if(distancia >= 150)
   {
    add_carro_inimigo(&carro_inimigo[indicie_carro]);
    indicie_carro++;
    indicie_carro %= CARRO_MAX;
    distancia = 0;
   }
   else
   {
    distancia += velocidade;
   }

   //Limpa a tela
   al_clear_to_color(al_map_rgb(0, 0, 0));

   //Desenha um retangulo
   al_draw_filled_rectangle(160, 0, 480, 480, al_map_rgb(125, 125, 125));

   //Pontos e nivel
   sprintf(texto, "Nivel: %i", nivel);
   allegro_escreve_texto(DATA, 0, 10, 10, al_map_rgb(255, 255, 255), texto);
   sprintf(texto, "pontuacao: %i", pontuacao);
   allegro_escreve_texto(DATA, 0, 10, 34, al_map_rgb(255, 255, 255), texto);

   //Desenha o jogador
   desenha_jogador(&jogador);

   //Atualiza os carros inimigos
   for(i = 0; i < CARRO_MAX; i++)
   {
    if(status_carro_inimigo(&carro_inimigo[i]))
    {
     atualiza_carro_inimigo(&carro_inimigo[i], velocidade);
     //Desenha o carro
     desenha_carro_inimigo(&carro_inimigo[i]);
     if(colicao_jogador_carro_inimigo(&jogador, &carro_inimigo[i]))
     {
      allegro_controle_musica(DATA,0,STOP); //Para a musica
      reset_posicao_inical_jogador(&jogador);
      reset_posicao_inical_bandeira(&bandeira);
      menu = 1; //Volta para o menu inicial
     }
    }
   }
   if(menu) break; //Volta para o menu inicial

   //Atualiza a bandeira
   atualiza_bandeira(&bandeira, 2 * velocidade);
   desenha_bandeira(&bandeira);

   if(colicao_jogador_bandeira(&jogador, &bandeira))
   {
    allegro_start_sample(DATA, 0);
    pontuacao++;
   }



    nivel = pontuacao/5;
    velocidade = nivel + 4;


   //Atualiza a tela
   al_flip_display();
   al_rest(0.06);

  }
  //Muda o record
  if(recorde < pontuacao)
  {
   recorde = pontuacao;
  }
 }

}

int jogo_menu(tipo_allegro5 *DATA,  int recorde)
{
 //Limpa a tela
 char texto[100];

 allegro_escreve_texto(DATA, 0, 220, 100, al_map_rgb(255, 255, 0), "Carros 1.04");
 allegro_escreve_texto(DATA, 0, 220, 124, al_map_rgb(255, 255, 255), "ENTER - Novo jogo");
 allegro_escreve_texto(DATA, 0, 220, 148, al_map_rgb(255, 255, 255), "ESC - sair");
 sprintf(texto,"Recorde: %i", recorde);
 allegro_escreve_texto(DATA, 0, 220, 172, al_map_rgb(255, 255, 255), texto);
 al_flip_display();
 ALLEGRO_EVENT evento;

 while(1) //Verifica se tem eventos
 {
  if(allegro_novo_evento(DATA, &evento))
  {

   if (evento.type == ALLEGRO_EVENT_DISPLAY_CLOSE) //Fecha a janela
   {
    return 0;
   }
   if(evento.keyboard.keycode == ALLEGRO_KEY_ESCAPE)
   {
    return 0;
   }
   if (evento.keyboard.keycode == ALLEGRO_KEY_ENTER)
   {
    return 1;
   }

  }
  al_rest(1/15);
 }
 return 0;
}
Como pode ser vistos no código houve algumas mudanças... Tudo relacionando a inicialização carregamento da biblioteca Allegro5 está sendo feito na funcao main.
Algumas variações:

Movimentos dos Carros Inimigos

Os carros inimigos continuam se movimentando aleatoriamente. Mas não é um movimento aleatório com pesos iguais. Agora o movimento tem um peso maior para ele continuar na direção que ele se encontra. Sendo assim a chance dele percorrer a pista toda é bem maior... Na versão 1.00 os Carros ficavam fazendo zig-zag  mais continuavam praticalmente no mesmo lugar

Mudança da distancia minima

A distancia mínima entre os carros inimigos foi algo que eu fiz na versão 1.00 mas não mencionei. A distancia mínima garante que não seja adicionado 2 carros... ao mesmo tempo, como nesse programa não estamos tratando da colisão entre carros inimigos isso ajuda. A distancia minima passou de 200 para 150... Aumentando assim na minha opinião a dificuldade.

Nivel e Pontos

Como vocês devem ter lido na outra postagem estava com uma dificuldade com relação ao aumento do nivel. Foi feito uma mudança bem simples...  O nível é definido da seguinte forma: nível = pontuacao/5... Algo bem simples neh XD

Jogo funcionando no Linux




Jogo funcionando no Linux

Vejam o vídeo:

terça-feira, 7 de outubro de 2014

Apresentação

Primeiramente boa noite.

Sempre quis aprender criação de jogos. E resolvi pegar fundo nas minhas ferias. Já tiver experiências com alguns "maker" para criação de jogos (rpg maker, game maker, ...). Mais o que realmente queria mesmo fazer é um jogo multi plataforma. Um código que compile tanto no WIN como no LINUX. Por isso escolhi a biblioteca Allegro 5 e a linguagem C.

E pq desse blog? Bom primeiramente, sou iniciante na área de criação de jogos e quero registrar o meu progresso. E segundo talvez ajude alguém.

Sei programar em C (ou deveria pois faço MATCOMP)... Não sou muito bom com ortografia, então se você procurar textos politicamente correto em relação a gramática e ortografia, creio que não vai encontrar nesse blog e já me desculpo adiantado.


segunda-feira, 6 de outubro de 2014

Buscando Conhecimento

Eu sou do tipo que acredita que se aprende a programar programando. Então resolvi buscar matéria sobre criação de jogos.. No google mesmo...

Achei 2 pdf legais: Introdução ao Desenvolvimento de Jogos em Java e PROGRAMAÇÃO DE JOGOS 2D USANDO O MRDX E FUNDAMENTOS DE JOGOS 3D 

O primeiro link como o título sugere da uma introdução a criação de jogos em Java. Vocês devem esta nesse momento se perguntando (ou não): "Mas você não ia programar em C?" a ideia desses pdf não é pegar o código em se (ou talvez seja) e sim pegar a essência e a ideia por de traz da criação de jogos. O segundo é uma trabalho acadêmico, o que mais me chamou atenção nele foi o MRDX que achei simplesmente foda.

Pesquisei sobre o MRDX, e cheguei no seguinte site (se der vou olhar todos os códigos disponível no site *-* ). Alias o primeiro jogo que dei o nome de  "Jogo de carro" (sem criatividade =/) eu me baseei em um exemplo feito com MRDX (ex1).

Como escrevi antes, se não escrevi escrevo agora, resolvi começar a pegar pesado no estudo de criação de jogos agora, mas eu já tinha pesquisado a respeito.. 2 sites que achei legal que ensinam um pouco sobre o uso da biblioteca Allegro: Rafael Toledo e Introdução à Programação em C com Jogos 2D

Bom vai ficar muito evidente que eu me baseei pesado nos exemplos do Rafael Toledo.

A imagem escolhida mostra um jogo feito com o MRDX.

Related Posts Plugin for WordPress, Blogger...