俄罗斯方块是一款十分经典的游戏,曾风靡全球,小时候玩得第一款电子游戏就是掌机俄罗斯方块。
现在我们基于SDL2自制俄罗斯方块。
首先我们通过3维数组定义不同种类的方块,方块矩阵为4x4的二维数组,第三维为每种方块的变形种类。
const int TT_Blocks[TT_BLOCK_TYPE_NUM][TT_BLOCK_TRANS_NUM][TT_BLOCK_NUM_AREA_HEIGHT][TT_BLOCK_NUM_AREA_WIDTH] = {
//TT_BLOCK_TYPE_NUM
{
//TT_BLOCK_TRANS_NUM
{
//TT_BLOCK_AREA_HEIGHT * TT_BLOCK_AREA_WIDTH
{1, 1, 1, 1},
{0, 0, 0, 0},
{0, 0, 0, 0},
{0, 0, 0, 0}
},
{
{0, 0, 1, 0},
{0, 0, 1, 0},
{0, 0, 1, 0},
{0, 0, 1, 0}
},
{
{1, 1, 1, 1},
{0, 0, 0, 0},
{0, 0, 0, 0},
{0, 0, 0, 0}
},
{
{0, 0, 1, 0},
{0, 0, 1, 0},
{0, 0, 1, 0},
{0, 0, 1, 0}
}
},
{
{
{1, 0, 0, 0},
{1, 1, 1, 0},
{0, 0, 0, 0},
{0, 0, 0, 0}
},
{
{1, 1, 0, 0},
{1, 0, 0, 0},
{1, 0, 0, 0},
{0, 0, 0, 0}
},
{
{1, 1, 1, 0},
{0, 0, 1, 0},
{0, 0, 0, 0},
{0, 0, 0, 0}
},
{
{0, 1, 0, 0},
{0, 1, 0, 0},
{1, 1, 0, 0},
{0, 0, 0, 0}
}
},
{
{
{1, 1, 1, 0},
{0, 1, 0, 0},
{0, 0, 0, 0},
{0, 0, 0, 0}
},
{
{0, 1, 0, 0},
{1, 1, 0, 0},
{0, 1, 0, 0},
{0, 0, 0, 0}
},
{
{0, 1, 0, 0},
{1, 1, 1, 0},
{0, 0, 0, 0},
{0, 0, 0, 0}
},
{
{1, 0, 0, 0},
{1, 1, 0, 0},
{1, 0, 0, 0},
{0, 0, 0, 0}
}
},
{
{
{1, 1, 0, 0},
{1, 1, 0, 0},
{0, 0, 0, 0},
{0, 0, 0, 0}
},
{
{1, 1, 0, 0},
{1, 1, 0, 0},
{0, 0, 0, 0},
{0, 0, 0, 0}
},
{
{1, 1, 0, 0},
{1, 1, 0, 0},
{0, 0, 0, 0},
{0, 0, 0, 0}
},
{
{1, 1, 0, 0},
{1, 1, 0, 0},
{0, 0, 0, 0},
{0, 0, 0, 0}
}
},
{
{
{1, 0, 0, 0},
{1, 1, 0, 0},
{0, 0, 0, 0},
{0, 0, 0, 0}
},
{
{1, 1, 0, 0},
{1, 0, 0, 0},
{0, 0, 0, 0},
{0, 0, 0, 0}
},
{
{1, 1, 0, 0},
{0, 1, 0, 0},
{0, 0, 0, 0},
{0, 0, 0, 0}
},
{
{0, 1, 0, 0},
{1, 1, 0, 0},
{0, 0, 0, 0},
{0, 0, 0, 0}
}
},
{
{
{1, 1, 0, 0},
{0, 1, 1, 0},
{0, 0, 0, 0},
{0, 0, 0, 0}
},
{
{0, 0, 1, 0},
{0, 1, 1, 0},
{0, 1, 0, 0},
{0, 0, 0, 0}
},
{
{1, 1, 0, 0},
{0, 1, 1, 0},
{0, 0, 0, 0},
{0, 0, 0, 0}
},
{
{0, 0, 1, 0},
{0, 1, 1, 0},
{0, 1, 0, 0},
{0, 0, 0, 0}
}
}
};
有了方块之后,我们使用SDL2库对数组对应方块就行渲染,即值不为0的位置渲染出方块粒,值为0的位置不渲染。同时,我们使用颜色类型这个变量代表红、绿、蓝、黄色的方块,不同颜色使用不同的纹理。
void drawBlocks(TT_Window *win, TT_Block *block){
if(block->bShown == false){
return;
}
int i, j;
int x = block->x;
int y = block->y;
for(i = 0; i < TT_BLOCK_NUM_AREA_HEIGHT; i++){
x = block->x;
for(j = 0; j < TT_BLOCK_NUM_AREA_WIDTH; j++){
if(TT_Blocks[block->type][block->curTransState][i][j] >= 1){
renderImageFromTexture(win, &block->tex[block->colorType - 1], NULL, x, y);
}
x += TT_BLOCK_WIDTH;
}
y += TT_BLOCK_HEIGHT;
}
}
我们利用SDL2把不同图片载入成相应的的纹理(Texture),如红、黄、绿、蓝色方块粒的图片以及背景图片。
TT_Texture loadImageTexture(TT_Window *win, const char *imgPath){
TT_Texture texture = {
.texture = NULL,
.width = 0,
.height = 0
};
SDL_Surface *surface = IMG_Load(imgPath);
if(!surface){
SDL_Log("Failed to load image %s: %s\n", imgPath, IMG_GetError());
}else{
SDL_SetColorKey(surface, SDL_TRUE, SDL_MapRGB(surface->format, 0xff, 0xff, 0xff));
texture.texture = SDL_CreateTextureFromSurface(win->render, surface);
if(!texture.texture){
SDL_Log("Failed to load image %s: %s\n", imgPath, SDL_GetError());
}
texture.width = surface->w;
texture.height = surface->h;
SDL_FreeSurface(surface);
}
return texture;
}
再添加一些俄罗斯方块的游戏逻辑,如消除完成的层,统计得分等。
void deleteCompletedBlocks(TT_Block *block){
if(block->remainBlockWidth < TT_BACKGROUND_WIDTH){
return;
}
int width = 0;
int height = 0;
int rowFlag = 0;
int tmp[TT_BLOCK_NUM_BACKGROUND_HEIGHT][TT_BLOCK_NUM_BACKGROUND_WIDTH];
SDL_memset(tmp, 0, sizeof (tmp));
for(int i = 0; i < TT_BLOCK_NUM_BACKGROUND_HEIGHT; i++){
width = 0;
for(int j = 0; j < TT_BLOCK_NUM_BACKGROUND_WIDTH; j++){
if(TT_RemainBlocks[i][j] >= 1){
width += 1;
if(width == TT_BLOCK_NUM_BACKGROUND_WIDTH){
for(int k = 0; k < TT_BLOCK_NUM_BACKGROUND_WIDTH; k++){
TT_RemainBlocks[i][k] = 0;
}
block->score++;
if(block->score > block->maxScore){
block->maxScore = block->score;
}
playSound(block->completeSound);
}
}
}
}
height = TT_BLOCK_NUM_BACKGROUND_HEIGHT - 1;
for(int i = TT_BLOCK_NUM_BACKGROUND_HEIGHT - 1; i > 0; i--){
for(int j = 0; j < TT_BLOCK_NUM_BACKGROUND_WIDTH; j++){
if(TT_RemainBlocks[i][j] >= 1){
tmp[height][j] = TT_RemainBlocks[i][j];
rowFlag = 1;
}
}
if(rowFlag == 1){
--height;
rowFlag = 0;
}
}
SDL_memcpy(TT_RemainBlocks, tmp, sizeof (TT_RemainBlocks));
calRemainBlocksSize(block);
}
我们来看看运行效果吧:
项目地址:https://gitee.com/yorkee/tetris