正文

SDL版本的俄罗斯方块程序2007-01-01 00:49:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/tonyhu/22142.html

分享到:

放元旦了……三天假,很闲……
其实要做的事实很多,都快期末考试了,可看着教材就不想看……
就花了点时间写了个俄罗斯方块程序了……
听有人说俄罗斯方块是初学程序设计语言去写的样本例子……
我真惭愧呀……我还花了两个下午来研究这个“初学者”级的程序……==||
不知道是那们人太牛了,还是我太逊了……

程序运行状态:


程序:tetris.cc

程序写得乱,我也懒得写注解了……因为总感觉人太逊了……
写得注解更要误导别人了……
可能受了那“牛人“打击了……

/***************************************************************************
 *            tetris.cc
 *
 *  Sat Dec 30 19:31:35 2006
 *  Copyright  2006  HuYinLin
 *  Email huyinlin@126.com
 ****************************************************************************/
//俄罗斯方块程序
#include <SDL/SDL.h>
#include <iostream>
#include <SDL/SDL_image.h>
#include <SDL/SDL_mixer.h>

using namespace std;

#define HW 512
#define HH 704

#define BLOCK_W 32  //象素值
#define BLOCK_H 32

#define GAME_W 10  //BLOCK值
#define GAME_H 22
#define MAXUPDATES 8*GAME_W+4*4

#define FPS 40
#define MAXINT 999999999

#define FONT_WIDTH 16
#define FONT_HIGHT 16

SDL_Surface *screen, *back, *block, *frame, *font, *up, *bottom;
int gamestate[GAME_W + 2][GAME_H + 1] = { };

int score;

typedef struct
{
 int coor[4][2];  //相对坐标
 int rotate_next;
} shape;

typedef struct
{
 int x, y;  //block坐标
 int type;  //形状
 SDL_Surface *img;
} object;

enum
{
 BOTTOM_WAV,
 EXPLODE_WAV,
 EXCELLENT_WAV,
 NUM_WAVES
};

Mix_Chunk *sounds[NUM_WAVES];

object current, next;
int speed = 10;

SDL_Rect src[MAXUPDATES];
SDL_Rect dst[MAXUPDATES];

int numupdates;

typedef struct
{
 SDL_Rect *src, *dst;
 SDL_Surface *img;
} Blit;

Blit blits[MAXUPDATES];

shape SP[19] = {
 {0, 0, 1, 0, 0, 1, 0, 2, 1},
 {-1, 0, -1, 1, 0, 1, 1, 1, 2},
 {0, 2, 1, 2, 1, 1, 1, 0, 3},
 {-1, 1, 0, 1, 1, 1, 1, 2, 0},

 {0, 0, 0, 1, 0, 2, 1, 2, 5},
 {-1, 1, 0, 1, 1, 1, 1, 0, 6},
 {0, 0, 1, 0, 1, 1, 1, 2, 7},
 {0, 2, 0, 1, 1, 1, 2, 1, 4},

 {0, 0, -1, 0, 1, 0, 0, 1, 9},
 {0, 0, 0, 1, 0, 2, 1, 1, 10},
 {-1, 1, 0, 1, 1, 1, 0, 0, 11},
 {0, 0, 0, 1, 0, 2, -1, 1, 8},

 {0, 0, -1, 0, 0, 1, 1, 1, 13},
 {0, 1, 0, 2, 1, 1, 1, 0, 12},

 {0, 0, 0, 1, 1, 0, -1, 1, 15},
 {0, 0, 0, 1, 1, 1, 1, 2, 14},

 {0, 0, 0, 1, 0, 2, 0, 3, 17},
 {-1, 1, 0, 1, 1, 1, 2, 1, 16},

 {0, 0, 0, 1, 1, 1, 1, 0, 18}
};

void
drawobject (object sprite)
{
 Blit *update;
 for (int i = 0; i < 4; i++)
 {
  update = &blits[numupdates++];
  update->img = sprite.img;
  update->src->x = update->src->y = 0;
  update->src->w = BLOCK_W;
  update->src->h = BLOCK_H;
  update->dst->x =
   (sprite.x + SP[sprite.type].coor[i][0]) * BLOCK_W -
   frame->w;
  update->dst->y =
   (sprite.y - SP[sprite.type].coor[i][1]) * BLOCK_H -
   frame->h;
  update->dst->w = BLOCK_W;
  update->dst->h = BLOCK_H;
 }
}

void
eraseobject (object sprite)
{
 Blit *update;
 for (int i = 0; i < 4; i++)
 {
  update = &blits[numupdates++];
  update->img = back;
  update->src->x =
   (sprite.x + SP[sprite.type].coor[i][0]) * BLOCK_W -
   frame->w;
  update->src->y =
   (sprite.y - SP[sprite.type].coor[i][1]) * BLOCK_H -
   frame->h;
  update->src->w = BLOCK_W;
  update->src->h = BLOCK_H;
  update->dst->x =
   (sprite.x + SP[sprite.type].coor[i][0]) * BLOCK_W -
   frame->w;
  update->dst->y =
   (sprite.y - SP[sprite.type].coor[i][1]) * BLOCK_H -
   frame->h;
  update->dst->w = BLOCK_W;
  update->dst->h = BLOCK_H;
 }
}
void
updatescene ()
{
 for (int i = 0; i < numupdates; i++)
  SDL_BlitSurface (blits[i].img, blits[i].src, screen,
     blits[i].dst);
 SDL_UpdateRects (screen, numupdates, dst);
 numupdates = 0;
}

void
Rotate ()
{
 int i, x, y;
 int type = SP[current.type].rotate_next;

 for (i = 0; i < 4; i++)
 {
  x = current.x + SP[type].coor[i][0];
  y = current.y + SP[type].coor[i][1];
  if (gamestate[x][y] != 0)
   break;
 }
 if (i == 4)
  current.type = type;
 else
  return;
}

void
drawframe ()
{
 int i = 0, j = 0, flag = 0;
 int down[4];
 for (i = 0; i < 4; i++)
  down[j++] = current.x + SP[current.type].coor[i][0];

 SDL_Rect dst;
 dst.w = frame->w;
 dst.h = frame->h;
 for (i = 0; i < HH; i += frame->h)
 {
  dst.x = 0;
  dst.y = i;
  SDL_BlitSurface (frame, NULL, screen, &dst);
  SDL_UpdateRects (screen, 1, &dst);
  dst.x = frame->w + GAME_W * BLOCK_W;
  SDL_BlitSurface (frame, NULL, screen, &dst);
  SDL_UpdateRects (screen, 1, &dst);
 }
 for (i = 0; i < frame->w + GAME_W * BLOCK_W; i += frame->w)
 {
  dst.y = HH - frame->h;
  dst.x = i;
  flag = 0;
  for (j = 0; j < 4; j++)
  {
   if (dst.x == (down[j] * BLOCK_H) - frame->w)
   {
    SDL_BlitSurface (bottom, NULL, screen, &dst);
    SDL_UpdateRects (screen, 1, &dst);
    i += frame->w;
    dst.x = i;
    SDL_BlitSurface (bottom, NULL, screen, &dst);
    flag = 1;
   }
  }
  if (!flag)
   SDL_BlitSurface (frame, NULL, screen, &dst);
  SDL_UpdateRects (screen, 1, &dst);
 }
}

void
init ()
{
 int i;
 if (SDL_Init (SDL_INIT_AUDIO | SDL_INIT_VIDEO) < 0)
  fprintf (stderr, "init error\n");
 if ((screen =
      SDL_SetVideoMode (HW, HH, 32,
          SDL_HWSURFACE | SDL_DOUBLEBUF)) == NULL)
  fprintf (stderr, "set video mode error\n");
 srand (time (NULL));
 atexit (SDL_Quit);

 SDL_WM_SetCaption ("tetris", "");

 for (i = 0; i < MAXUPDATES; i++) //更新矩阵进行锁定
 {
  blits[i].src = &src[i];
  blits[i].dst = &dst[i];
 }
 for (i = 0; i < GAME_W + 2; i++) //设置底线
  gamestate[i][GAME_H] = 1;
 for (i = 0; i < GAME_H; i++)
  gamestate[0][i] = gamestate[GAME_W + 1][i] = 1;

 next.x = 13;
 next.y = 10;

 if (Mix_OpenAudio (22050, AUDIO_U16, 1, 512) < 0)
 {
  fprintf (stderr,
    "Warning: Couldn't set 22050 Hz 16-bit audio\n- Reason: %s\n",
    SDL_GetError ());
 }
}

SDL_Surface *
LoadIMG (const char *name)
{
 SDL_Surface *tmp, *ok;
 if ((tmp = IMG_Load (name)) == NULL)
 {
  fprintf (stderr, "load %s error\n", name);
  return NULL;
 }
 ok = SDL_DisplayFormat (tmp);
 SDL_FreeSurface (tmp);
 SDL_SetColorKey (ok, SDL_SRCCOLORKEY | SDL_RLEACCEL,
    *(Uint32 *) ok->pixels);
 return ok;
}

void
showstring (int x, int y, const char *string)
{
 int length = strlen (string), i;
 SDL_Rect src, dst;
 dst.y = y;
 src.w = FONT_WIDTH;
 src.h = FONT_HIGHT;
 for (i = 0; i < length; i++)
 {
  dst.x = x + i * FONT_WIDTH;
  if (string[i] >= 'a' && string[i] <= 'o')
  {
   src.x = (string[i] - 'a' + 1) * FONT_WIDTH;
   src.y = 2 * FONT_HIGHT;
  }
  else
  {
   src.x = (string[i] - 'p') * FONT_WIDTH;
   src.y = 3 * FONT_HIGHT;
  }
  SDL_BlitSurface (font, &src, screen, &dst);
  SDL_UpdateRects (screen, 1, &dst);
 }

}

void
LoadData ()
{
 block = LoadIMG ("element.gif");
 back = LoadIMG ("back.jpg");
 frame = LoadIMG ("frame.gif");
 font = LoadIMG ("glassfont.png");
 up = LoadIMG ("up.gif");
 bottom = LoadIMG ("bottom.gif");

 sounds[BOTTOM_WAV] = Mix_LoadWAV ("bottom.wav");
 sounds[EXPLODE_WAV] = Mix_LoadWAV ("explosion.wav");
 sounds[EXCELLENT_WAV] = Mix_LoadWAV ("excellent.wav");
}

int
moveable (int faceing)
{
 int x, y, i;
 switch (faceing)
 {
 case -1:
  for (i = 0; i < 4; i++)
  {
   x = current.x + SP[current.type].coor[i][0] - 1;
   y = current.y - SP[current.type].coor[i][1];
   if (gamestate[x][y] != 0)
    break;
  }
  if (i == 4)
   return 1;
  else
   return 0;
 case 0:
  for (i = 0; i < 4; i++)
  {
   x = current.x + SP[current.type].coor[i][0];
   y = current.y - SP[current.type].coor[i][1] + 1;
   if (gamestate[x][y] != 0)
    break;
  }
  if (i == 4)
   return 1;
  else
   return 0;
 case 1:
  for (i = 0; i < 4; i++)
  {
   x = current.x + SP[current.type].coor[i][0] + 1;
   y = current.y - SP[current.type].coor[i][1];
   if (gamestate[x][y] != 0)
    break;
  }
  if (i == 4)
   return 1;
  else
   return 0;
 default:
  return 0;
 }
}

int
atbottom ()
{
 if (moveable (0))
  return 0;
 else
  return 1;
}

int
over ()
{
 int y, i;

 for (i = 0; i < 4; i++)
 {
  y = current.y - SP[current.type].coor[i][1];
  if (y < 4)
   break;
 }
 if (i == 4)
  return 0;
 else
  return 1;
}

void
FreeData ()
{
 SDL_FreeSurface (block);
 SDL_FreeSurface (back);
 SDL_FreeSurface (frame);
 SDL_FreeSurface (font);
 SDL_FreeSurface (up);
 SDL_FreeSurface (bottom);
 Mix_CloseAudio ();
}

void
drawupline ()
{
 SDL_Rect src, dst;
 dst.y = 4 * BLOCK_H;
 dst.x = 2 * frame->w + (GAME_W - 2) * BLOCK_W;
 dst.w = up->w;
 dst.h = up->h;
 src.x = src.y = 0;
 src.h = up->h;
 src.w = 2 * BLOCK_W;
 SDL_BlitSurface (up, &src, screen, &dst);
 SDL_UpdateRects (screen, 1, &dst);
}

void
creatblock ()
{
 int type = rand () % 19;
 next.type = type;
 next.img = block;
 current.x = GAME_W / 2;
 current.y = 4;
}

void
moveblock (int faceing)
{
 int can = moveable (faceing);
 if (can)
 {
  switch (faceing)
  {
  case -1:
   current.x--;
   break;
  case 0:
   current.y++;
   break;
  case 1:
   current.x++;
   break;
  };

 }
}

void
wait ()
{
 Uint32 this_tick;
 static Uint32 next_tick = 0;
 this_tick = SDL_GetTicks ();
 if (next_tick > this_tick)
  SDL_Delay (next_tick - this_tick);
 next_tick = this_tick + 1000 / FPS;
}

void
addscore (int num)
{
 switch (num)  //消掉的行数
 {
 case 1:
  score += 100;
  break;
 case 2:
  score += 300;
  break;
 case 3:
  score += 700;
  break;
 case 4:
  score += 1500;
  break;
 default:
  break;
 };
 if (num >= 3)
  Mix_PlayChannel (EXCELLENT_WAV, sounds[EXCELLENT_WAV], 0);
 else
  Mix_PlayChannel (EXPLODE_WAV, sounds[EXPLODE_WAV], 0);
}

void
shownum (int x, int y, int num_char, int num)
{
 int a, i = num_char - 1;
 int S[10] = { };
 while (num != 0)
 {
  a = num % 10;
  S[i--] = a;
  num /= 10;
 }
 SDL_Rect src, dst;
 for (i = 0; i < num_char; i++)
 {
  src.x = S[i] * FONT_WIDTH;
  src.y = 1 * FONT_HIGHT;
  src.w = FONT_WIDTH;
  src.h = FONT_HIGHT;
  dst.x = x + i * FONT_WIDTH;
  dst.y = y;
  dst.w = FONT_WIDTH;
  dst.h = FONT_HIGHT;
  SDL_BlitSurface (back, &dst, screen, &dst);
  SDL_BlitSurface (font, &src, screen, &dst);
  SDL_UpdateRects (screen, 1, &dst);
 }
}

void
eraseline (int line)
{
 int i, j;
 for (j = line - 1; j > 0; j--)
  for (i = 1; i < GAME_W + 1; i++)
   gamestate[i][j + 1] = gamestate[i][j];
}

void
collision ()
{
 int num = 0, i, j;
 for (j = GAME_H - 1; j > 0; j--)
 {
  for (i = 1; i < GAME_W + 1; i++)
  {
   if (gamestate[i][j] == 0)
    break;
  }
  if (i == GAME_W + 1)
  {
   num++;
   eraseline (j++);
  }
 }
 if (num != 0)
  addscore (num);
}

void
rungame ()
{
 SDL_Event event;
 int point = 0;
 Uint8 *key;
 int run = 1, i, j, x, y, w = 0, s = 0;
 int up = 0, left = 0, right = 0, tr = 10, tl = 10;
 numupdates = 0;
 score = 0;
 drawframe ();
 creatblock ();
 current.type = next.type;
 current.img = next.img;
 creatblock ();
 drawobject (next);

 x = frame->w * 4 + GAME_W * BLOCK_W;
 y = BLOCK_H * (GAME_H - 8);
 showstring (x, y, "speed");

 y = BLOCK_H * (GAME_H - 7);
 shownum (x, y, 1, 11 - speed);

 x = frame->w * 4 + GAME_W * BLOCK_W;
 y = BLOCK_H * (GAME_H - 3);
 showstring (x, y, "score");

 x = frame->w * 4 + GAME_W * BLOCK_W;
 y = 6 * BLOCK_H;
 showstring (x, y, "next");

 x = 2 * frame->w + GAME_W * BLOCK_W;
 y = 4 * BLOCK_H;
 showstring (x, y, "upper line");

 x = frame->w * 4 + GAME_W * BLOCK_W;
 y = BLOCK_H * (GAME_H - 2);
 shownum (x, y, 6, score);

 while (run)
 {
  wait ();
  eraseobject (current);

  drawframe ();
  drawupline ();

  point++;
  if (point % (speed * (FPS / 10)) == 0)
   moveblock (0);
  if (point > MAXINT)
   point -= MAXINT;

  while (SDL_PollEvent (&event))
  {
   switch (event.type)
   {
   case SDL_QUIT:
    return;
   };
  }
  key = SDL_GetKeyState (NULL);

  if (!w && key[SDLK_w])
   speed--;
  if (speed < 1)
   speed = 1;
  w = key[SDLK_w];

  if (!s && key[SDLK_s])
   speed++;
  if (speed > 10)
   speed = 10;
  s = key[SDLK_s];
//
  if (key[SDLK_LEFT])
   tl--;
  else
   tl = 10;
  if (tl <= 0 && key[SDLK_LEFT])
   moveblock (-1);
  if (tl > 0 && !left && key[SDLK_LEFT])
   moveblock (-1);
  left = key[SDLK_LEFT];
//
  if (key[SDLK_RIGHT])
   tr--;
  else
   tr = 10;
  if (tr <= 0 && key[SDLK_RIGHT])
   moveblock (1);
  if (tr > 0 && !right && key[SDLK_RIGHT])
   moveblock (1);
  right = key[SDLK_RIGHT];
//
  if (key[SDLK_SPACE])
   moveblock (0);
//
  if (!up && key[SDLK_UP])
   Rotate ();
  up = key[SDLK_UP];
//
  drawobject (current);
  updatescene ();
  speed -= score / 10000;
  if (speed < 1)
   speed = 1;
  else if (speed > 10)
   speed = 10;
  shownum (frame->w * 4 + GAME_W * BLOCK_W,
    BLOCK_H * (GAME_H - 7), 2, 11 - speed);
  if (atbottom ())
  {
   if (over ())
    return;
   Mix_PlayChannel (BOTTOM_WAV, sounds[BOTTOM_WAV], 0);
   eraseobject (next);

   for (i = 0; i < 4; i++)
   {
    x = current.x + SP[current.type].coor[i][0];
    y = current.y - SP[current.type].coor[i][1];
    gamestate[x][y] = 1;
   }
   collision ();

   shownum (frame->w * 4 + GAME_W * BLOCK_W,
     BLOCK_H * (GAME_H - 2), 6, score);

   eraseobject (current);
   updatescene ();
   SDL_Rect dst;
   for (j = GAME_H - 1; j > 0; j--)
    for (i = 1; i < GAME_W + 1; i++)
    {
     dst.x = i * BLOCK_W - frame->w;
     dst.y = j * BLOCK_H - frame->h;
     if (gamestate[i][j])
     {
      SDL_BlitSurface
       (block,
        NULL, screen, &dst);
     }
     else
     {
      SDL_BlitSurface
       (back,
        &dst, screen, &dst);
     }
     SDL_UpdateRects (screen, 1, &dst);
    }
   current.type = next.type;
   current.img = next.img;
   creatblock ();
   drawobject (next);
  }
  updatescene ();
 }
}

int
main ()
{
 init ();
 LoadData ();
 SDL_BlitSurface (back, NULL, screen, NULL);
 SDL_Flip (screen);
 numupdates = 0;
 rungame ();
 FreeData ();
}

阅读(6639) | 评论(9)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

loading...
您需要登录后才能评论,请 登录 或者 注册