Code of Poem
Unknown programmer's programming note.

Hello SFML!

唐突ですが…

SDLからSFMLというライブラリに切り替えることにしました。一番の理由は、個人的なもので、二つ目のディスプレイをつなげてマルチディスプレイの環境にしたら、SDLのウィンドウを使ったプログラムの終了時に画面がフラッシュしてしまう現象が発生するようになったためです。終了時に一度暗転するだけで、動作そのものには影響はなく、直接プログラミングの学習に支障がでるというものではありません。しかし、終了させるたびにフラッシュするので毎回「何とかならないかなー」という雑念が入ってきます。小さなことですがこういうことで気分が下がってしまうのは良くないです。取れる手段は、ディスプレイを一つに戻すか、問題が解決するまでSDLを使用を控えておくかのどちらかです。今更ディスプレイ一つに戻ることはできないので、後者を取ることにしました。せっかくSDLの使い方を少し覚えてきたのにもったいないですが、また新しい環境で作り始めるのも気分が刷新できて悪くはないと考えておくことにします。

SFMLとは…

SFMLに期待する役割はSDLの代替です。つまり、ゲームのためのシンプルなウィンドウを表示させることが出来て、その中にある程度高速に描画できるグラフィックスの機能を備えていて、その他にもゲームに必要な入力の扱いやサウンドなどを最低限扱うことができるというものです。さらにクロスプラットフォームでソースコードが公開されていることです。使い方がシンプルであればあるほどさらに良い(ただしシンプルすぎては良くない)です。たぶんSFMLはこの無茶な要件を満たしてくれています。

3Dグラフィックスの機能は求めていません。今はまだC++でゲームのコードの基礎を学んでいる段階です。いずれはOpenGLで3Dゲームを作り始める予定ではありますがもうちょっと先になりそうです。SDLはレンダリングにOpenGLを使うことが出来て、OpenGLのためのウィンドウなどのツールキットとして使用することも出来ます。SFMLでもOpenGL中心のプログラミングのサポートをするツールキットのような使い方ができるのかどうかまだ分かってません。不可能ではなさそうです。どちらにせよ、2Dのゲームで基礎をしっかり作ってからにしたいので、まず2Dゲームを作るのに適しているかどうかが重要です。

SFMLはC++がメインの言語ですが、他の言語でも使うことができるようです。SDLにもCとC++以外の言語のバインディングがありますが、SFMLの方が充実しているように見えます。個人的はD、Go、Haskell、Rustなどを使ってみたいです。それは置いておいて、SFMLがCではなくC++をメインとしていることは、C++の学習という観点からはプラスに働くのではないかなと思います。

SFMLのインストール

DebianやUbuntuだったら次のコマンドでインストールできます。

sudo apt isntall libsfml-dev

パッケージマネージャでインストールできないLinuxディストリビューションやWindowsやmacOSのプラットフォームの場合はダウロードページから入手してインストールします。

とりあえず動かしてみる

ちゃんとインストールできたかの確認を込めて、何も考えずにここのコードを実行してみます。

#include <SFML/Graphics.hpp>

int main() {
  sf::RenderWindow window(sf::VideoMode(200, 200), "Hello SFML!");
  sf::CircleShape shape(100.f);
  shape.setFillColor(sf::Color::Green);

  while (window.isOpen()) {
    sf::Event event;
    while (window.pollEvent(event)) {
      if (event.type == sf::Event::Closed) {
        window.close();
      }
    }

    window.clear();
    window.draw(shape);
    window.display();
  }
}

aptでインストールした場合は以下のコマンドでコンパイルできます。

g++ -std=c++17 -Wall -o hellosfml hellosfml.cpp -lsfml-graphics -lsfml-window -lsfml-system

実行するとウィンドウが表示されます。

SFML Hello SFML! Window

SDLもシンプルでしたが、SFMLの方がさらにシンプルなように見えます。前回のブロック崩しで円を描くのを作るかどうかというような話をしていて結局作りませんでした。SFMLには円を描くAPIが用意されていて思いがけずこんなところで実現されてしました。

一つ注意することとしては、

using namespace sf;

とするのは良くないことだそうです。私は小さなプログラムのソース(.cppファイル)の中では結構using namespace std;と書いてしまうのですが、ここの投稿を見るとusing namespace sf;は良くないそうです。

あと、もっと大きなサイズの円にしてみると円周部分があまりきれいではありません。きれいな曲線にする方法が用意されているのか気になるところではあります。

Geanyのタグを作る

GeanyのエディタでSFMLのシンボルを補完できるようにするために、システムにインストールされたSFMLのヘッダからグローバルタグファイル(Global tags file)を生成します。ヘッダが/usr/include/SFML以下にインストールされているなら以下のコマンドでGeanyのグローバルタグファイルを作れます。

CFLAGS=`pkg-config --cflags sfml-all` geany -gP ~/sfml.cpp.tags /usr/include/SFML/*/*.hpp

出来たタグファイルはGeanyのコンフィグディレクトにコピーしておきます。

cp sfml.cpp.tags ~/.config/geany/tags

これでGeanyを再起動するとCtrl+SpaceでSFMLのシンボルを補完できるようになります。またShift+Ctrl+Spaceで関数の引数のヒント(コールチップ)を表示させることができるようになります。…しかし、名前空間やクラスのスコープが考慮さないため使いづらいです。std::以下のclear(std::vector::clear)、sf::以下のclear、自分で定義したclearなどが全て出現してきてきます。特にコールチップはマウスでしか候補の表示を切り替えが操作できないためさらに使いづらいです。この点においては、SDLのAPIは名前がSDL_で始まっているので曖昧になることがなく、SDLの方がGeanyと相性が良いです。というよりもC++自体がGeanyの補完と相性が良くないです。

参考