基于SDL2自制俄罗斯方块

俄罗斯方块是一款十分经典的游戏,曾风靡全球,小时候玩得第一款电子游戏就是掌机俄罗斯方块。

现在我们基于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

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SDL制作俄罗斯方块是完全可行的。SDL(Simple DirectMedia Layer)是一个跨平台的多媒体库,非常适合用于制作游戏。 首先,我们需要定义游戏的基本元素和规则。俄罗斯方块游戏通常由一个矩形的游戏区域、七种不同类型的方块和下落速度组成。玩家需要操作方块,使其在游戏区域中水平移动并旋转,直到方块堆积到游戏区域底部或其他方块上方。当一行填满时,该行将被清除,并获得得分。游戏继续进行直到方块堆积得太高时,导致游戏结束。 接下来,我们可以使用SDL的图形功能来绘制游戏界面。可以使用SDL的绘图函数来绘制游戏区域、方块和分数等。还可以使用SDL的输入功能来响应玩家的操作,如按键盘上的箭头键来控制方块的移动和旋转。 游戏的逻辑部分可以使用C或C++来编写。可以使用循环来控制方块的下落速度和游戏的进行。可以使用数组或链表来表示游戏区域和方块的位置。每一次循环,都需要检测方块是否可以向下移动或旋转,如果不能则堆积方块并生成新的方块。 游戏还需要处理方块堆积到顶部或其他方块上方时游戏结束的情况。此时可以使用SDL的消息框功能来显示游戏结束的提示信息,并可以根据需要选择重新开始游戏或退出游戏。 在编写完成后,可以使用SDL的编译工具来编译和构建游戏,并在支持SDL的平台上进行测试和运行。 总的来说,使用SDL制作俄罗斯方块是一个有趣和具有挑战性的项目。通过合理规划和编写,我们可以实现一个完整的俄罗斯方块游戏,并让玩家体验到经典的游戏乐趣。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值