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