estar-lab.net趣味工作日記プライバシーポリシー

Xubuntu(Ubuntu)でDxLibを使う


2018年05月02日 Tweet
作成日: 2018-05-02, 更新日: 2020-10-11

普段使いのOSをXubuntuにしました管理人です。
とは言えWindowsとのデュアルブート環境です(Windows7は捨てたくなかったので)。 本来ならOSを変えた時の日記を書きたかったのですが、書きかけの記事が入っていた外付けHDDがお亡くなりに・・・orz

というわけで今回は「Xubuntu(Ubuntu)でDxLibを使う」そして開発をしていきます。
ただし、今回やっている手法はかなり無理やりで推奨されたものではないので実際にゲームとして出すときは、 もう少し正しい手順を踏むか、Windowsでビルドしなおした上でリリースしなおしてください。
なお、管理人はそこまでLinuxに明るくないので「ここ違うだろ」って思った際は適時読み替えてください。
文章を書いている時点でのGCC(G++)のバージョンは5.3.1です。

目次

留意点

・真面目な方法で動作させていません
ゴリ押しで動かしている点があります。正しい開発方法ではないので知識がある方以外は作ったプログラムを配布しないほうが良いと思われます。(しっかりとWindowsでビルドしてください。)
・Linuxの知識が豊富にあるわけではありません
ところどころ間違った知識があるかもしれないので鵜呑みにせずあくまで参考としてご覧ください。
・あくまで管理人の備忘録です
「自分ができるようになるための覚え書き」です。不親切な表現があるかもしれませんのでご了承ください。

目的

最終目標は「XubuntuでC/C++とDxLib書いたプログラムをクロスコンパイルし、Windowsで動かせるプログラムを作成する」です。
あくまで最終的にはWindowsで動かすことがメインで、Linux上で動かすことには観点を置いていないことに注意してください。

Wineのインストール

コンパイルしたプログラムはWindowsのプログラムなので動かすためにWineを使用します。
https://wiki.winehq.org/Ubuntu
このサイトに従いWine(stable)をインストールします。

MinGW-w64のインストール

クロスコンパイラである「MinGW-w64」をインストールします。

sudo apt install mingw-w64

インストールが終わったら

i686-w64-mingw32-g++

とか打ってみて反応が返ってくればインストールできています。

次に、このままでは毎回上記のコマンドを打たなければいけないので非常に面倒です。 なので、エイリアスを登録します。
どうやって登録をするかはその人次第ですが今回は「~/.bashrc」をエディタで開いて

# some more ls aliases
alias ll='ls -alF'
alias la='ls -A'
alias l='ls -CF'

と書いてある行の下に

alias mingw64g++='x86_64-w64-mingw32-g++'
alias mingw32g++='i686-w64-mingw32-g++'

この二行を追記します。
これで「mingw64g++」で64bit向けのC++コンパイラ、「mingw32g++」で32bit向けのC++コンパイラを呼び出せます。
また、エイリアスを適用させるためにPCを再起動させるか以下のコマンドで再読み込みを行います。

source ~/.bashrc

Visual Studio Codeのインストール

続いては、Visual Studio Codeのインストールをします。
Ubuntuユーザなので以下のサイトで「Visual Studio Code ダウンロード」→「.deb」と進みパッケージを入手します。
https://www.microsoft.com/ja-jp/dev/products/code-vs.aspx
ダウンロードしたファイルを開けばインストールできます。
余談ですが、管理人はVisual Studio CodeをIDEだと勘違いしていました。インストールしてソースエディタと気づきました(笑)

Visual Studio Codeで開発する(準備)

インストールが完了したところでスタートメニュー(Windowsの方言)の開発タブに「Visual Studio Code」が追加されています。

それを起動すると

このようなウィンドウが立ち上がります。普段開発で目にするVisual Studioとは少し違うようです。(ツールバーがなかったりなど)

次にワークスペースにフォルダーを追加します。ワークスペースは使い方を意識したことはありませんが「C言語の開発、Javaの開発」「ゲーム、ユーティリティ」などでまとめるのに使います。(本来の使い方かわからないので詳しくは各自調べてください。)
メニューの「ファイル」→「ワークスペースにフォルダを追加」でフォルダを選択することでワークスペースにフォルダが追加されます。

ワークスペース追加にあたっては、
ワークスペース: {$HOME}/Programmings/VSCode/
今回の開発するプロジェクトのフォルダ: {$HOME}/Programmings/VSCode/hello
とし、フォルダーを作成した上で「hello」をワークスペースに追加しました。
これで以下のような画面になります。

このままではワークスペースが未設定の状態なので、とりあえず保存しておきます。
メニューの「ファイル」→「名前を付けてワークスペースを保存」でワークスペースフォルダに「default」という名前で保存しました。 この「default」がワークスペース名になります。

Visual Studio Codeで開発する(テストプログラム開発)

一通り準備が終わったところで開発を始めてみたいと思います。
「hello」を選択した状態で「DEFAULT(ワークスペース)」にマウスをかざすと、ファイルアイコンに+マークがついた「新しいファイル」が出てくるので押します。すると「hello」新規ファイルが作られます。ファイル名は「main.c」とかにしておきます。

ファイル名を決めるとエディタが開くので、さくっと「世界にこんにちは」するプログラムを書きます。

プログラムが書き終わったら「hello」を右クリックして「ターミナルで開く」を押すことで、プロジェクトのフォルダでターミナルが開きます。

ターミナルが開いたらプログラムをコンパイルします。

mingw32g++ main.c

コンパイルエラーが出ない限り、何も表示されなければコンパイル成功のようです。(ファイル名は指定しない限りa.exeです。)

次にできた実行ファイルを実行します。ファイルはWindows向け実行ファイルなのでWineで実行します。

wine cmd

これでWindowsのコマンドプロンプトのような物にアクセスできます。
この状態でWindows同様「a.exe」と打てば実行されます。(後にわかりましたがコマンドプロンプトを開かずに「wine a.exe」だけで良いようです。)

Visual Studio Codeで開発する(DxLib開発)

ソースコードについて

いよいよDxLibでの開発を行います。まずはライブラリをダウンロードします。
http://dxlib.o.oo7.jp/index.html
「DXライブラリのダウンロード」→「DXライブラリ Windows版 Gnu C++( MinGW )用(Ver3.19b)をダウンロードする(zip圧縮形式(約72.4MB))」からダウンロードできます。(現時点で最新版は3.19bですが、その時の最新版で大丈夫だと思います。)
これをどこか適当な場所に解凍しておいておきます。なお、解凍した際に文字化けしたフォルダがありますが、以下の画像で示したフォルダがライブラリ本体のフォルダです。

補足

ここで文字化けが発生する理由はファイル名などの文字エンコードの違いです。(WindowsではShiftJISだがLinuxではUTF-8で扱おうとする)

unzip -O shift_jis 解凍するファイル.zip

このようにunzipコマンドで解凍する時の文字エンコードを指定してあげると文字化けは発生しなくなります。

「hello」を作ったとき同様に新しいプロジェクトを作ります。今回は「dxlib」という名前にしました。
さらに「dxlib」のフォルダに「DxLib」というフォルダを作成し、ライブラリ本体のフォルダ内にある「5_3_0_i686」の中身を、作った「DxLib」フォルダにすべてコピーします。

プログラムは本家様のサンプルを元に描画部分だけ変えたものを使います。(点描画だとわかりにくいことがあるため)
ファイル名はDxLibがC++で書かれているため「main.cpp」にします。

#include <DxLib.h>

#ifdef LINUX_BUILD
#define DX_GCC_COMPILE
#define DX_NON_INLINE_ASM

void * __gxx_personality_v0 = 0;
void * _Unwind_Resume = 0;
#endif

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpStr, int nCmdShow){
    ChangeWindowMode(TRUE);
    if(DxLib_Init() == -1){
        return -1;
    }
    
    DrawBox(320 - 20, 240 - 20, 320 + 20, 240 + 20, GetColor(255, 0, 0), TRUE);

    WaitKey();

    DxLib_End();
    return 0;
}

普段のDxLibでは見慣れない部分があると思うので追って説明します。
「#ifdef LINUX_BUILD〜#endif」ではg++環境において宣言しなければいけないものをまとめてあります。 これにより、Windows環境に移してコンパイルをし直す場合ソースコードの書き換えをする必要がなくなります。

#define DX_GCC_COMPILE
#define DX_NON_INLINE_ASM

は本家様サイトで指示されている定義です。何故か定義しておかなくてもエラーは出ませんが一応入れておきます。

void * __gxx_personality_v0 = 0;
void * _Unwind_Resume = 0;

今回一番のゴリ押しポイントです。
https://stackoverflow.com/questions/10419801/undefined-reference-to-unwind-resume-and-gxx-personality-v0
このサイトに答えがありました。
まず、MinGWでのコンパイルは使うライブラリもバージョンを揃えないとコンパイルエラーが出てしまうようです。MinGW-w64とDxLibでも例外はないようで、MinGW-w64のgcc(g++)がバージョン5.3.1、DxLibのコンパイルバージョンが5.3.0となっています。MinGW-w64の他のバージョンをインストールも考えましたが方法があるのかわからず断念しました。
DxLibの作者様に頼んで適正バージョンでコンパイルしてもらうという方法もありますが、そもそもWindows環境でのコンパイルでない以上、本当にうまく行くかわからないような物を頼むということに違和感があるため、自身で完結させるべきだと思います。
もうひとつ、質問者の方がエラーの抑制方法を書いています。「未定義の参照でエラーがでるのであれば、自身でそれを定義してしまおう」ということのようです。それがプログラムに書いた2行のコードとなります。

コンパイルについて

「hello」のプログラム同様、書いたプログラムのコンパイルをする必要があります。
どのようにコンパイルするかを先に書いてしまうと以下の形になります。

mingw32g++ <ファイル名> -DLINUX_BUILD -I./DxLib/ -L./DxLib/ -static -lDxLib -lDxUseCLib -lDxDrawFunc -ljpeg -lpng -lzlib -ltiff -ltheora_static -lvorbis_static -lvorbisfile_static -logg_static -lbulletdynamics -lbulletcollision -lbulletmath -lopusfile -lopus -lsilk_common -lcelt -mwindows -fexec-charset=cp932

追記:パスを相対パスに変更しプロジェクトを変えるたびに書き換える必要をなくしました。
このようになります。非常に長いです。
ファイル名にはコンパイルするファイル(main.cppなど)を入れてください。
念の為、実際に使っているコンパイルオプションも書いて置きます。(ソースファイルがmain.cppまた、フォルダ構成が同じであればそのまま以下をコピペで使えると思います。)

mingw32g++ main.cpp -DLINUX_BUILD -I./DxLib/ -L./DxLib/ -static -lDxLib -lDxUseCLib -lDxDrawFunc -ljpeg -lpng -lzlib -ltiff -ltheora_static -lvorbis_static -lvorbisfile_static -logg_static -lbulletdynamics -lbulletcollision -lbulletmath -lopusfile -lopus -lsilk_common -lcelt -mwindows -fexec-charset=cp932

簡単にコンパイルオプションについて説明します。
-DLINUX_BUILDでLINUX_BUILDを定義(ソース内の#define LINUX_BUILDに当たる)します。これによりソースに干渉することなくLinux、Windowsでのビルドの住み分けができます。
-I, -Lはインクルードパス、ライブラリパスを指定しています。
-lで始まるものはライブラリです。これはDxLibの解説に乗っている順番厳守の絶対に必要な項目です。
-staticは「libgcc_s_sjlj-1.dll」や「libstdc++-6.dll」がないと単体で実行できないためスタティックリンクオプションを付与します。(詳しくは各自調べてください。)
-mwindowsはGUIを持ったプログラムを使うのに必要なので追加します。
-fexec-charset=cp932は文字化け防止です。そのままコンパイルすると日本語の文字化けが起こるので実行ファイルの文字セットをShift-JISにしてコンパイルします。

完成

これで晴れてXubnutu(Ubuntu)でDxLibの開発ができるようになりました。
WaitKey関数を使うと画面がおかしくなったりすることはありますが基本的な使用・テストには十分な環境です。普段使いのOSがLinuxだけど、Windows用のゲームが開発したいという場合に可能な限りLinux上で開発することができるようになりました。
しかし、最終的にはWindows環境でのチェック・コンパイルが必須なってくるので完全にWindowsフリーで開発するということはできないという点を念頭に置きましょう。

日記の部屋に戻る