SDL2窗口按右方向键生成彩色方块、左方向键删除的实现问题
SDL2方块动态增删实现方案
核心修改思路
- 新增
Square结构体存储每个方块的位置、颜色属性 - 用
std::vector容器维护所有方块实例,原生支持后增后删的操作逻辑,刚好匹配需求里「新方块加在最后、删的时候先删最新」的规则 - 预定义颜色池,新增方块时按顺序轮询取色,保证每个方块颜色不同
- 修正原代码逻辑错误:渲染代码不能嵌套在事件轮询
SDL_PollEvent的循环内,否则只有触发输入事件时才会刷新画面;同时删除原代码混用SDL_RenderPresent和SDL_UpdateWindowSurface的冲突逻辑,统一用Renderer渲染即可
完整可运行代码
#include <SDL2/SDL.h> #include <SDL2/SDL_image.h> #include <stdio.h> #include <vector> #include <string> #include <cmath> const int SCREEN_WIDTH = 800; const int SCREEN_HEIGHT = 640; const int MAX_SQUARES = 20; const int SQUARE_SIZE = 100; // 方块结构体 struct Square { SDL_Rect rect; SDL_Color color; }; // 预定义颜色池 const SDL_Color COLORS[] = { {255, 165, 0, 255}, // 橙色 {39, 139, 34, 255}, // 绿色 {0, 255, 255, 255}, // 青色 {127, 0, 255, 255}, // 紫色 {255, 0, 0, 255} // 红色 }; const int COLOR_COUNT = sizeof(COLORS) / sizeof(COLORS[0]); SDL_Window* gWindow = NULL; SDL_Renderer* gRenderer = NULL; int main( int argc, char* args[] ) { SDL_Init(SDL_INIT_VIDEO); SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1"); gWindow = SDL_CreateWindow("Muhammad Hilmi Bin Sazali Q1771290", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN); gRenderer = SDL_CreateRenderer(gWindow, -1, SDL_RENDERER_ACCELERATED); SDL_SetRenderDrawColor(gRenderer, 0xFF, 0xFF, 0xFF, 0xFF); // 初始化第一个方块 std::vector<Square> squares; Square firstSquare = { {SCREEN_WIDTH / 4, SCREEN_HEIGHT / 4, SQUARE_SIZE, SQUARE_SIZE}, COLORS[0] }; squares.push_back(firstSquare); bool quit = false; SDL_Event e; while( !quit ) { // 处理事件 while( SDL_PollEvent( &e ) != 0 ) { if( e.type == SDL_QUIT ) quit = true; else if (e.type == SDL_KEYDOWN) { switch (e.key.keysym.sym) { case SDLK_LEFT: // 最少保留1个方块 if (squares.size() > 1) { squares.pop_back(); } break; case SDLK_RIGHT: // 最多20个方块 if (squares.size() < MAX_SQUARES) { Square newSquare; // 新方块位置做偏移,避免完全重叠,可按需调整 int offset = squares.size() * 20; newSquare.rect.x = (SCREEN_WIDTH / 4 + offset) % (SCREEN_WIDTH - SQUARE_SIZE); newSquare.rect.y = (SCREEN_HEIGHT / 4 + offset) % (SCREEN_HEIGHT - SQUARE_SIZE); newSquare.rect.w = SQUARE_SIZE; newSquare.rect.h = SQUARE_SIZE; // 轮询取颜色 newSquare.color = COLORS[squares.size() % COLOR_COUNT]; squares.push_back(newSquare); } break; } } } // 渲染逻辑 SDL_SetRenderDrawColor( gRenderer, 0xFF, 0xFF, 0xFF, 0xFF ); SDL_RenderClear( gRenderer ); // 遍历渲染所有方块 for (const auto& sq : squares) { SDL_SetRenderDrawColor(gRenderer, sq.color.r, sq.color.g, sq.color.b, sq.color.a); SDL_RenderFillRect(gRenderer, &sq.rect); } SDL_RenderPresent( gRenderer ); } // 资源释放 SDL_DestroyRenderer(gRenderer); SDL_DestroyWindow(gWindow); gWindow = NULL; gRenderer = NULL; IMG_Quit(); SDL_Quit(); return 0; }
功能说明
- 启动后默认显示第一个橙色方块
- 按下右方向键:最多新增到20个方块,每个方块颜色按预设池轮询,位置自动偏移不会完全重叠
- 按下左方向键:从最新生成的方块开始删除,直到只剩1个初始方块为止
内容的提问来源于stack exchange,提问作者Hilmi Blaze
相关产品推荐
相关产品推荐

