Coder Social home page Coder Social logo

libsdl2pp / libsdl2pp Goto Github PK

View Code? Open in Web Editor NEW
552.0 30.0 88.0 1.15 MB

C++ bindings/wrapper for SDL2

Home Page: https://sdl2pp.amdmi3.ru

License: Other

CMake 1.78% C++ 98.15% Makefile 0.07%
sdl c-plus-plus gamedev graphics sdl-mixer sdl-ttf sdl-image sdl2

libsdl2pp's Introduction

libsdl2pp packaging status

CI Github commits (since latest release)

libSDL2pp

This library provides C++ bindings/wrapper for SDL2 and satellite libraries.

Synopsis

try {
  using namespace SDL2pp;

  // Init SDL; will be automatically deinitialized when the object is destroyed
  SDL sdl(SDL_INIT_VIDEO | SDL_INIT_AUDIO);

  // Likewise, init SDL_ttf library
  SDLTTF sdl_ttf;

  // Straightforward wrappers around corresponding SDL2 objects
  // These take full care of proper object destruction and error checking
  Window window("libSDL2pp demo",
                SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
                640, 480, SDL_WINDOW_RESIZABLE);
  Renderer renderer(window, -1, SDL_RENDERER_ACCELERATED);
  Texture sprite1(renderer, SDL_PIXELFORMAT_ARGB8888,
                            SDL_TEXTUREACCESS_STATIC, 16, 16);
  Texture sprite2(renderer, "sprite.png"); // SDL_image support

  Font font("Vera.ttf", 20); // SDL_ttf font

  // Initialize audio mixer
  Mixer mixer(MIX_DEFAULT_FREQUENCY, MIX_DEFAULT_FORMAT, MIX_DEFAULT_CHANNELS, 4096);

  Chunk sound("effect.ogg"); // OGG sound file

  // Create texture from surface containing text rendered by SDL_ttf
  Texture text(renderer, font.RenderText_Solid("Hello, world!",
               SDL_Color{255, 255, 255, 255}));

  unsigned char pixels[16 * 16 * 4];

  // Note proper constructor for Rect
  sprite1.Update(Rect(0, 0, 16, 16), pixels, 16 * 4);

  // Most setter methods are chainable
  renderer.SetLogicalSize(640, 480).SetDrawColor(0, 16, 32).Clear();

  // Also note a safe way to specify null rects and points
  renderer.Copy(sprite1, NullOpt, NullOpt);

  // There are multiple convenient ways to construct e.g. a Rect;
  // Objects provide extensive set of getters
  renderer.Copy(text, NullOpt, Rect(Point(0, 0), text.GetSize()));

  // Copy() is overloaded, providing access to both SDL_RenderCopy and SDL_RenderCopyEx
  renderer.Copy(sprite2, NullOpt, NullOpt, 45.0);

  renderer.Present();

  // Play our sound one time on a first available mixer channel
  mixer.PlayChannel(-1, sound);

  // You can still access wrapped C SDL types
  SDL_Renderer* sdl_renderer = renderer.Get();

  // Of course, C SDL2 API is still perfectly valid
  SDL_Delay(2000);

  // All SDL objects are released at this point or if an error occurs
} catch (SDL2pp::Exception& e) {
  // Exception stores SDL_GetError() result and name of function which failed
  std::cerr << "Error in: " << e.GetSDLFunction() << std::endl;
  std::cerr << "  Reason: " << e.GetSDLError() << std::endl;
} catch (std::exception& e) {
  // This also works (e.g. "SDL_Init failed: No available video device")
  std::cerr << e.what() << std::endl;
}

There's also more elaborate tutorial.

Features

Currently, the library provides wrapper classes for

  • SDL
    • Library initialization/deinitialization
    • Audio
      • Audio device
      • WAV-related functions
      • SDL_AudioSpec
    • Graphics
      • SDL_Point
      • SDL_Rect
      • SDL_Renderer
      • SDL_Surface
      • SDL_Texture
      • SDL_Window
    • I/O
      • SDL_RWops
  • SDL_image
    • Library initialization/deinitialization
    • Loading functions integrated into Texture and Surface
  • SDL_mixer
    • Library initialization/deinitialization
    • Sound sample handling (Mix_Chunk)
    • Music handling (Mix_Music)
    • Mixer class which encapsulates device handling and all playback functions
  • SDL_ttf
    • Library initialization/deinitialization
    • TTF_Font (all functions covered)

each with a subset of methods corresponding to SDL functions working with specific types of objects and, in some cases, additional convenience methods. These classes support:

  • RAII-style initialization and destruction, automatic resource lifetime control (you no longer need to care of manually freeing your stuff)
  • Total error checking: exceptions are thrown if any SDL function fails. Exception itself allows retrieval of SDL error string (you no longer need to manually check return code after each function call)
  • Method overloading, default arguments, method chaining allow shorter and cleaner code
  • Move semantics support, which allow you to store SDL objects in containers and pass/return them by value without noticeable overhead

Set of functional extensions above SDL2 is also available:

  • RWops adapters for C++ containers and streams
  • Optional object to safely handle values which may not be present, (for which SDL2 usually uses NULL pointers)
  • Number of additional methods and operator support for Point and Rect

Building

Dependencies:

To build standalone version:

cmake .
cmake --build .

Following variables may be supplied to CMake to affect build:

  • SDL2PP_WITH_IMAGE - enable SDL_image support (default ON)
  • SDL2PP_WITH_MIXER - enable SDL_mixer support (default ON)
  • SDL2PP_WITH_TTF - enable SDL_ttf support (default ON)
  • SDL2PP_WITH_EXAMPLES - enable building example programs (only for standalone build, default ON)
  • SDL2PP_WITH_TESTS - enable building tests (only for standalone build, default ON)
  • SDL2PP_STATIC - build static library instead of shared (only for standalone build, default OFF)
  • SDL2PP_ENABLE_LIVE_TESTS - enable tests which require X11 and/or audio device to run (only for standalone build, default ON)

Installation

To install the library system-wide, run:

cmake .
cmake --build .
cmake --install .

You can change installation prefix with CMAKE_INSTALL_PREFIX cmake variable:

cmake -DCMAKE_INSTALL_PREFIX=/usr/local .
cmake --build .
cmake --install .

SDL2pp installs pkg-config file, so it can be used with any build system that interacts with pkg-config, including CMake, meson and GNU Autotools. It also installs CMake module file, which can be used from CMake directly:

find_package(SDL2pp REQUIRED)

target_link_libraries(mytarget SDL2pp::SDL2pp)

Bundling

The library is easy to integrate into other CMake projects (and as the library has no stable API yet, this way of using it is still recommended).

Just place the library into dedicated directory in your project (for example, extlib/libSDL2pp) and add

set(SDL2PP_WITH_IMAGE ON) # if you need SDL_image support
set(SDL2PP_WITH_MIXER ON) # if you need SDL_mixer support
set(SDL2PP_WITH_TTF ON) # if you need SDL_ttf support
add_subdirectory(extlib/libSDL2pp)

into your core CMakeLists.txt. This will act similar to how find_package usually does, and will provide SDL2pp::SDL2pp target for your project. You will then be able it as usual:

target_link_libraries(mytarget SDL2pp::SDL2pp)

If bundled, libSDL2pp does not build examples and becomes a static library. See hoverboard project as an example of using both bundled and systemwide SDL2pp.

Completeness

The library still doesn't cover all aspects of SDL2, and the development is generally guided by the author's needs and interest without a goal for covering all SDL2 functions as soon as possible. However, if you need specific bits which are not yet implemented in the library, feel free to drop an issue. Patches are of course more than welcome.

It should be noted, however, that I currently do not plan to implement any wrappers over non object-oriented SDL2 code, as these will not bring any benefits over using plain C API. E.g. I see no point in implementing SDL2pp::Delay() as it won't bring any convenience over SDL_Delay().

The same strongly applies to the SDL2 bits which duplicate C++17 standard library, e.g. threads and atomic ops.

Users

Projects using libSDL2pp:

  • fontbm - Command line font generator, compatible with BMFont
  • hoverboard-sdl - Desktop version of xkcd 1608 "Hoverboard" game
  • neopedersia - Nexus Wars style game
  • OpenDaed - Libre reimplementation of The Daedalus Encounter game
  • OpenStrike - Libre reimplementation of Jungle and Desert Strike games
  • osmview - Desktop OpenStreetMap viewer
  • planetonomy - Old-school platformer/exploration game with CGA graphics

WWW

Author

Contributors

License

libSDL2pp comes under zlib license, the same license as SDL2. See COPYING.txt.

libsdl2pp's People

Contributors

aargonian avatar amdmi3 avatar csoren avatar ilyapopov avatar kumar8600 avatar lowest0ne avatar ooxi avatar vraiment avatar whoozle avatar xzxzzxzxzca avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

libsdl2pp's Issues

Surface constructor parameters

flags parameter is unused and should be set to zero. Do we need this parameter at all?

Mask parameters can take zero values meaning "default". Thus, the signature could be:

Surface::Surface(int width, int height, int depth, 
    Uint32 Rmask = 0, Uint32 Gmask = 0, Uint32 Bmask = 0, Uint32 Amask = 0);

Of course, I understand that changing the signature is a breaking change and not acceptable, thus an alternative overload can be added?

Texture-based text renderer

Using SDL_ttf to render dynamic text in the game is ineffective, as each string is first rendered by freetype onto Surface (slow!), then surface data is converted into Texture and uploaded to GPU (also slow!). A facility is needed to cache glyphs on a texture and render them without calling SDL_ttf code. Texture atlas support is needed for this (#37)

Wav: empty ctor and ctor from existing data

Provide constructors for Wav:
Wav(nsamples, spec) to create silence of specified format for later filling and Wav(data, nsamples, spec) to load audio data from existing buffer.

virtualize Renderer class

Currently Renderer class only provides virtual destructor. It would be much more flexible, however, if more of its functions were virtual.

For example, I need a renderer for low-resolution game which automatically scales its 320x200 resolutions onto a bigger render area. This can be done inside SDL with SetViewport and SetScale, however this method has drawbacks:

  • SetScale will affect horizontal and vertical lines (e.g. with 2x scale, vertical line will be 2 pixels wide), while diagonal lines won't be affected
  • SetScale works BEFORE SetViewport, so to place scaled 320x200 screen in your window you'll need to think in scaled coords

Alternative methods include:

  • Scale all rendering operations instead (sprites will be scaled, lines will be not)
  • Render onto intermediate target, then place it on the screen (both sprites and lines will be scaled)

Both methods may be done transparently with custom Renderer derivative which overrides some operations, however for that to work really transparently, base Renderer functions should be virtual. virtual call has an overhead, but it is incomparably small to operations that Renderer class performs (heavyweight opengl operations which go through multiple layers of library calls). Performance testing would be nice though.

More (and more consistent) Rect side and corner getters/setters

Drop GetX2/GetY2, instead implement:

  • Get{Left,Right,Top,Bottom}
  • Set{Left,Right,Top,Bottom} (scaling size correspondingly)
  • Set{TopLeft,TopRight,BottomLeft,BottomRight} (scaling size correspondingly)
  • Move{Left,Right,Top,Bottom,TopLeft,TopRight,BottomLeft,BottomRight} (not changing size)

FillCopy method

Which automatically calls number of Copy() to fill specific rectangle with texture

c++1y support

With the latest libSDL2pp changes, it is obvious that we would benefit from C++1y features, for example: [[deprecated]] attribute and experimental/optional header. It's not easy, however, as using -std=c++1y would impose the same requirement on client code, but without it named features will be inaccessible (with the exception of that [[deprecated]] is available on clang with -std=c++11). Probably an option for c++1y should be added + automatic checks for optional and deprecated which run regardless of set standard.

C++11 move semantics support

It'd be useful to properly implement C++11 move semantics. Will be easy, but the question is how empty (e.g. moved from) objects should behave:

  • be a no-op (impossible for some operations, e.g. Point::GetX())
  • throw exceptions
  • die with assert()'s which are only compiled in in debug version
  • die with assert()'s which are always compiled in
  • any of above, selectable during library compilation

Complete SDL_ttf-related documentation

Currently mixer documentation refer to SDL_ttf website. This is inconvenient, copy function descriptions here instead. While at it, recheck completeness of \throw items.

Asserts all over the place

Asserts checking that contained pointers are not null (e.g. misuse of moved-from objects) would be useful. Also, NDEBUG define should be set for the release build.

Documentation improvements

  • Document remaining classes, namely custom RWops
  • Document deleted constructors and assigments
  • Proofread generated documentation
  • Run all documentation through spelling checker
  • Add title page
  • Add travis check for doxygen warnings
  • Add in/out specifiers for function params

CustomRWops refactoring

CustomRWops interface is imperfect:

RWops rw(MyCustomRWops(arg1, arg2));

Ideally, there should be a single RWops class, which works with SDL_rwops by default, but allows deriving custom classes with redefined read/write/close/seek operations. I remember some problems which didn't let me implement it this way from the start, maybe they could be solved on the second try.

If that's still impossible, above mentioned constructor should be at least turned into something like:

RWops rw = RWops::FromCustom<MyCustomRWops>(arg1, arg2);

Longer, but clearer and doesn't require MyCustomRWops to be movable or copyable.

Optional support

As suggested by @rianhunter in #13, it'd be nice to move "valid" property out of Rect and Point into seprate "optional" entity. I plan to take implementation from libc++ as more readable.

experimental/optional is not detected and used even if present

This happens for both gcc/libstdc++ and clang++/libc++, because experimental/optional is only in C++14 standard and not in C++11, and both gcc and clang refuse to compile the test program with -std=c++11 flag.

Tested on Ubuntu 14.10 with gcc 4.9.1 and clang 3.5.0.

And the same with [[deprecated]].

I see two solutions:

  • Use -std=c++14 flag when possible.
  • Since optional is bundled anyway always use the bundled version.

Complete SDL_mixer-related documentation

Currently mixer documentation refer to SDL_mixer website. This is inconvenient, copy function descriptions here instead. While at it, recheck completeness of \throw items.

Texture atlas support

This is far beyond SDL scope, however such facility is very useful in the games are absolutely required for effective text renderer (see #38)

Cover all functions with tests and/or demos

Not everything can be tested (for example, audio), but everything should be at least covered by a demo. cppcheck helps finding functions which are not used anywhere.

cppcheck -q --enable=unusedFunction . 2>&1 | sort

  • AudioDevice.cc (5 left)
  • AudioSpec.cc (1 left)
  • Exception.cc (1 left)
  • Font.cc (25 left)
  • Mixer.cc (9 left)
  • RWops.cc (4 left)
  • Renderer.cc (16 left)
  • SDL.cc (3 left)
  • SDLImage.cc (2 left)
  • Surface.cc (10 left)
  • SurfaceLock.cc (3 left)
  • Texture.cc (2 left)
  • Window.cc (24 left)

SliceRWops

RWops which take another RWops and a range, and limit I/O operations with that range

std::istream support

Several classes have the ability to open files using filenames. It would be nice to also have support opening files using std::istream.

Provide a convenient way to convert to Surface's pixel format

Suppose I want to fill a rectangle with some color. FillRect member function expects a color in surface's format. There is conversion function, SDL_MapRGB, but it expects SDL_PixelFormat*. Surface::GetFormat, however, returns only SDL_PixelFormat::format, not the whole structure.

What is the preferred way to convert RGB values to surface's color that FillRect expects?

surface.FillRect(rect, SDL_MapRGB(???, r, g, b));

Shall a method be provided to convert RGB to color value:

Surface::MapRGB(Uint8 r, Uint8 g, Uint8 b);

Or even a FillRect overload taking RGB values?

SDL_Image initialization wrapper

I.e. IMG_Init and IMG_Quit similar to SDL2pp::SDL.

IMG_Init may load preload libraries for specifiic format support on start to save loading time, and IMG_Quit cleans things up (e.g. for valgrind).

Implement Texture locking

In addition to Lock/Unlock methodes, there could be a separate Lock object which does Lock in constructor and Unlock in destructor, and handles the duration of locking automatically.

I can't pass test.

$ ./gui_rendering 
PASSED: pixels.Test(0, 0, 1, 2, 3)
PASSED: pixels.Test3x3(10, 10, 0x020, 255, 128, 0)
PASSED: pixels.Test3x3(20, 20, 0x020, 0, 255, 128)
PASSED: pixels.Test3x3(30, 30, 0x020, 128, 0, 255)
PASSED: pixels.Test3x3(10, 20, 0x222, 255, 128, 0)
PASSED: pixels.Test3x3(20, 20, 0x222, 0, 255, 128)
PASSED: pixels.Test3x3(30, 20, 0x222, 128, 0, 255)
PASSED: pixels.Test3x3(10, 10, 0x032, 255, 128, 0)
PASSED: pixels.Test3x3(19, 10, 0x062, 255, 128, 0)
PASSED: pixels.Test3x3(10, 19, 0x230, 255, 128, 0)
FAILED: pixels.Test3x3(19, 19, 0x260, 255, 128, 0)
PASSED: pixels.Test3x3(30, 10, 0x032, 0, 255, 128)
PASSED: pixels.Test3x3(39, 10, 0x062, 0, 255, 128)
PASSED: pixels.Test3x3(30, 19, 0x230, 0, 255, 128)
FAILED: pixels.Test3x3(39, 19, 0x260, 0, 255, 128)
PASSED: pixels.Test3x3(10, 30, 0x032, 128, 0, 255)
PASSED: pixels.Test3x3(19, 30, 0x062, 128, 0, 255)
PASSED: pixels.Test3x3(10, 39, 0x230, 128, 0, 255)
FAILED: pixels.Test3x3(19, 39, 0x260, 128, 0, 255)
PASSED: pixels.Test3x3(30, 30, 0x032, 128, 192, 255)
PASSED: pixels.Test3x3(39, 30, 0x062, 128, 192, 255)
PASSED: pixels.Test3x3(30, 39, 0x230, 128, 192, 255)
FAILED: pixels.Test3x3(39, 39, 0x260, 128, 192, 255)
PASSED: pixels.Test3x3(10, 10, 0x033, 255, 128, 0)
PASSED: pixels.Test3x3(19, 10, 0x066, 255, 128, 0)
PASSED: pixels.Test3x3(10, 19, 0x330, 255, 128, 0)
PASSED: pixels.Test3x3(19, 19, 0x660, 255, 128, 0)
PASSED: pixels.Test3x3(30, 10, 0x033, 0, 255, 128)
PASSED: pixels.Test3x3(39, 10, 0x066, 0, 255, 128)
PASSED: pixels.Test3x3(30, 19, 0x330, 0, 255, 128)
PASSED: pixels.Test3x3(39, 19, 0x660, 0, 255, 128)
PASSED: pixels.Test3x3(10, 30, 0x033, 128, 0, 255)
PASSED: pixels.Test3x3(19, 30, 0x066, 128, 0, 255)
PASSED: pixels.Test3x3(10, 39, 0x330, 128, 0, 255)
PASSED: pixels.Test3x3(19, 39, 0x660, 128, 0, 255)
PASSED: pixels.Test3x3(30, 30, 0x033, 128, 192, 255)
PASSED: pixels.Test3x3(39, 30, 0x066, 128, 192, 255)
PASSED: pixels.Test3x3(30, 39, 0x330, 128, 192, 255)
PASSED: pixels.Test3x3(39, 39, 0x660, 128, 192, 255)
PASSED: pixels.Test3x3(10, 10, 0x033, 127, 127, 127)
PASSED: pixels.Test3x3(19, 10, 0x066, 127, 127, 127)
PASSED: pixels.Test3x3(10, 19, 0x330, 127, 127, 127)
PASSED: pixels.Test3x3(19, 19, 0x660, 127, 127, 127)
4 failures

What?

967fd8659ea164fe4c636714348e7c0f

Cursors support

Cursors (SDL_Cursor) are wrappable into SDL2pp object, however how SDL2 behaves when cursor is destroyed is poorly documented. This needs some investigation.

SDL_ttf support

This satellite library has many alloc/free-style managed objects, so it's nice candidate for SDL2pp wrapper

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.