Programação de Jogos com SDL
Este é um tutorial 2 em 1, vamos programar passo a passo dois jogos. O primeiro jogo será um jogo de labirinto e o segundo um snake (jogo da cobrinha). Os jogos serão feitos usando linguagem C e a biblioteca SDL.
[ Hits: 25.716 ]
Por: Samuel Leonardo em 18/11/2013
#include <stdio.h> #include <stdlib.h> #include <SDL/SDL.h> /* Definicoes, para facilitar o uso da funcao para desenhar o mapa */ #define PAREDE 1 #define VOCE 2 /* não usado */ #define GRAMA 3 #define SAIDA 4 /* Desfinicoes da configuracao do Video */ #define LARGURA 800 /* Numero total de colunas*largura_da_parede */ #define ALTURA 200 /* Numero total de linhas*altura_da_parede */ #define BPP 0 /* A Flag SDL_ANYFORMAT se encaregara da resolucao */ SDL_Surface * tela, * piso, * parede, * player, * final, * grama; int coluna_atual = 1, linha_atual = 1, fim = 0; /* O Mapa */ int mapa[10][40] = { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,3,3,3, 1,3,3,3,3,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,1,0,1,1,1,3,3,3, 1,3,1,3,3,1,1,1,0,1,1,1,1,1,1,1,1,0,0,1,1,1,0,1,1,1,1,1,1,1,1,0,1,0,0,0,0,1,0,1, 1,3,3,1,3,3,3,3,0,1,1,0,0,0,0,0,0,1,1,1,1,1,0,1,3,3,1,1,1,1,1,0,1,1,1,1,0,1,0,1, 1,3,3,1,3,3,3,3,0,1,1,0,1,1,1,1,1,1,1,1,1,1,0,1,3,3,0,0,0,1,1,0,1,1,1,1,0,1,0,1, 1,3,3,3,3,1,3,3,0,1,1,0,1,1,1,1,1,1,0,1,1,1,0,1,3,3,1,1,0,1,1,0,0,0,0,0,0,1,0,1, 1,3,3,3,3,3,3,3,0,0,0,0,1,1,1,1,1,0,1,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,0,1, 1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,0,1,1,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1, 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,4,1,1,1,1,1,1,1,1,1,1,1 }; /*==========================FUNCOES==========================*/ /* Funcao que controla o fps */ void controla_fps ( int tempo_inicial ) { int fps = 1000/60; // converte 60 FPS para milissegundos int tempo_agora = SDL_GetTicks() - tempo_inicial; if(tempo_agora < fps) SDL_Delay(fps - tempo_agora); } /* Funcao de inicializacao */ int carrega_imagens ( ) { /* Carrega as Imagens */ parede = SDL_LoadBMP("parede_muro.bmp"); if (parede == NULL) { printf("Não carregou parede_muro.bmp\n"); return 0; } player = SDL_LoadBMP("gamer.bmp"); if (player == NULL) { printf("Não carregou gamer.bmp\n"); return 0; } final = SDL_LoadBMP("fim.bmp"); if (final == NULL) { printf("Não carregou fim.bmp\n"); return 0; } grama = SDL_LoadBMP("gramado.bmp"); if (grama == NULL) { printf("Não carregou gramado.bmp\n"); return 0; } return 1; } /* Funcao para desenhar o Mapa */ void desenha_mapa ( ) { SDL_Rect destino; int linha, coluna; for (linha = 0; linha < 10; linha++) { destino.y = linha * 20; for (coluna = 0; coluna < 40; coluna++) { destino.x = coluna * 20; if (mapa[linha][coluna] == PAREDE) { /* pegue a imagem parede completa(NULL) e jogue na tela em destino */ SDL_BlitSurface(parede, NULL, tela, &destino); } else if (mapa[linha][coluna] == GRAMA) { /* pegue a imagem grama completa(NULL) e jogue na tela em destino */ SDL_BlitSurface(grama, NULL, tela, &destino); } else if (mapa[linha][coluna] == SAIDA) { /* pegue a imagem final completa(NULL) e jogue na tela em destino */ SDL_BlitSurface(final, NULL, tela, &destino); } } } } void move_jogador ( SDL_Event event ) { /*=============== Deslocamento do jogador =====================*/ switch (event.key.keysym.sym) { /* Na vertical */ case SDLK_UP: /* Se o usuario aperta a seta para cima e linha_atual for maior que 0 ... */ if (linha_atual > 0) /* 0 = primeira linha */ { /* ...subtraia 1 de linha_atual, ou seja, suba uma linha... */ linha_atual = linha_atual - 1; /* ... e verifique a localizacao do jogador ...*/ if (mapa[linha_atual][coluna_atual] == PAREDE) linha_atual = linha_atual + 1; /* ... Se for sobre a PAREDE volte para a posição anterior. */ } break; case SDLK_DOWN: if (linha_atual < 9) { linha_atual = linha_atual + 1; if (mapa[linha_atual][coluna_atual] == PAREDE) linha_atual = linha_atual - 1; } break; /* Na horizontal */ case SDLK_LEFT: /* Se o usuario aperta a seta para esquerda e coluna_atual for maior que 0 ... */ if (coluna_atual > 0) /* 0 = primeira coluna */ { /* ...subtraia 1 de coluna_atual, ou seja, recue uma coluna ... */ coluna_atual = coluna_atual - 1; /* ... e verifique a localizacao do jogador ...*/ if (mapa[linha_atual][coluna_atual] == PAREDE) coluna_atual = coluna_atual + 1; /* ... Se for sobre a PAREDE adicione 1 a coluna_atual. */ } break; case SDLK_RIGHT: if (coluna_atual < 39)/* 39 = última coluna */ { coluna_atual = coluna_atual + 1; if (mapa[linha_atual][coluna_atual] == PAREDE) coluna_atual = coluna_atual - 1; } break; default: break; } } int main ( ) { /*inicializando a SDL e verificando possiveis erros */ if(SDL_Init(SDL_INIT_VIDEO) != 0) { printf("Erro: %s\n", SDL_GetError()); exit(-1); } SDL_Rect destino; /* para blitar o jogador */ SDL_Event evento; /* para os eventos */ /* Carrega as imagens */ if (carrega_imagens() == 0) /* Se não carregou uma ou outra imagem */ { return 1; /* encerre o programa */ } /* Configura o Video */ tela = SDL_SetVideoMode(LARGURA, ALTURA, BPP, SDL_SWSURFACE | SDL_ANYFORMAT); if(tela == NULL) { printf("Erro: %s\n", SDL_GetError()); return 1; /* encerre o programa */ } int tempo_inicial; /* Loop principal */ while (fim == 0) /* Enquanto NÃO for verdadeiro o fim */ { /* Para a funcao controla_fps */ tempo_inicial = SDL_GetTicks(); /* Loop de eventos */ while(SDL_PollEvent(&evento)) { if(evento.type == SDL_QUIT) fim = 1; /* move o jogador */ if (evento.type == SDL_KEYDOWN) move_jogador(evento); } /* Verifica se o jogador chegou ao ponto final */ if (mapa[linha_atual][coluna_atual] == SAIDA) { printf("Chegou ao ponto final\n"); } /* Pinta a tela inteira de branco antes de desenhar o mapa, esse branco eh o caminho */ SDL_FillRect(tela, NULL, SDL_MapRGB(tela->format, 255, 255, 255)); /* Desenha o mapa sobre a tela */ desenha_mapa(); /* blita o jogador na tela */ /* para o jogador: destino.x = coluna_atual*largura_da_imagem e destino.y = linha_atual*altura_da_imagem */ destino.x = coluna_atual * 20; destino.y = linha_atual * 20; /* pegue a imagem player completa(NULL) e jogue na tela em destino */ SDL_BlitSurface(player, NULL, tela, &destino); SDL_UpdateRect(tela,0,0,0,0); /* Atualiza a tela inteira */ controla_fps(tempo_inicial); // controla o FPS } /* Finalizando o SDL */ SDL_Quit(); return 0; }
/* Funcao de inicializacao */ int carrega_imagens ( ) { /* Carrega as Imagens */ parede = SDL_LoadBMP("parede_muro.bmp"); if (parede == NULL) { printf("Não carregou parede_muro.bmp\n"); return 0; } player = SDL_LoadBMP("gamer.bmp"); if (player == NULL) { printf("Não carregou gamer.bmp\n"); return 0; } final = SDL_LoadBMP("fim.bmp"); if (final == NULL) { printf("Não carregou fim.bmp\n"); return 0; } grama = SDL_LoadBMP("gramado.bmp"); if (grama == NULL) { printf("Não carregou gramado.bmp\n"); return 0; } return 1; }
/* Funcao para desenhar o Mapa */ void desenha_mapa ( ) { SDL_Rect destino; int linha, coluna; for (linha = 0; linha < 10; linha++) { destino.y = linha * 20; for (coluna = 0; coluna < 40; coluna++) { destino.x = coluna * 20; if (mapa[linha][coluna] == PAREDE) { /* pegue a imagem parede completa(NULL) e jogue na tela em destino */ SDL_BlitSurface(parede, NULL, tela, &destino); } else if (mapa[linha][coluna] == GRAMA) { /* pegue a imagem grama completa(NULL) e jogue na tela em destino */ SDL_BlitSurface(grama, NULL, tela, &destino); } else if (mapa[linha][coluna] == SAIDA) { /* pegue a imagem final completa(NULL) e jogue na tela em destino */ SDL_BlitSurface(final, NULL, tela, &destino); } } } }
void move_jogador ( SDL_Event event ) { /*=============== Deslocamento do jogador =====================*/ switch (event.key.keysym.sym) { /* Na vertical */ case SDLK_UP: /* Se o usuario aperta a seta para cima e linha_atual for maior que 0 ... */ if (linha_atual > 0) /* 0 = primeira linha */ { /* ...subtraia 1 de linha_atual, ou seja, suba uma linha... */ linha_atual = linha_atual - 1; /* ... e verifique a localizacao do jogador ...*/ if (mapa[linha_atual][coluna_atual] == PAREDE) linha_atual = linha_atual + 1; /* ... Se for sobre a PAREDE volte para a posição anterior. */ } break; case SDLK_DOWN: if (linha_atual < 9) { linha_atual = linha_atual + 1; if (mapa[linha_atual][coluna_atual] == PAREDE) linha_atual = linha_atual - 1; } break; /* Na horizontal */ case SDLK_LEFT: /* Se o usuario aperta a seta para esquerda e coluna_atual for maior que 0 ... */ if (coluna_atual > 0) /* 0 = primeira coluna */ { /* ...subtraia 1 de coluna_atual, ou seja, recue uma coluna ... */ coluna_atual = coluna_atual - 1; /* ... e verifique a localizacao do jogador ...*/ if (mapa[linha_atual][coluna_atual] == PAREDE) coluna_atual = coluna_atual + 1; /* ... Se for sobre a PAREDE adicione 1 a coluna_atual. */ } break; case SDLK_RIGHT: if (coluna_atual < 39)/* 39 = última coluna */ { coluna_atual = coluna_atual + 1; if (mapa[linha_atual][coluna_atual] == PAREDE) coluna_atual = coluna_atual - 1; } break; default: break; } }
/* Loop principal */ while (fim == 0) /* Enquanto NÃO for verdadeiro o fim */ { /* Para a funcao controla_fps */ tempo_inicial = SDL_GetTicks(); /* Loop de eventos */ while(SDL_PollEvent(&evento)) { if(evento.type == SDL_QUIT) fim = 1; /* move o jogador */ if (evento.type == SDL_KEYDOWN) move_jogador(evento); } /* Verifica se o jogador chegou ao ponto final */ if (mapa[linha_atual][coluna_atual] == SAIDA) { printf("Chegou ao ponto final\n"); } /* Pinta a tela inteira de branco antes de desenhar o mapa, esse branco eh o caminho */ SDL_FillRect(tela, NULL, SDL_MapRGB(tela->format, 255, 255, 255)); /* Desenha o mapa sobre a tela */ desenha_mapa(); /* blita o jogador na tela */ /* para o jogador: destino.x = coluna_atual*largura_da_imagem e destino.y = linha_atual*altura_da_imagem */ destino.x = coluna_atual * 20; destino.y = linha_atual * 20; /* pegue a imagem player completa(NULL) e jogue na tela em destino */ SDL_BlitSurface(player, NULL, tela, &destino); SDL_UpdateRect(tela,0,0,0,0); /* Atualiza a tela inteira */ controla_fps(tempo_inicial); // controla o FPS }
Dicas para aprender programação
Desenhando fácil um pinguim no Inkscape
Algoritmo Antissocial - Recuperando o Controle da sua Mente
SDL - Ótimo para criação de jogos
Tratamento de exceções na linguagem C
SDL e C - Uma dupla sensacional
Android NDK: Desmistificando o acesso a códigos nativos em C
lib cURL - Trabalhe com URLs em C
Enviar mensagem ao usuário trabalhando com as opções do php.ini
Meu Fork do Plugin de Integração do CVS para o KDevelop
Compartilhando a tela do Computador no Celular via Deskreen
Como Configurar um Túnel SSH Reverso para Acessar Sua Máquina Local a Partir de uma Máquina Remota
Configuração para desligamento automatizado de Computadores em um Ambiente Comercial
Criando uma VPC na AWS via CLI
Multifuncional HP imprime mas não digitaliza
Dica básica para escrever um Artigo.
Como Exibir Imagens Aleatórias no Neofetch para Personalizar seu Terminal