Building Interactive Buttons

Creating Image Buttons in SDL

Can I create a button with an image instead of a solid color?

Abstract art representing computer programming

Absolutely! Creating buttons with images instead of solid colors can greatly enhance the visual appeal of your UI. Let's modify our Button class to support image-based buttons using SDL.

First, we'll need to include the SDL_image library to handle image loading:

#include <SDL.h>
#include <SDL_image.h>
#include <string>

class ImageButton : public Button {
public:
  ImageButton(int x, int y, int w, int h,
              const std::string& imagePath)
    : Button{x, y, w, h},
      imagePath{imagePath} { LoadImage(); }

  ~ImageButton() {
    if (buttonImage) {
      SDL_FreeSurface(buttonImage);
    }
  }

  void Render(SDL_Surface* Surface) override {
    if (buttonImage) {
      SDL_BlitScaled(buttonImage, nullptr,
                     Surface, &Rect);
    } else { Button::Render(Surface); }
  }

private:
  void LoadImage() {
    buttonImage = IMG_Load(imagePath.c_str());
    if (!buttonImage) {
      std::cerr << "Failed to load image: "
          << IMG_GetError() << '\n';
    }
  }

  std::string imagePath;
  SDL_Surface* buttonImage{nullptr};
};

In this ImageButton class, we're loading an image file in the constructor and using it in the Render() method. If the image fails to load, it falls back to the default solid color rendering.

To use this new ImageButton class:

#include <SDL.h>
#include <SDL_image.h>

int main(int argc, char* argv[]) {
  SDL_Init(SDL_INIT_VIDEO);
  IMG_Init(IMG_INIT_PNG);

  Window GameWindow;
  ImageButton PlayButton{
      50, 50, 100, 50,
      "assets/play_button.png"};
  ImageButton QuitButton{
      50, 120, 100, 50,
      "assets/quit_button.png"};

  // Main game loop
  SDL_Event Event;
  bool shouldQuit{false};
  while (!shouldQuit) {
    while (SDL_PollEvent(&Event)) {
      PlayButton.HandleEvent(Event);
      QuitButton.HandleEvent(Event);
      if (Event.type == SDL_QUIT) {
        shouldQuit = true;
      }
    }
    GameWindow.Render();
    PlayButton.Render(GameWindow.GetSurface());
    QuitButton.Render(GameWindow.GetSurface());
    GameWindow.Update();
  }

  IMG_Quit();
  SDL_Quit();
  return 0;
}

This code creates two image buttons: a "Play" button and a "Quit" button, each with its own image.

Remember to handle different button states (normal, hovered, pressed) by either loading multiple images or modifying the button image at runtime. For example:

class ImageButton : public Button {
public:
  ImageButton(int x, int y, int w, int h,
              const std::string& normalImage,
              const std::string& hoverImage,
              const std::string& pressedImage)
    : Button{x, y, w, h} {
    LoadImages(normalImage, hoverImage,
               pressedImage);
  }

  // ... rest of the class ...

private:
  void LoadImages(const std::string& normal,
                  const std::string& hover,
                  const std::string& pressed) {
    normalImage = IMG_Load(normal.c_str());
    hoverImage = IMG_Load(hover.c_str());
    pressedImage = IMG_Load(pressed.c_str());
    // Error handling...
  }

  SDL_Surface* normalImage{nullptr},
             * hoverImage{nullptr},
             * pressedImage{nullptr};
};

With these modifications, you can create visually appealing image-based buttons in your SDL application!

Answers to questions are automatically generated and may not have been reviewed.

sdl2-promo.jpg
Part of the course:

Game Dev with SDL2

Learn C++ and SDL development by creating hands on, practical projects inspired by classic retro games

Free, unlimited access

This course includes:

  • 53 Lessons
  • 100+ Code Samples
  • 91% Positive Reviews
  • Regularly Updated
  • Help and FAQ
Free, Unlimited Access

Professional C++

Comprehensive course covering advanced concepts, and how to use them on large-scale projects.

Screenshot from Warhammer: Total War
Screenshot from Tomb Raider
Screenshot from Jedi: Fallen Order
Contact|Privacy Policy|Terms of Use
Copyright © 2024 - All Rights Reserved