Table of Contents
1 SDL
SDLとはSimple DirectMedia Layerの略で、Cで実装されたマルチプラット フォームな描画ライブラリです。Simpleという名がつくように、単純な機能 に絞られておりますが、Windows、OSX、Linuxをサポートしており、SDLを用 いることでマルチプラットフォームなアプリを作成することができます。
SDLは1.2系と2.0系が存在し、インターフェースに差異があります。2.0系は 比較的新しい環境で導入されつつあります。 2.0系ではiOSとAndroidがサポートされており、新規にSDLを利用するユーザ は2.0系を選ぶべきでしょう。 SDLのWikiに1.2系から2.0系へ移植する為のガイドがあります。
SDL自体は機能が絞られている為、文字列描画等を実現する為には、SDL_ttf 等を利用する必要があります。
1.1 SDL_ttf
SDLを用いて文字列描画をサポートするライブラリです。
1.2 SDL_image
SDLではサポートしていない画像形式をサポートするライブラリです。PNGや JPEGを用いることができます。
1.3 その他
その他にも音源を扱うSDL_mixer等の各種プロジェクトが存在します。
2.2 ubuntu
ubuntu 12.04環境ではSDL1.2のパッケージしか入っていない為、SDL2.0をソー スコードからインストールする必要があります。
2.2.1 SDL 2.0
ビルドに必要なパッケージを取得します。ここではSDL1.2に必要なパッケー ジを取得しています。
sudo apt-get build-dep libsdl1.2-dev
SDL2.0のソースコードを取得し、インストールします。
wget https://www.libsdl.org/release/SDL2-2.0.3.tar.gz tar zxvf SDL2-2.0.3.tar.gz cd SDL2-2.0.3 ./configure make sudo make install
/usr/localディレクトリ配下にインストールされます。
2.2.2 SDL_ttf
SDL_ttfの場合は以下の通りです。
sudo apt-get build-dep libsdl-ttf2.0-dev wget https://www.libsdl.org/projects/SDL_ttf/release/SDL2_ttf-2.0.12.tar.gz tar zxvf SDL2_ttf-2.0.12.tar.gz cd SDL2_ttf-2.0.12 configure make sudo make install
2.2.3 SDL_image
SDL_imageの場合は以下の通りです。
sudo apt-get build-dep libsdl-image1.2-dev wget https://www.libsdl.org/projects/SDL_image/release/SDL2_image-2.0.0.tar.gz tar zxvf SDL2_image-2.0.0.tar.gz cd SDL2_image-2.0.0 ./configure make sudo make install
3 プログラムのビルド
3.1 osx
GCC/Clangに-frameworkオプションでSDL2、SDL2_ttf、SDL2_imageを指定し、 それぞれのインクルードパスを通してやる必要があります(インクルードパ スを指定する必要があるのは設定が不十分な為?)
c++ foo.cpp \ -framework SDL2 -framework SDL2_ttf -framework SDL2_image \ -I/Library/Frameworks/SDL2.framework/Headers/ \ -I/Library/Frameworks/SDL2_image.framework/Headers/ \ -I/Library/Frameworks/SDL2_ttf.framework/Headers/ foo.cpp
3.2 ubuntu
sdl2-configコマンドでCFLAGSと必要なライブラリのオプションを取得し、 それらをGCCに渡します。ただし、SDL2_ttfとSDL2_imageのライブラリは別 途指定する必要があります。
g++ foo.cpp `sdl2-config --cflags --libs` -lSDL2_ttf -lSDL2_image
3.3 osx / ubuntuで共用できるMakefile
unameコマンドでosxとlinuxのCXXFLAGSを切り替えるMakefileの例は以下の 通りです。
TARGET := $(patsubst %.cpp,%,$(wildcard *.cpp)) UNAME := $(shell uname) ifeq ($(UNAME),Linux) CXXFLAGS += $(shell sdl2-config --cflags --libs) CXXFLAGS += -lSDL2_ttf -lSDL2_image else CXXFLAGS += -framework SDL2 -framework SDL2_ttf -framework SDL2_image CXXFLAGS += -I/Library/Frameworks/SDL2.framework/Headers/ CXXFLAGS += -I/Library/Frameworks/SDL2_image.framework/Headers/ CXXFLAGS += -I/Library/Frameworks/SDL2_ttf.framework/Headers/ endif CXXFLAGS += $(EXTRA_CXXFLAGS) $(TARGET): $(CXX) -o $@ $@.cpp $(CXXFLAGS) all: $(TARGET) clean: rm -rf $(TARGET)
4 サンプル
PNG画像と文字列を表示するサンプルを以下に記載します。別途PNG画像のファ イルとフォントのファイルが必要となります。
#include <iostream> #include <SDL.h> #include <SDL_ttf.h> #include <SDL_image.h> #define SAMPLE_SPRITE "sample.png" #define SAMPLE_FONT "sazanami-gothic.ttf" #define SAMPLE_FONT_SIZE (32) #define SAMPLE_STRING "Sample string" static SDL_Window *gWindow; static int gWindowWidth; static int gWindowHeight; static SDL_Renderer *gRenderer; static SDL_RWops *gFontRWops; static TTF_Font *gFont; static int gFontWidth; static int gFontHeight; static SDL_Color gFontColor = { 255, 255, 0 }; static bool initializeFont() { gFontRWops = SDL_RWFromFile(SAMPLE_FONT, "rb"); if (gFontRWops == nullptr) return false; gFont = TTF_OpenFontRW(gFontRWops, 0, SAMPLE_FONT_SIZE); if (gFont == nullptr) goto err1; if (TTF_SizeUTF8(gFont, "a", &gFontWidth, &gFontHeight) < 0) goto err2; return true; err2: TTF_CloseFont(gFont); err1: SDL_RWclose(gFontRWops); return false; } static void finalizeFont() { TTF_CloseFont(gFont); SDL_RWclose(gFontRWops); } static bool initialize(int width, int height) { if (SDL_Init(SDL_INIT_EVERYTHING) < 0) return false; if (TTF_Init() < 0) goto err1; if (SDL_CreateWindowAndRenderer(width, height, 0, &gWindow, &gRenderer) < 0) goto err2; if (!initializeFont()) goto err3; SDL_GetWindowSize(gWindow, &gWindowWidth, &gWindowHeight); return true; err3: SDL_DestroyRenderer(gRenderer); SDL_DestroyWindow(gWindow); err2: TTF_Quit(); err1: SDL_Quit(); return false; } static void finalize() { finalizeFont(); SDL_DestroyRenderer(gRenderer); SDL_DestroyWindow(gWindow); TTF_Quit(); SDL_Quit(); } SDL_Texture *createSprite(const char *spriteName) { SDL_RWops *rwops; SDL_Surface *surface; SDL_Texture *texture; rwops = SDL_RWFromFile(spriteName, "rb"); if (rwops == nullptr) return nullptr; surface = IMG_LoadPNG_RW(rwops); if (surface == nullptr) goto err; texture = SDL_CreateTextureFromSurface(gRenderer, surface); SDL_FreeSurface(surface); err: SDL_RWclose(rwops); return texture; } SDL_Texture *createString(const char *string) { SDL_Surface *surface; SDL_Texture *texture; surface = TTF_RenderUTF8_Solid(gFont, string, gFontColor); if (surface == nullptr) { std::cerr << "utf8" << std::endl; return nullptr; } texture = SDL_CreateTextureFromSurface(gRenderer, surface); SDL_FreeSurface(surface); return texture; } int main() { SDL_Texture *sprite, *string; int ret = 1; if (!initialize(400, 400)) { std::cerr << "Initialize error" << std::endl; return 1; } sprite = createSprite(SAMPLE_SPRITE); if (sprite == nullptr) { std::cerr << "Sprite error" << std::endl; goto err1; } string = createString(SAMPLE_STRING); if (string == nullptr) { std::cerr << "String error" << std::endl; goto err2; } SDL_RenderClear(gRenderer); SDL_RenderCopy(gRenderer, sprite, nullptr, nullptr); SDL_RenderCopy(gRenderer, string, nullptr, nullptr); SDL_RenderPresent(gRenderer); SDL_Delay(10000); ret = 0; SDL_DestroyTexture(string); err2: SDL_DestroyTexture(sprite); err1: finalize(); return ret; }