C++ 如何使用SDL C+;在win32窗口中设置GUI按钮+;?

C++ 如何使用SDL C+;在win32窗口中设置GUI按钮+;?,c++,sdl,C++,Sdl,我是SDL和游戏开发的新手。我想制作一个游戏,我需要在游戏窗口中放置一个“开始”按钮。那么有谁能帮我做这件事吗? 没有鼠标事件在整个屏幕上我只想创建一个按钮,点击它,我可以在哪里插入按钮的代码? 这是我的代码: int main (int argc, char *argv[]){ int quit = 0; SDL_Init(SDL_INIT_VIDEO); SDL_Window* window = NULL; window = SDL_CreateWindow

我是SDL和游戏开发的新手。我想制作一个游戏,我需要在游戏窗口中放置一个“开始”按钮。那么有谁能帮我做这件事吗? 没有鼠标事件在整个屏幕上我只想创建一个按钮,点击它,我可以在哪里插入按钮的代码? 这是我的代码:

 int main (int argc, char *argv[]){
    int quit = 0;
    SDL_Init(SDL_INIT_VIDEO);
    SDL_Window* window = NULL;
    window = SDL_CreateWindow("Snaykie v1.0",350, 150, 800, 500,    SDL_WINDOW_SHOWN);
    if (window == NULL){
        std::cout << "Can not open the game" << std::endl;
        return 0;
    }
    SDL_Renderer* renderer = NULL;
    renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
    SDL_Event* evt = new SDL_Event();

    SDL_Texture* txt = NULL;
    txt = IMG_LoadTexture(renderer, "mainview.bmp");

    SDL_Rect rct;
    rct.x = 0 ;
    rct.y = 0;
    rct.h = 500;
    rct.w = 800;

    SDL_Surface *button = NULL;

    while (!quit && evt->type != SDL_QUIT){
        SDL_PollEvent(evt);
       SDL_RenderClear(renderer);
       SDL_RenderCopy(renderer, txt, NULL, &rct);
       SDL_RenderPresent(renderer);
    }
    SDL_DestroyWindow(window);
    SDL_DestroyRenderer(renderer);
    delete evt;
    return 0;
}
intmain(intargc,char*argv[]){
int-quit=0;
SDL_Init(SDL_Init_视频);
SDL_Window*Window=NULL;
窗口=SDL_创建窗口(“Snaykie v1.0”,显示350、150、800、500,SDL_窗口);
如果(窗口==NULL){

std::cout没有一两行那么简单。下面是一个例子:

#include <SDL2/SDL.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>

typedef struct {
    SDL_Rect draw_rect;    // dimensions of button
    struct {
        Uint8 r, g, b, a;
    } colour;

    bool pressed;
} button_t;

static void button_process_event(button_t *btn, const SDL_Event *ev) {
    // react on mouse click within button rectangle by setting 'pressed'
    if(ev->type == SDL_MOUSEBUTTONDOWN) {
        if(ev->button.button == SDL_BUTTON_LEFT &&
                ev->button.x >= btn->draw_rect.x &&
                ev->button.x <= (btn->draw_rect.x + btn->draw_rect.w) &&
                ev->button.y >= btn->draw_rect.y &&
                ev->button.y <= (btn->draw_rect.y + btn->draw_rect.h)) {
            btn->pressed = true;
        }
    }
}

static bool button(SDL_Renderer *r, button_t *btn) {
    // draw button
    SDL_SetRenderDrawColor(r, btn->colour.r, btn->colour.g, btn->colour.b, btn->colour.a);
    SDL_RenderFillRect(r, &btn->draw_rect);

    // if button press detected - reset it so it wouldn't trigger twice
    if(btn->pressed) {
        btn->pressed = false;
        return true;
    }
    return false;
}

int main (int argc, char *argv[]){
    int quit = 0;
    SDL_Init(SDL_INIT_VIDEO);
    SDL_Window* window = NULL;
    window = SDL_CreateWindow("",350, 150, 800, 500,    SDL_WINDOW_SHOWN);
    if (window == NULL){
        fprintf(stderr, "create window failed: %s\n", SDL_GetError());
        return 1;   // 'error' return status is !0. 1 is good enough
    }

    SDL_Renderer* renderer = NULL;
    renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
    if(!renderer) {   // renderer creation may fail too
        fprintf(stderr, "create renderer failed: %s\n", SDL_GetError());
        return 1;
    }

    SDL_Texture* txt = NULL;

    SDL_Rect rct;
    rct.x = 0 ;
    rct.y = 0;
    rct.h = 500;
    rct.w = 800;

    // button state - colour and rectangle
    button_t start_button = {
        .colour = { .r = 255, .g = 255, .b = 255, .a = 255, },
        .draw_rect = { .x = 128, .y = 128, .w = 128, .h = 128 },
    };

    enum {
        STATE_IN_MENU,
        STATE_IN_GAME,
    } state = 0;

    while(!quit) {
        SDL_Event evt;    // no need for new/delete, stack is fine

        // event loop and draw loop are separate things, don't mix them
        while(SDL_PollEvent(&evt)) {
            // quit on close, window close, or 'escape' key hit
            if(evt.type == SDL_QUIT ||
                    (evt.type == SDL_WINDOWEVENT && evt.window.event == SDL_WINDOWEVENT_CLOSE) ||
                    (evt.type == SDL_KEYDOWN && evt.key.keysym.sym == SDLK_ESCAPE)) {
                quit = 1;
            }

            // pass event to button
            button_process_event(&start_button, &evt);
        }

        SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
        SDL_RenderClear(renderer);

//      SDL_RenderCopy(renderer, txt, NULL, &rct);

        if(state == STATE_IN_MENU) {
            if(button(renderer, &start_button)) {
                printf("start button pressed\n");
                state = STATE_IN_GAME;   // state change - button will not be drawn anymore
            }
        } else if(state == STATE_IN_GAME) {
            /* your game logic */
        }

        SDL_RenderPresent(renderer);
    }
    SDL_DestroyWindow(window);
    SDL_DestroyRenderer(renderer);
    return 0;
}
#包括
#包括
#包括
#包括
类型定义结构{
SDL_Rect draw_Rect;//按钮的尺寸
结构{
Uint8 r,g,b,a;
}颜色;
布尔压榨;
}按钮t;
静态无效按钮处理事件(按钮t*btn,常数SDL\U事件*ev){
//通过设置“按下”,在按钮矩形内单击鼠标时作出反应
如果(ev->type==SDL_鼠标按钮){
如果(ev->button.button==SDL_按钮左&&
ev->button.x>=btn->draw_rect.x&&
ev->button.x draw\u rect.x+btn->draw\u rect.w)&&
ev->button.y>=btn->draw\u rect.y&&
ev->按钮y绘制(y+btn->绘制(h)){
btn->按下=真;
}
}
}
静态布尔按钮(SDL_渲染器*r,按钮*btn){
//绘图按钮
SDL_SetRenderDrawColor(r,btn->color.r,btn->color.g,btn->color.b,btn->color.a);
SDL_RenderFillRect(r,&btn->draw_rect);
//如果检测到按钮按下-重置它,使其不会触发两次
如果(btn->按下){
btn->按下=错误;
返回true;
}
返回false;
}
int main(int argc,char*argv[]){
int-quit=0;
SDL_Init(SDL_Init_视频);
SDL_Window*Window=NULL;
window=SDL_CreateWindow(显示“、350、150、800、500,SDL_窗口”);
如果(窗口==NULL){
fprintf(stderr,“创建窗口失败:%s\n”,SDL_GetError());
返回1;//“错误”返回状态为!0。1足够好了
}
SDL_渲染器*渲染器=NULL;
渲染器=SDL\u CreateRenderer(窗口,-1,SDL\u渲染器\u加速);
如果(!renderer){//渲染器创建也可能失败
fprintf(stderr,“创建渲染器失败:%s\n”,SDL_GetError());
返回1;
}
SDL_纹理*txt=NULL;
直接随机对照试验;
rct.x=0;
rct.y=0;
rct.h=500;
rct.w=800;
//按钮状态-颜色和矩形
按钮\u t启动\u按钮={
.color={.r=255.g=255.b=255.a=255,},
.draw_rect={.x=128.y=128.w=128.h=128},
};
枚举{
在_菜单中输入_,
在游戏中陈述,
}状态=0;
而(!退出){
SDL_Event evt;//不需要新建/删除,堆栈很好
//事件循环和绘制循环是分开的,不要混淆它们
while(SDL_事件和evt)){
//按“关闭”、“关闭窗口”或“退出”键退出
如果(evt.type==SDL\u退出||
(evt.type==SDL\u WINDOWEVENT&&evt.window.event==SDL\u WINDOWEVENT\u CLOSE)||
(evt.type==SDL\u KEYDOWN和&evt.key.keysym.sym==SDLK\u ESCAPE)){
退出=1;
}
//将事件传递到按钮
按钮\流程\事件(&start\按钮和evt);
}
SDL_SetRenderDrawColor(渲染器,0,0,0,255);
SDL_渲染器(渲染器);
//SDL_渲染复制(渲染器、txt、NULL和rct);
如果(状态==菜单中的状态){
if(按钮(渲染器和启动按钮)){
printf(“按下启动按钮”);
state=游戏中的state\u;//状态更改-按钮将不再绘制
}
}else if(state==游戏中的state){
/*你的游戏逻辑*/
}
SDL_渲染器呈现(渲染器);
}
SDL_窗口(窗口);
SDL_渲染器(渲染器);
返回0;
}
(它是C,但这里不是重点)。它绘制一个简单的恒定颜色矩形,并检测其上的点击。用纹理等替换矩形很简单;添加文本可能有点困难,使用SDL_ttf可能是最简单的方法

它可能会在许多方面得到改进,这取决于您想要得到什么。例如,它会在鼠标按钮按下时做出反应,而在某些情况下,您可能会希望对按钮释放做出反应,并跟踪按钮被按下和释放的位置。如果您有许多按钮,则在每个按钮上调用事件更新是很难看的,因此您可能希望为此提供不同的系统。您可能还希望具有非矩形按钮(例如,图像指定的某些形状)-这将需要完全不同的方法,因为您需要根据形状遮罩检查鼠标单击

我建议你看一看


作为旁注,不要新增SDL_事件,这绝对没有意义。

它并没有一两行那么简单。下面是一个例子:

#include <SDL2/SDL.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>

typedef struct {
    SDL_Rect draw_rect;    // dimensions of button
    struct {
        Uint8 r, g, b, a;
    } colour;

    bool pressed;
} button_t;

static void button_process_event(button_t *btn, const SDL_Event *ev) {
    // react on mouse click within button rectangle by setting 'pressed'
    if(ev->type == SDL_MOUSEBUTTONDOWN) {
        if(ev->button.button == SDL_BUTTON_LEFT &&
                ev->button.x >= btn->draw_rect.x &&
                ev->button.x <= (btn->draw_rect.x + btn->draw_rect.w) &&
                ev->button.y >= btn->draw_rect.y &&
                ev->button.y <= (btn->draw_rect.y + btn->draw_rect.h)) {
            btn->pressed = true;
        }
    }
}

static bool button(SDL_Renderer *r, button_t *btn) {
    // draw button
    SDL_SetRenderDrawColor(r, btn->colour.r, btn->colour.g, btn->colour.b, btn->colour.a);
    SDL_RenderFillRect(r, &btn->draw_rect);

    // if button press detected - reset it so it wouldn't trigger twice
    if(btn->pressed) {
        btn->pressed = false;
        return true;
    }
    return false;
}

int main (int argc, char *argv[]){
    int quit = 0;
    SDL_Init(SDL_INIT_VIDEO);
    SDL_Window* window = NULL;
    window = SDL_CreateWindow("",350, 150, 800, 500,    SDL_WINDOW_SHOWN);
    if (window == NULL){
        fprintf(stderr, "create window failed: %s\n", SDL_GetError());
        return 1;   // 'error' return status is !0. 1 is good enough
    }

    SDL_Renderer* renderer = NULL;
    renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
    if(!renderer) {   // renderer creation may fail too
        fprintf(stderr, "create renderer failed: %s\n", SDL_GetError());
        return 1;
    }

    SDL_Texture* txt = NULL;

    SDL_Rect rct;
    rct.x = 0 ;
    rct.y = 0;
    rct.h = 500;
    rct.w = 800;

    // button state - colour and rectangle
    button_t start_button = {
        .colour = { .r = 255, .g = 255, .b = 255, .a = 255, },
        .draw_rect = { .x = 128, .y = 128, .w = 128, .h = 128 },
    };

    enum {
        STATE_IN_MENU,
        STATE_IN_GAME,
    } state = 0;

    while(!quit) {
        SDL_Event evt;    // no need for new/delete, stack is fine

        // event loop and draw loop are separate things, don't mix them
        while(SDL_PollEvent(&evt)) {
            // quit on close, window close, or 'escape' key hit
            if(evt.type == SDL_QUIT ||
                    (evt.type == SDL_WINDOWEVENT && evt.window.event == SDL_WINDOWEVENT_CLOSE) ||
                    (evt.type == SDL_KEYDOWN && evt.key.keysym.sym == SDLK_ESCAPE)) {
                quit = 1;
            }

            // pass event to button
            button_process_event(&start_button, &evt);
        }

        SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
        SDL_RenderClear(renderer);

//      SDL_RenderCopy(renderer, txt, NULL, &rct);

        if(state == STATE_IN_MENU) {
            if(button(renderer, &start_button)) {
                printf("start button pressed\n");
                state = STATE_IN_GAME;   // state change - button will not be drawn anymore
            }
        } else if(state == STATE_IN_GAME) {
            /* your game logic */
        }

        SDL_RenderPresent(renderer);
    }
    SDL_DestroyWindow(window);
    SDL_DestroyRenderer(renderer);
    return 0;
}
#包括
#包括
#包括
#包括
类型定义结构{
SDL_Rect draw_Rect;//按钮的尺寸
结构{
Uint8 r,g,b,a;
}颜色;
布尔压榨;
}按钮t;
静态无效按钮处理事件(按钮t*btn,常数SDL\U事件*ev){
//通过设置“按下”,在按钮矩形内单击鼠标时作出反应
如果(ev->type==SDL_鼠标按钮){
如果(ev->button.button==SDL_按钮左&&
ev->button.x>=btn->draw_rect.x&&
ev->button.x draw\u rect.x+btn->draw\u rect.w)&&
ev->button.y>=btn->draw\u rect.y&&
ev->按钮y绘制(y+btn->绘制(h)){
btn->按下=真;
}
}
}
静态布尔按钮(SDL_渲染器*r,按钮*btn){
//绘图按钮
SDL_SetRenderDrawColor(r,btn->color.r,btn->color.g,btn->color.b,btn->color.a);
SDL_RenderFillRect(r,&btn->draw_rect);
//如果按钮pr