SDL2ではAndroid向けのビルドもサポートされています。SDL2を用いたサンプルプログラムを動作させてみます。また簡単なテトリスをLinux上とAndroid上で動作させてみました。
1. SDL2のインストール
ダウンロードのページにOSX向けのdmgファイルがあります。
Ubuntu 12.04ではSDL1.2のパッケージはありますが、SDL2のパッケージはない ようです。下記手順でビルドできます。
$ sudo apt-get build-dep libsdl1.2debian $ wget http://www.libsdl.org/release/SDL2-2.0.2.tar.gz $ tar zxvf SDL2-2.0.2.tar.gz $ cd SDL2-2.0.2 $ ./configure # --prefixを指定しない場合は/usr/localにインストール $ make $ sudo make install
2. Android向けのサンプルプログラム
チュートリアルのページにサンプルが紹介されています。
Androidのサンプルのページではmain.cとimage.bmpというファイルを利用した サンプルが紹介されています。main.cはウィンドウを作成し、image.bmpを表 示するプログラムです。
3. OSX向けのビルド
ウィンドウのサイズを400x400に変更します。
$ diff -uprN main.c.org main.c --- main.c.org 2014-03-14 10:28:07.000000000 +0900 +++ main.c 2014-03-14 10:27:50.000000000 +0900 @@ -57,7 +57,7 @@ int main(int argc, char *argv[]) SDL_Window *window; SDL_Renderer *renderer; - if(SDL_CreateWindowAndRenderer(0, 0, 0, &window, &renderer) < 0) + if(SDL_CreateWindowAndRenderer(400, 400, 0, &window, &renderer) < 0) exit(2); Sprite sprite = LoadSprite("image.bmp", renderer);
コンパイルします(インクルードファイルのサーチパスは-Iで指定する以外の 方法はないのですかね?)。
clang -framework SDL2 main.c \ -I/Library/Frameworks/SDL2.framework/Headers/
実行するとウィンドウが開かれます。クリック等のイベントで終了します。
4. Android向けのビルド
こちらは先ほどとは異なり、ウィンドウサイズを指定する必要はありません。 SDL2のディレクトリに格納されているAndroid向けのビルド用ディレクトリを コピーして利用します。
$ cp -a SDL2-2.0.2/android-project . $ cd android-project
main.cをjni/srcディレクトリ配下に格納します。
$ cp ../main.c jni/src/
image.bmpをassetsディレクトリ配下に格納します。 SDL_loadBMPを実行すると assetsディレクトリ配下のファイルが読み込まれます。
$ mkdir assets $ cp ../image.bmp assets
main.cをビルド対象とする為にjni/src/Android.mkを編集します。
--- jni/src/Android.mk.org 2014-03-14 10:59:53.000000000 +0900 +++ jni/src/Android.mk 2014-03-14 11:03:00.000000000 +0900 @@ -10,7 +10,7 @@ LOCAL_C_INCLUDES := $(LOCAL_PATH)/$(SDL_ # Add your application source files here... LOCAL_SRC_FILES := $(SDL_PATH)/src/main/android/SDL_android_main.c \ - YourSourceHere.c + main.c LOCAL_SHARED_LIBRARIES := SDL2
SDLのコードを参照させる為、jniディレクトリ直下にSDLディレクトリのシン ボリックリンクを作成します。
$ cd jni $ ln -s ../../SDL2-2.0.2 SDL #SDLでないとビルドエラー $ cd ..
antでjniディレクトリ配下をビルドする為、custom_rules.xmlを追加します。
$ cat custom_rules.xml <?xml version="1.0" encoding="UTF-8"?> <project> <target name="-pre-build"> <exec executable="ndk-build" failonerror="true"/> </target> </project>
android update projectを実行し、antでビルドできるようにします。 -t 4は環境依存の値なので、各々のandroid list devicesで確認できるターゲッ トを指定して下さい。
$ android update project -p . -t 4 Updated project.properties Updated local.properties Updated file ./proguard-project.txt
android-mode.elでビルドすると以下の出力を得られます。SDL2を静的リンク する為、SDL2のビルドが実行されています。
-pre-build: Android NDK: WARNING: APP_PLATFORM android-16 is larger than android:minSdkVersion 10 in ./AndroidManifest.xml [armeabi] Compile thumb : SDL2 <= SDL.c [armeabi] Compile thumb : SDL2 <= SDL_assert.c [armeabi] Compile thumb : SDL2 <= SDL_error.c [armeabi] Compile thumb : SDL2 <= SDL_hints.c [armeabi] Compile thumb : SDL2 <= SDL_log.c [armeabi] Compile thumb : SDL2 <= SDL_audio.c <snip> [armeabi] SharedLibrary : libSDL2.so [armeabi] Install : libSDL2.so => libs/armeabi/libSDL2.so [armeabi] Compile thumb : main <= SDL_android_main.c [armeabi] Compile thumb : main <= main.c [armeabi] SharedLibrary : libmain.so [armeabi] Install : libmain.so => libs/armeabi/libmain.so <snip>
emulator上で実行すると以下の画面が表示されます。画面タッチ等のイベント で終了します。
5. まとめ
SDL2を利用することで、他環境で作成したSDL2のプログラムをそのまま流用で きます(SDLActivity.javaからJNI経由でmain関数が呼ばれる為)。 onResume/onPauseの際にデータ退避等はどうするかが気になるところ(仕組み は用意されているみたいです)。
6. 使ってみて気になった点
しばらく使ってみて気になった点を挙げてみます。
6.1. 環境依存
Androidの場合、main関数で作成したスレッドでSDL_EventPollやSDL_EventWaitによるイベントハンドリングが可能であるのに、OSX等では可能ではありませんでした。前処理に違いがでてくるのでしょうかね。#ifdef ANDROIDで切り分けする必要がありました。環境依存の原因が判明するまで色々試行錯誤が必要なので、スムーズに移植が可能とはいかないかもしれません。
6.2. 文字列の表示
SDL単体では文字列を画面に描画する機能がありません。そこでSDL_ttfを用いて、以下の処理を実装することになります。
- TTFファイルの読み込み
- 文字列の生成(例えば、文字列をファイルから読み込む処理)
- 文字列用のテクスチャの作成
- テクスチャの表示
描画の処理毎に3と4を実行するので、気になります。予めTTFファイル読み込み時に全ての文字データをテクスチャにしておきたいのですが、どんな文字列が来てもいいようにするのは難しいです(アルファベットなら可能ですけど、漢字まで含めるとできないような)。せいぜい、同じ文字列の表示はキャッシュしたテクスチャを使うとかが関の山ですかね。通常のGUIライブラリはどうやってるのでしょうか。SDL_DrawStringみたいなAPIが欲しいところです。でないと文字列の表示を実装するコストが必要になります。
6.3. BlueTooth
例えばゲームでBlueToothによる通信をしたいと思っても、SDLが対応していないし、そもそもndkのライブラリにもAPIがありません。
githubにSDL2で実装したテトリスを公開しました(かなりやっつけではありますが)。Ncursesでも動作します。