📄 tetris_cpp.cpp
字号:
//============================================================================// Name : tetris_cpp.cpp// Author : gogo649// Version :// Copyright : Your copyright notice// Description : tetris in C, SDL SDL_image SDL_mixer//============================================================================//俄罗斯方块程序#include <SDL/SDL.h>#include <iostream>#include <SDL/SDL_image.h>#include <SDL/SDL_mixer.h>using namespace std;#define HW 512#define HH 720#define BLOCK_W 30 //象素值#define BLOCK_H 30#define GAME_W 10 //BLOCK值#define GAME_H 24#define MAXUPDATES 8*GAME_W+4*4#define FPS 40#define MAXINT 999999999#define FONT_WIDTH 16#define FONT_HIGHT 16SDL_Surface *screen, *back, *block, *block_2, *block_3, *block_4, *block_5, *block_6, *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; //形状 int color; 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() { back = LoadIMG("C:\\tetris\\back.jpg"); block = LoadIMG("C:\\tetris\\element.png"); block_2 = LoadIMG("C:\\tetris\\element_2.png"); block_3 = LoadIMG("C:\\tetris\\element_3.png"); block_4 = LoadIMG("C:\\tetris\\element_4.png"); block_5 = LoadIMG("C:\\tetris\\element_5.png"); block_6 = LoadIMG("C:\\tetris\\element_6.png"); frame = LoadIMG("C:\\tetris\\frame.png"); font = LoadIMG("C:\\tetris\\glassfont1.png"); up = LoadIMG("C:\\tetris\\up.png"); bottom = LoadIMG("C:\\tetris\\bottom.png");// 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(block_2); SDL_FreeSurface(block_3); SDL_FreeSurface(block_4); SDL_FreeSurface(block_5); SDL_FreeSurface(block_6); 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);}SDL_Surface* ch_block_col(int color){ switch (color) { case 1: return block; break; case 2: return block_2; break; case 3: return block_3; break; case 4: return block_4; break; case 5: return block_5; break; case 6: return block_6; break; default: return block; break; }}void creatblock() { int type = rand() % 19; int color = rand() % 6 +1; next.type = type; next.color = color; next.img = ch_block_col(color); current.x = GAME_W / 2; current.y = 2;}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.color = next.color; 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] = current.color; } 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]) { //什么颜色的方块落下还是什么颜色 gamestate[][]保存颜色状态 SDL_BlitSurface(ch_block_col(gamestate[i][j]), NULL, screen, &dst); } else { SDL_BlitSurface(back, &dst, screen, &dst); } SDL_UpdateRects(screen, 1, &dst); } //当前 = 下一个 { current.type = next.type; current.img = next.img; current.color = next.color; } creatblock(); drawobject(next); } updatescene(); }}int main(int argc, char *argv[]) { init(); LoadData(); SDL_BlitSurface(back, NULL, screen, NULL); SDL_Flip(screen); numupdates = 0; rungame(); FreeData();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -