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.811 ]
Por: Samuel Leonardo em 18/11/2013 | Blog: https://nerdki.blogspot.com.br/
#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 um avatar do Tux no InkScape
Algoritmo Antissocial - Recuperando o Controle da sua Mente
Dicas para aprender programação
Desenhando fácil um pinguim no Inkscape
lib cURL - Trabalhe com URLs em C
Tratamento de exceções na linguagem C
Android NDK: Desmistificando o acesso a códigos nativos em C
Passkeys: A Evolução da Autenticação Digital
Instalação de distro Linux em computadores, netbooks, etc, em rede com o Clonezilla
Título: Descobrindo o IP externo da VPN no Linux
Armazenando a senha de sua carteira Bitcoin de forma segura no Linux
Enviar mensagem ao usuário trabalhando com as opções do php.ini
Instalando Brave Browser no Linux Mint 22
vídeo pra quem quer saber como funciona Proteção de Memória:
Encontre seus arquivos facilmente com o Drill
Mouse Logitech MX Ergo Advanced Wireless Trackball no Linux
Compartilhamento de Rede com samba em modo Público/Anônimo de forma simples, rápido e fácil
Remoção de propaganda com o programa Comskip[AJUDA] (3)
Instalação do drive do adaptador wiffi (5)
Linux Lite Demorando Muito Para Ligar (1)