Jogo Micro Breakout

Publicado por Samuel Leonardo 15/06/2009 (última atualização em 13/08/2009)

[ Hits: 9.197 ]

Homepage: https://nerdki.blogspot.com.br/

Download MicroBreakout.tar.gz

Download versao2.MicroBreakout.tar.gz (versão 2)




Mais um joguinho meu, um breakout simples.

Controles:
  --botão espaço inicia o jogo
  --seta esquerda/direita controlam o paddle
  --botão escape termina o jogo


Acompanha uma versão pré-compilada (como sempre)
Para compilar:
  $ gcc -o breakout breakout.c -lSDL
  Para executar:
  $ ./breakout
  
Valeu!

  



Versões atualizadas deste script

Versão 2 - Enviado por Samuel Leonardo em 13/08/2009

Changelog: Retirada a linha 203: printf("PADDLE_>BALL\n");

Download versao2.MicroBreakout.tar.gz


Esconder código-fonte

/*
  Jogo Micro Breakout
  Mais um joguinho meu, um breakout simples.
  Controles:
  --botão espaço inicia o jogo
  --seta esquerda/direita controlam o paddle
  --botão escape termina o jogo
  Acompanha uma versão pré-compilada (como sempre)
  Para compilar:
  $ gcc -o breakout breakout.c -lSDL
  Para executar:
  $ ./breakout
  
  valeu!
  
  OBSERVE: POR FAVOR, SE POSSIVEL DEIXE UM COMENTARIO ;)
*/

#include <stdio.h>
#include <SDL/SDL.h>

#define  FPS    60
#define  BPP    16
#define  FLAGS  (SDL_SWSURFACE | SDL_HWSURFACE | SDL_ANYFORMAT | SDL_HWACCEL | SDL_RLEACCEL | SDL_DOUBLEBUF)

/*para os eventos de teclado*/
#define  DOWN   1 /*o usuario apertou um botão*/
#define  UP     0 /*o usuario soltou o botão*/

#define  MAP_W        10
#define  MAP_H        15

#define  BRICK_W      96
#define  BRICK_H      32

#define  B_VELO        5
#define  PADDLE_VELO   15

char map[MAP_H][MAP_W] = {
{"aaaaaaaaaa"},
{"aee....eea"},
{"aeeeeeeeea"},
{"adddddddda"},
{"acccccccca"},
{"abbbbbbbba"},
{"aa.a.ae.aa"},
{"aea.aa.aea"},
{".........."},
{".........."},
{".........."},
{".........."},
{".........."},
{".........."},
{".........."}
};

//botões inicializando
int right = UP, left = UP;//, space = UP;

void FPS_Control(Uint32 time);
int MovePaddle(int *x, int w, int *velo_x, int screen_w);
int MoveBall(int *x, int w, int *velo_x, int *y, int h, int *velo_y, int screen_w);
int Colli_Hor(int ax, int aw, int bx, int bw);
int Colli_Ver(int ay, int ah, int by, int bh);
int Colli_Point(int ax, int ay, int bx, int by);
int Colli_BallBrick(int ax, int ay, int aw, int ah, int bx, int by);
int ChangeBrick(int coor_x, int coor_y, char to_c);//muda um caractere no mapa dos blocos
int BrickIndex(char map_c, const char *brickstr);
int Blit(SDL_Surface *surf, SDL_Surface *screen, int x, int y);
void DrawMap(SDL_Surface *bricks, int w, int h, const char *brickstr, SDL_Surface *b_side, SDL_Surface *screen);


int main(int argc, char *argv[])
{
  SDL_Event event;
  SDL_Surface *screen, *bricks, *paddle, *b_side, *ball;
  
  screen = SDL_SetVideoMode(MAP_W*BRICK_W, MAP_H*BRICK_H, BPP, FLAGS);
  if(screen == NULL)
     {
       printf("%s\n", SDL_GetError());
       exit(1);
     }
  
  ball = SDL_LoadBMP("imagens/ball.bmp");
  bricks = SDL_LoadBMP("imagens/bricks.bmp");
  paddle = SDL_LoadBMP("imagens/paddle.bmp");
  b_side = SDL_LoadBMP("imagens/brick_side.bmp");
  if(!ball || !bricks || !paddle || !b_side)
     {
       printf("%s\n", SDL_GetError());
       SDL_Quit();
       exit(1);
     }
  //transparencia
  SDL_SetColorKey(ball, SDL_SRCCOLORKEY | SDL_RLEACCEL, SDL_MapRGB(ball->format, 0, 255, 0));
  SDL_SetColorKey(b_side, SDL_SRCCOLORKEY | SDL_RLEACCEL, SDL_MapRGB(b_side->format, 0, 255, 0));
  SDL_SetColorKey(bricks, SDL_SRCCOLORKEY | SDL_RLEACCEL, SDL_MapRGB(bricks->format, 0, 255, 0));
  SDL_SetColorKey(paddle, SDL_SRCCOLORKEY | SDL_RLEACCEL, SDL_MapRGB(paddle->format, 0, 255, 0));

  //A forma correta de inicializar o SDL é só depois de configurar o screen
  if(SDL_Init(SDL_INIT_VIDEO) != 0)
     {
       printf("%s\n", SDL_GetError());
       SDL_Quit();
       exit(1);
     }
  
  int done = 0;
  //paddle
  int px, py, velo_x;
  
  velo_x = 0;
  px = (screen->w - paddle->w)/2;
  py = (screen->h - paddle->h);

  //bola
  int move_init = 0;
  int bx, by, b_velo_x, b_velo_y;
  
  bx = (screen->w - ball->w)/2;
  by = (py - 19);//19 é a largura/altura da bola para colisão
  b_velo_x = 0;
  b_velo_y = 0;
  
  Uint32 time_now;
  SDL_WM_SetCaption("MicroBreakout - by Sam L.", NULL);
  while(!done)
        {
          time_now = SDL_GetTicks();
          while(SDL_PollEvent(&event))
                {
                  if(event.type == SDL_KEYDOWN)
                     {
                       switch(event.key.keysym.sym)
                              {
                                case SDLK_RIGHT:
                                     right = DOWN;
                                     break;

                                case SDLK_LEFT:
                                     left = DOWN;
                                     break;

                                case SDLK_ESCAPE:
                                     done = 1;
                                     break;

                                case SDLK_SPACE:
                                     if(move_init == 0)
                                        {
                                          b_velo_x = -B_VELO;
                                          b_velo_y = -B_VELO;
                                          move_init = 1;
                                        }

                                default:
                                      break;
                              }
                     }
                  if(event.type == SDL_KEYUP)
                     {
                       switch(event.key.keysym.sym)
                              {
                                case SDLK_RIGHT:
                                     right = UP;
                                     break;

                                case SDLK_LEFT:
                                     left = UP;
                                     break;

                                default:
                                      break;
                              }
                     }
                  if(event.type == SDL_QUIT)
                     {
                       done = 1;
                     }
                }
          //19 é a largura/altura da bola para colisão
          MoveBall(&bx, 19, &b_velo_x, &by, 19, &b_velo_y, screen->w);
          if((by + 19) > screen->h)
             {
               velo_x = 0;
               px = (screen->w - paddle->w)/2;
               py = (screen->h - paddle->h);

               bx = (screen->w - ball->w)/2;
               by = (py - 19);//19 é a largura/altura da bola para colisão
               b_velo_x = 0;
               b_velo_y = 0;
               move_init = 0;
             }
          
          //bate acima do paddle
          if(Colli_Point(bx + 9, by + 19, px, py) ||
             Colli_Point(bx + 19, by + 9, px, py) || 
             Colli_Point(bx, by + 9, px, py))
             {
               b_velo_y = -b_velo_y;
               printf("PADDLE_>BALL\n");
             }


          MovePaddle(&px, paddle->w, &velo_x, screen->w);
          SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 255, 255, 255));
          //void DrawMap(SDL_Surface *bricks, int w, int h, const char *brickstr, SDL_Surface *b_side, SDL_Surface *screen)
          DrawMap(bricks, BRICK_W, BRICK_H, ".abcde", b_side, screen);
          Blit(ball, screen, bx, by);
          Blit(paddle, screen, px, py);
          
          SDL_UpdateRect(screen, 0,0,0,0);
          FPS_Control(time_now);
        }
  SDL_Quit();
  return 0;
}

void FPS_Control(Uint32 time)
{
  static int fps = 1000/FPS;

  Uint32 time2 = SDL_GetTicks() - time;
  if(time2 < fps)
     {
       SDL_Delay(fps - time2);
     }
}

int MovePaddle(int *x, int w, int *velo_x, int screen_w)
{
  //sempre parado se não apertar nenhum botão
  *velo_x = 0;
  
  if(right == DOWN)
     {
       *velo_x = PADDLE_VELO;
     }
  
  if(left == DOWN)
     {
       *velo_x = -PADDLE_VELO;
     }
  //movendo no screen
  *x = *x + *velo_x;
  
  //limitando a posição dentro do screen
  //Se a posição do paddle for menor que zero...
  if(*x < 0)
     {
     //...fixe a posição do paddle em 0, pois estava indo para esquerda.
       *x = 0;
     }
  //Se não, se aposição do paddle for maior do que a largura do screen...
  else if(*x + w > screen_w)
          {
          //...fixe a posição do paddle em screen_w - w, pois estava indo para direita.
            *x = screen_w - w;//w é a largura do paddle
          }

  return 0;
}

int MoveBall(int *x, int w, int *velo_x, int *y, int h, int *velo_y, int screen_w)
{
  int lin, col, side;
  int brick_x, brick_y, colli = 0;
 //mova a bola no eixo X
  *x = *x + *velo_x;
//verifique se ela não saiu dos limites do screen_w
 if( (*x < 0) || (*x + w > screen_w) )//se saido a esquerda/direita do screen
    {
      *velo_x = -(*velo_x);
    }
 
 //mova a bola no eixo Y
  *y = *y + *velo_y;

 //verifique se ela não saiu dos limites do screen_h
  if(*y < 0)//se saindo por cima do screen
     {
       *velo_y = -(*velo_y);
     }

 //NOTE: Aqui tá muito mal feito mas funciona
  for(lin = 0; lin < MAP_H && (colli == 0); lin++)
      {
        brick_y = lin*BRICK_H;
        for(col = 0; col < MAP_W && (colli == 0); col++)
            {
              brick_x = col*BRICK_W;
              if(map[lin][col] != '.')
                {
                  side = Colli_BallBrick(*x, *y, w, h, brick_x, brick_y);

                  switch(side)
                         {
                           case 0:
                                break;

                           case 1://esquerda/direita
                                *velo_x = -(*velo_x);
                                break;

                           case 2://cima/baixo
                                *velo_y = -(*velo_y);
                               break;

                           case 3://no centro
                                *velo_x = -(*velo_x);
                                *velo_y = -(*velo_y);
                                break;
                         }
                  if(side != 0)
                     {
                       colli = ChangeBrick(col, lin, '.');
                     }
                }
            }
      }

  return 0;
}

int Colli_BallBrick(int ax, int ay, int aw, int ah, int bx, int by)
{
 

  //nas laterais
  if(Colli_Point(ax, ay + ah/2, bx, by) ||
     Colli_Point(ax + aw, ay + ah/2, bx, by))
     {
       return 1;
     }

  //em cima/baixo
  if(Colli_Point(ax + aw/2, ay, bx, by) ||
     Colli_Point(ax + aw/2, ay + ah, bx, by))
     {
       return 2;
     }

  if(Colli_Point(ax + aw/2, ay + ah/2, bx, by))
     {
       printf("COLLI:::#\n");
       return 3;
     }

  return 0;
}

int Colli_Point(int ax, int ay, int bx, int by)
{
  if(ax > bx + BRICK_W)  return 0;
  if(ax < bx)            return 0;
  
  if(ay > by + BRICK_H)  return 0;
  if(ay < by)            return 0;
  
  return 1;
}

int Colli_Hor(int ax, int aw, int bx, int bw)
{
  if(ax > bx + bw)   return 0;
  if(ax + aw < bx)   return 0;
  
  return 1;
}

int Colli_Ver(int ay, int ah, int by, int bh)
{
  if(ay > by + bh)   return 0;
  if(ay + ah < by)   return 0;
  
  return 1;
}

int ChangeBrick(int coor_x, int coor_y, char to_c)
{
  if(map[coor_y][coor_x] != '.')//'.' é o vazio
     {
       map[coor_y][coor_x] = to_c;
       return 1;
     }

  return 0;
}

int BrickIndex(char map_c, const char *brickstr)
{
  int aux;
  
  aux = 0;
  while(*brickstr)
        {
          if(*brickstr == map_c)
             {
               return aux;
             }
          brickstr++;
          aux++;
        }

  return -1;
}

int Blit(SDL_Surface *surf, SDL_Surface *screen, int x, int y)
{
  SDL_Rect offset;
  
  offset.x = x;
  offset.y = y;
  
  return SDL_BlitSurface(surf, NULL, screen, &offset);
}

void DrawMap(SDL_Surface *bricks, int w, int h, const char *brickstr, SDL_Surface *b_side, SDL_Surface *screen)
{
  int lin, col, index;
  SDL_Rect font, dest;

  font.x = 0;
  font.y = 0;
  font.w = w;
  font.h = h;
  
  lin = 0;
  while(lin < MAP_H)
        {
          dest.y = lin*h;
          col = 0;
          while(col < MAP_W)
                {
                  dest.x = col*w;

                  index = BrickIndex(map[lin][col], brickstr);

                  if(index > 0)
                     {
                       font.y = index*h;
                       SDL_BlitSurface(bricks, &font, screen, &dest);
                       SDL_BlitSurface(b_side, NULL, screen, &dest);
                     }

                  col++;
                }
          lin++;
        }
}


Scripts recomendados

AA linux kernel modificado por minhe

Jogo Windows Invaders (com gráficos)

Jogo da Velha com IA invencivel

Rotina para controle de portas paralelas em C. (biblioteca LP.h)

POGRAMA EM C REGISTRO DE CADASTRO ALTERAR E REMOVER CLIENTES PRODUTOS


  

Comentários
[1] Comentário enviado por danielgimenes em 17/06/2009 - 20:05h

haha..

ficou legal! Só faltou um "vc venceu" e um "fim de jogo". ;)

[2] Comentário enviado por SamL em 17/06/2009 - 20:18h

E cara foi mesmo, hehehe
Mas no próximo script vou lembrar de fazer isso.
valeu pelo toque!

[3] Comentário enviado por SamL em 21/06/2009 - 04:01h

Wow!, esse script teve quase 800 hits em 2 horas, na madrugada.

[4] Comentário enviado por jomarumu em 03/01/2010 - 16:50h

Pode dar esse problema:

initializer-string for array of chars is too long

Mas é fácil retirar, é só remover um caractere de cada linha.

Muito bom o seu código, só não entendi o porque na homepage: "Um Dia Talvez!", com esses códigos você teria uma bela página, o Macoratti do C++ :)


Contribuir com comentário




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts