Reputation: 11
Iam soo newbie in SDL and games developement. I want to make a game and I need to put a "Start" button in the game's window. So please can anyone help me on how to do it? No mouse event in the whole screen I want just to create a button to click on it, where can I insert the code of the button? this is my code:
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;
}
Upvotes: 1
Views: 13060
Reputation: 18399
It's not as simple as one or two lines. Here is an example:
#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;
}
(it is C but it's not a point here). It draws a simple constant-colour rectangle and detects clicks on it. It is trivial to replace rectangle with e.g. texture; adding text may be a bit harder, using SDL_ttf is probably simplest way to do it.
It may be improved in many ways depending on what you wanted to get. E.g. it reacts on mouse button down, while in some cases you might want to react to button release, and track where it was pressed and released. And if you'll have many buttons, calling event update on each one is ugly, so you might want to come with different system for that. You might also want to have non-rectangular buttons (e.g. some shape specified by image) - that will need quite different approach as you'll need to check mouse click against shape mask.
I would recommend taking a look at imgui.
As a side note, don't new
SDL_Event
, there is absolutely no point in that.
Upvotes: 13