Jogo Micro Breakout

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

[ Hits: 8.113 ]

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

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

QuickSort Genérico

Arvores Red Black

Joguinho de labirinto usando as setas do teclado

Calculadora em C++

Emulador de Chip8 (com gráficos)


  

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
Linux banner
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts