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.715 ]
Por: Samuel Leonardo em 18/11/2013
#include <stdio.h> #include <stdlib.h> #include <time.h> #include <SDL/SDL.h> /* direções da cobra */ #define CIMA 0 #define DIREITA 1 #define BAIXO 2 #define ESQUERDA 3 #define TAMANHOIMAGEM 32 struct Pedaco { int coorX; int coorY; int direcao; // direção } pedaco[256], maca; // pedaco[0] = ponta do rabo E pedaco[tamanho - 1] = cabeça /* Imagens e tela principal */ SDL_Surface *tela, *img_maca, *img_snakes, *img_cabeca; int seta_cima = 0, seta_baixo = 0, seta_esquerda = 0, seta_direita = 0; int colisao = 0; // identifica colisao da cabeça com outras partes do corpo // tamanho = tamanho atual da cobra int tamanho = 5, tamanho_anterior = 5; int velX = 0, velY = 0; // para mover a cobra int mapa_largura = 25, mapa_altura = 20; // dimensões do mapa char hud[256]; // informações passadas ao usuario /* Funcao que controla o fps */ void controla_fps ( int tempo_inicial ) { int fps = 1000/7; // converte 7 FPS para milissegundos int tempo_agora = SDL_GetTicks() - tempo_inicial; if(tempo_agora < fps) SDL_Delay(fps - tempo_agora); } int carrega_imagens ( ) { img_maca = SDL_LoadBMP("apple.bmp"); if (img_maca == NULL) { printf("Não carregou apple.bmp\n"); return 0; } img_snakes = SDL_LoadBMP("piece.bmp"); if (img_snakes == NULL) { printf("Não carregou piece.bmp\n"); return 0; } img_cabeca = SDL_LoadBMP("head.bmp"); if (img_cabeca == NULL) { printf("Não carregou head.bmp\n"); return 0; } return 1; } void posiciona_maca ( ) { int i; int repetir; do { // escolhe aleatoriamente as coordenadas maca.coorX = rand() % mapa_largura; maca.coorY = rand() % mapa_altura; repetir = 0; for (i = 0; i < tamanho; i++) { // verifica em todas as peças se as coordenadas delas // são iguais as novas coordenadas da maçã. if ((pedaco[i].coorX == maca.coorX) && (pedaco[i].coorY == maca.coorY)) { // Se forem iguais então pare o loop e // repita o procedimento para escolher outra coordenada para a maçã. repetir = 1; break; } } // enquanto for para repetir continue escolhendo outra coordenada para a maçã. } while (repetir); } void inicia_jogo ( ) { tamanho_anterior = tamanho; // para o hud //Reinicie o jogo tamanho = 5; colisao = 0; velX = 0; velY = 0; // reinicializando as peças // inicializando a parte A - a cabeça pedaco[4].coorX = 5; pedaco[4].coorY = 3; pedaco[4].direcao = DIREITA; // inicializando a parte B pedaco[3].coorX = 4; pedaco[3].coorY = 3; pedaco[3].direcao = DIREITA; // inicializando a parte C pedaco[2].coorX = 3; pedaco[2].coorY = 3; pedaco[2].direcao = DIREITA; // inicializando a parte D pedaco[1].coorX = 2; pedaco[1].coorY = 3; pedaco[1].direcao = DIREITA; // inicializando a parte E - o rabo pedaco[0].coorX = 1; pedaco[0].coorY = 3; pedaco[0].direcao = DIREITA; // inicializando as coordenadas da maçã. posiciona_maca(); } void controla_snake ( SDL_Event evento ) { if (evento.type == SDL_KEYDOWN) { switch (evento.key.keysym.sym) { case SDLK_RIGHT: seta_direita = 1; break; case SDLK_LEFT: seta_esquerda = 1; break; case SDLK_UP: seta_cima = 1; break; case SDLK_DOWN: seta_baixo = 1; break; case SDLK_p: velX = 0; velY = 0; break; default: break; } } else if (evento.type == SDL_KEYUP) { switch (evento.key.keysym.sym) { case SDLK_RIGHT: seta_direita = 0; break; case SDLK_LEFT: seta_esquerda = 0; break; case SDLK_UP: seta_cima = 0; break; case SDLK_DOWN: seta_baixo = 0; break; default: break; } } } void move_snake ( ) { if (seta_direita && pedaco[tamanho - 1].direcao != ESQUERDA) { velX = 1; // move horizontalmente a cabeça para direita velY = 0; // e para de mover verticalmente pedaco[tamanho - 1].direcao = DIREITA; } else if (seta_esquerda && pedaco[tamanho - 1].direcao != DIREITA) { velX = -1; // move horizontalmente a cabeça para esquerda velY = 0; // e para de mover verticalmente pedaco[tamanho - 1].direcao = ESQUERDA; } else if (seta_cima && pedaco[tamanho - 1].direcao != BAIXO) { velX = 0; // para de mover horizontalmente velY = -1; // e move verticalmente a cabeça pedaco[tamanho - 1].direcao = CIMA; } else if (seta_baixo && pedaco[tamanho - 1].direcao != CIMA) { velX = 0; // para de mover horizontalmente velY = 1; // e move verticalmente a cabeça pedaco[tamanho - 1].direcao = BAIXO; } // depois ajustando as posições das outras peças (partes) // primeiro move as partes do corpo if (velX || velY) // se estiver movendo { int i; for (i = 0; i < tamanho - 1; i++) { // faça a peça de trás (pedaco[i]) igual a peça da frente (pedaco[i + 1]) pedaco[i].coorX = pedaco[i + 1].coorX; pedaco[i].coorY = pedaco[i + 1].coorY; pedaco[i].direcao = pedaco[i + 1].direcao; } } // agora move a cabeça pedaco[tamanho - 1].coorX += velX; pedaco[tamanho - 1].coorY += velY; // Verifica os limites do movimento da cobra // Para o eixo X // se estiver além da largura da tela/mapa if (pedaco[tamanho - 1].coorX >= mapa_largura) { // volte para posição coorX = 0 pedaco[tamanho - 1].coorX = 0; } else if (pedaco[tamanho - 1].coorX < 0) // se estiver além de 0 { // volte para a posição da largura do mapa pedaco[tamanho - 1].coorX = mapa_largura - 1; } // Para o eixo Y if (pedaco[tamanho - 1].coorY >= mapa_altura) { pedaco[tamanho - 1].coorY = 0; } else if (pedaco[tamanho - 1].coorY < 0) { pedaco[tamanho - 1].coorY = mapa_altura - 1; } } void desenha_snake ( ) { int i; SDL_Rect destino; // blitando as img_macas das peças for (i = 0; i < tamanho - 1; i++) { destino.y = pedaco[i].coorY * TAMANHOIMAGEM; destino.x = pedaco[i].coorX * TAMANHOIMAGEM; SDL_BlitSurface(img_snakes, NULL, tela, &destino); } // blitando a cabeça destino.y = pedaco[tamanho - 1].coorY * TAMANHOIMAGEM; destino.x = pedaco[tamanho - 1].coorX * TAMANHOIMAGEM; SDL_BlitSurface(img_cabeca, NULL, tela, &destino); } int main (int argc, char **args) { if (SDL_Init(SDL_INIT_VIDEO) < 0) { printf("ERROR: %s\n", SDL_GetError()); SDL_Quit(); return 1; } SDL_Event evento; // controle do FPS Uint32 tempo_inicial; tela = SDL_SetVideoMode(mapa_largura * TAMANHOIMAGEM, mapa_altura * TAMANHOIMAGEM, 16, SDL_SWSURFACE); if (tela == NULL) { printf("ERROR: %s\n", SDL_GetError()); SDL_Quit(); return 1; } if (carrega_imagens() == 0) { printf("ERROR: %s\n", SDL_GetError()); SDL_Quit(); return 1; } // inicia o jogo inicia_jogo(); srand(time(NULL)); int i; int fim = 0; // variável de controle do loop principal while (!fim) { tempo_inicial = SDL_GetTicks(); sprintf(hud, "SNAKE by Sam L. - TAMANHO: ATUAL = %d | ANTERIOR = %d", tamanho, tamanho_anterior); SDL_WM_SetCaption(hud, NULL); while (SDL_PollEvent(&evento)) { if (evento.type == SDL_QUIT) { fim = 1; break; } controla_snake(evento); } // move a cobra move_snake(); // colisão com a maçã if ((pedaco[tamanho - 1].coorX == maca.coorX) && (pedaco[tamanho - 1].coorY == maca.coorY)) { tamanho++; pedaco[tamanho - 1].coorX = maca.coorX; pedaco[tamanho - 1].coorY = maca.coorY; pedaco[tamanho - 1].direcao = pedaco[tamanho - 2].direcao; // reinicializando a posição da maçã // escolhe uma posição diferente das peças da serpente posiciona_maca(); } /* Colisão só será atualizada no próximo loop, pois o usuário deve ver as peças sobrepostas */ if (colisao) { // reinicia o jogo e seta a variavel colisao para 0 inicia_jogo(); } /* Colisão entre cabeça e outras partes da cobra */ for (i = 0; i < tamanho - 2 && colisao == 0; i++) { if ((pedaco[tamanho - 1].coorX == pedaco[i].coorX) && (pedaco[tamanho - 1].coorY == pedaco[i].coorY)) colisao = 1; } // Blitagem // Pintando o tela de branco SDL_FillRect(tela, NULL, SDL_MapRGB(tela->format, 255, 255, 255)); SDL_Rect destino; destino.x = maca.coorX * TAMANHOIMAGEM; destino.y = maca.coorY * TAMANHOIMAGEM; SDL_BlitSurface(img_maca, NULL, tela, &destino); desenha_snake(); // atualizando a tela SDL_UpdateRect(tela, 0,0,0,0); controla_fps(tempo_inicial); } SDL_Quit(); // fecha o SDL return 0; }
/* Funcao que controla o fps */ void controla_fps ( int tempo_inicial ) { int fps = 1000/7; // converte 7 FPS para milissegundos int tempo_agora = SDL_GetTicks() - tempo_inicial; if(tempo_agora < fps) SDL_Delay(fps - tempo_agora); }
int carrega_imagens ( ) { img_maca = SDL_LoadBMP("apple.bmp"); if (img_maca == NULL) { printf("Não carregou apple.bmp\n"); return 0; } img_snakes = SDL_LoadBMP("piece.bmp"); if (img_snakes == NULL) { printf("Não carregou piece.bmp\n"); return 0; } img_cabeca = SDL_LoadBMP("head.bmp"); if (img_cabeca == NULL) { printf("Não carregou head.bmp\n"); return 0; } return 1; }
void posiciona_maca ( ) { int i; int repetir; do { // escolhe aleatoriamente as coordenadas maca.coorX = rand() % mapa_largura; maca.coorY = rand() % mapa_altura; repetir = 0; for (i = 0; i < tamanho; i++) { // verifica em todas as peças se as coordenadas delas // são iguais as novas coordenadas da maçã. if ((pedaco[i].coorX == maca.coorX) && (pedaco[i].coorY == maca.coorY)) { // Se forem iguais então pare o loop e // repita o procedimento para escolher outra coordenada para a maçã. repetir = 1; break; } } // enquanto for para repetir continue escolhendo outra coordenada para a maçã. } while (repetir); }
void controla_snake ( SDL_Event evento ) { if (evento.type == SDL_KEYDOWN) { switch (evento.key.keysym.sym) { case SDLK_RIGHT: seta_direita = 1; break; case SDLK_LEFT: seta_esquerda = 1; break; case SDLK_UP: seta_cima = 1; break; case SDLK_DOWN: seta_baixo = 1; break; case SDLK_p: velX = 0; velY = 0; break; default: break; } } else if (evento.type == SDL_KEYUP) { switch (evento.key.keysym.sym) { case SDLK_RIGHT: seta_direita = 0; break; case SDLK_LEFT: seta_esquerda = 0; break; case SDLK_UP: seta_cima = 0; break; case SDLK_DOWN: seta_baixo = 0; break; default: break; } } }
void move_snake ( ) { if (seta_direita && pedaco[tamanho - 1].direcao != ESQUERDA) { velX = 1; // move horizontalmente a cabeça para direita velY = 0; // e para de mover verticalmente pedaco[tamanho - 1].direcao = DIREITA; } else if (seta_esquerda && pedaco[tamanho - 1].direcao != DIREITA) { velX = -1; // move horizontalmente a cabeça para esquerda velY = 0; // e para de mover verticalmente pedaco[tamanho - 1].direcao = ESQUERDA; } else if (seta_cima && pedaco[tamanho - 1].direcao != BAIXO) { velX = 0; // para de mover horizontalmente velY = -1; // e move verticalmente a cabeça pedaco[tamanho - 1].direcao = CIMA; } else if (seta_baixo && pedaco[tamanho - 1].direcao != CIMA) { velX = 0; // para de mover horizontalmente velY = 1; // e move verticalmente a cabeça pedaco[tamanho - 1].direcao = BAIXO; } // depois ajustando as posições das outras peças (partes) // primeiro move as partes do corpo if (velX || velY) // se estiver movendo { int i; for (i = 0; i < tamanho - 1; i++) { // faça a peça de trás (pedaco[i]) igual a peça da frente (pedaco[i + 1]) pedaco[i].coorX = pedaco[i + 1].coorX; pedaco[i].coorY = pedaco[i + 1].coorY; pedaco[i].direcao = pedaco[i + 1].direcao; } } // agora move a cabeça pedaco[tamanho - 1].coorX += velX; pedaco[tamanho - 1].coorY += velY; // Verifica os limites do movimento da cobra // Para o eixo X // se estiver além da largura da tela/mapa if (pedaco[tamanho - 1].coorX >= mapa_largura) { // volte para posição coorX = 0 pedaco[tamanho - 1].coorX = 0; } else if (pedaco[tamanho - 1].coorX < 0) // se estiver além de 0 { // volte para a posição da largura do mapa pedaco[tamanho - 1].coorX = mapa_largura - 1; } // Para o eixo Y if (pedaco[tamanho - 1].coorY >= mapa_altura) { pedaco[tamanho - 1].coorY = 0; } else if (pedaco[tamanho - 1].coorY < 0) { pedaco[tamanho - 1].coorY = mapa_altura - 1; } }
if (seta_direita && pedaco[tamanho - 1].direcao != ESQUERDA) { velX = 1; // move horizontalmente a cabeça para direita velY = 0; // e para de mover verticalmente pedaco[tamanho - 1].direcao = DIREITA; } else if (seta_esquerda && pedaco[tamanho - 1].direcao != DIREITA) { velX = -1; // move horizontalmente a cabeça para esquerda velY = 0; // e para de mover verticalmente pedaco[tamanho - 1].direcao = ESQUERDA; } else if (seta_cima && pedaco[tamanho - 1].direcao != BAIXO) { velX = 0; // para de mover horizontalmente velY = -1; // e move verticalmente a cabeça pedaco[tamanho - 1].direcao = CIMA; } else if (seta_baixo && pedaco[tamanho - 1].direcao != CIMA) { velX = 0; // para de mover horizontalmente velY = 1; // e move verticalmente a cabeça pedaco[tamanho - 1].direcao = BAIXO; }
// Verifica os limites do movimento da cobra // Para o eixo X // se estiver além da largura da tela/mapa if (pedaco[tamanho - 1].coorX >= mapa_largura) { // volte para posição coorX = 0 pedaco[tamanho - 1].coorX = 0; } else if (pedaco[tamanho - 1].coorX < 0) // se estiver além de 0 { // volte para a posição da largura do mapa pedaco[tamanho - 1].coorX = mapa_largura - 1; }
void desenha_snake ( ) { int i; SDL_Rect destino; // blitando as img_macas das peças for (i = 0; i < tamanho - 1; i++) { destino.y = pedaco[i].coorY * TAMANHOIMAGEM; destino.x = pedaco[i].coorX * TAMANHOIMAGEM; SDL_BlitSurface(img_snakes, NULL, tela, &destino); } // blitando a cabeça destino.y = pedaco[tamanho - 1].coorY * TAMANHOIMAGEM; destino.x = pedaco[tamanho - 1].coorX * TAMANHOIMAGEM; SDL_BlitSurface(img_cabeca, NULL, tela, &destino); }
/*===== o loop principal =====*/ while (!fim) { tempo_inicial = SDL_GetTicks(); sprintf(hud, "SNAKE by Sam L. - TAMANHO: ATUAL = %d | ANTERIOR = %d", tamanho, tamanho_anterior); SDL_WM_SetCaption(hud, NULL); while (SDL_PollEvent(&evento)) { if (evento.type == SDL_QUIT) { fim = 1; break; } controla_snake(evento); } // move a cobra move_snake(); // colisão com a maçã if ((pedaco[tamanho - 1].coorX == maca.coorX) && (pedaco[tamanho - 1].coorY == maca.coorY)) { tamanho++; pedaco[tamanho - 1].coorX = maca.coorX; pedaco[tamanho - 1].coorY = maca.coorY; pedaco[tamanho - 1].direcao = pedaco[tamanho - 2].direcao; // reinicializando a posição da maçã // escolhe uma posição diferente das peças da serpente posiciona_maca(); } /* Colisão só será atualizada no próximo loop, pois o usuário deve ver as peças sobrepostas */ if (colisao) { // reinicia o jogo e seta a variavel colisao para 0 inicia_jogo(); } /* Colisão entre cabeça e outras partes da cobra */ for (i = 0; i < tamanho - 2 && colisao == 0; i++) { if ((pedaco[tamanho - 1].coorX == pedaco[i].coorX) && (pedaco[tamanho - 1].coorY == pedaco[i].coorY)) colisao = 1; } // Blitagem // Pintando o tela de branco SDL_FillRect(tela, NULL, SDL_MapRGB(tela->format, 255, 255, 255)); SDL_Rect destino; destino.x = maca.coorX * TAMANHOIMAGEM; destino.y = maca.coorY * TAMANHOIMAGEM; SDL_BlitSurface(img_maca, NULL, tela, &destino); desenha_snake(); // atualizando a tela SDL_UpdateRect(tela, 0,0,0,0); controla_fps(tempo_inicial); }
// colisão com a maçã if ((pedaco[tamanho - 1].coorX == maca.coorX) && (pedaco[tamanho - 1].coorY == maca.coorY)) { tamanho++; pedaco[tamanho - 1].coorX = maca.coorX; pedaco[tamanho - 1].coorY = maca.coorY; pedaco[tamanho - 1].direcao = pedaco[tamanho - 2].direcao; // reinicializando a posição da maçã // escolhe uma posição diferente das peças da serpente posiciona_maca(); }
/* Colisão só será atualizada no próximo loop, pois o usuário deve ver as peças sobrepostas */ if (colisao) { // reinicia o jogo e seta a variavel colisao para 0 inicia_jogo(); } /* Colisão entre cabeça e outras partes da cobra */ for (i = 0; i < tamanho - 2 && colisao == 0; i++) { if ((pedaco[tamanho - 1].coorX == pedaco[i].coorX) && (pedaco[tamanho - 1].coorY == pedaco[i].coorY)) colisao = 1; }
// Blitagem // Pintando o tela de branco SDL_FillRect(tela, NULL, SDL_MapRGB(tela->format, 255, 255, 255)); SDL_Rect destino; destino.x = maca.coorX * TAMANHOIMAGEM; destino.y = maca.coorY * TAMANHOIMAGEM; SDL_BlitSurface(img_maca, NULL, tela, &destino); desenha_snake(); // atualizando a tela SDL_UpdateRect(tela, 0,0,0,0); controla_fps(tempo_inicial);
Desenhando fácil um pinguim no Inkscape
Algoritmo Antissocial - Recuperando o Controle da sua Mente
Desenhando um avatar do Tux no InkScape
openCertiface: Biométrica Facial em nuvem baseada em software livre
Instalando Facebook Folly através do Conan
Desenvolvendo aplicativo para autenticação biométrica utilizando a Libfprint
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
Calculando casas de um numero flutuante em c++ [RESOLVIDO] (1)
ocorreu um erro ao carregar o pacote (4)
Ubuntu 24.04.01 do nada as pastas estão abrindo o Analisador de arquiv... (1)