HaxeでHashLink/SDLを使ってみる


追記:SDLとOpenALの導入のくだりは、自分でHashLinkをビルドする時にするものでした。必要ないので削除しました(恥

全くと言って良い程に日本語の情報がないHashLinkを、恐る恐る使っていきます。

そもそも

HashLinkとは、皆さんご存知(でもない)Haxeのターゲットとして、2016年に追加されたプラットフォームです。

ホームページを見てみるとわかると思いますが、「HashLinkはHaxe専用のVMです」と堂々と銘打っています。
そもそも開発者はHaxe FoundationもといNicolas Cannasse(Haxe、Nekoの生みの親)氏ですので、まさにHaxeによるHaxeの為のプラットフォームと言った所でしょうか。

そして、先ほども述べた通りHashLinkは仮想マシンなのですが、一方でコンパイラでもあるというちょっと特殊な構成をしています。

それってNekoと若干被ってない?

そう、HaxeにはNekoという、これまたHaxe専用のVM(正確には、Neko VMで動作するNeko言語に変換しています)があったはず。
なぜ今になって新しいプラットフォームを打ち出してきたのでしょう?

実は、Nekoが登場したての頃はHaxeと独立した言語としてリリースされていた事もあり(今でもそうだとは思うのですが、実質Haxe専用ですよね)、ちょっとHaxeとは相性が悪かったのだそうで。

例えば、Nekoは動的型付け言語です。
Haxeは静的型付け言語だからこその高速な動作をウリにしているのですから、それならC++等に変換して使う方が良いですよね。わざわざNekoを使うメリットは薄いように思えます。

一方HashLinkは静的型付け言語ですので、その点に限ってもHashLinkの方がHaxeとの相性が良いと言えるでしょう。

また、HashLinkは将来的にモバイルコンシューマゲームに対応する事がアナウンスされています。
コンシューマっていうとPS4、Vita、Xboxあたりですかね。これは期待です。

HashLinkのコンパイルターゲット

HashLinkでのコンパイルとは、Haxeと同様他の言語に変換する事を意味します。

Haxeで-hlオプションを付けてコンパイルするとHashLinkバイトコード(.hl)を吐き出すので、それをHashLink(hl.exe)に渡してやればコンパイルできます。

Haxeは、HashLinkを含めC++やJavaScriptなど様々な言語に変換できる言語でしたね。
ではHashLinkはどんな言語に変換してくれるのかと言いますと、それがなんとC(!)なのですよ。
CですよC。ロストテクノロジーです。
まぁ、パフォーマンスを追求するのならCは最良の選択肢なのでしょう。
私達がCを書かされる訳でもないですし、さほど問題はありません。

そして、HashLinkそのものもCで書かれています。
HashLink開発者の方は、あんな開発効率の悪い言語を書かなきゃならないのですね…さぞ大変な事でしょう。
Nicolas氏はすごい楽しんで書いてそうだけど。

Cに変換するほか、バイトコードを直接HashLink VM上で実行する事も可能です。
パフォーマンスはCに劣るとはいえ、NekoやV8エンジン上のNode.jsより高速に動作するそうで、開発時にはぜひこちらを利用してくれとの事。
デバッグ時はHashLink VMで、最終リリース時はCでって感じで使い分けると良いかと思います。

あ、そうそう。
現状、HashLinkはWindowsLinuxにしか対応していません。
Cに書き出した後からならどうとでもなると思いますが、VMの実行やコンパイルそのものはmacOSではまだできないのでご注意を。

今見てみたらこの記述は消えていて、代わりにmacOSでのビルド方法が書いてありました。
まだバイナリでのリリースはされていないようですので、自分でビルドする必要があります。

HashLinkでできる事

HaskLinkでは、CのライブラリであるSDLの主要な機能をサポートしています。
サポートしている機能の中には、ウィンドウ生成やジョイパッドの管理など様々な機能が含まれていますが、最も重要な点はOpenGLをフルサポートしているという点でしょう。これは大きい。

HashLinkはSDL以外にも、Cのサードパーティ製ライブラリを幾つか内包しています。

  • Bullet - 3D物理エンジン
  • DirectX - Win専用のマルチメディアAPI(一部のみ)
  • FFmpeg - マルチメディアエンコーダ
  • libjpeg-turbo - JPEGのエンコード/デコード
  • libmesa - OpenGLベースの3Dグラフィックス
  • libpng - PNGのエンコード/デコード
  • libuv - 非同期IOによるイベントループ
  • libvorbis - Ogg/Vorbisのエンコード/デコード
  • mbed TLS - SSL/TLS通信のサポート
  • OpenAL - 高度な音声処理
  • PCRE - Perlの正規表現
  • SQLite - データベース管理
  • Steamworks API - Steamでのリリースに必須
  • zlib - 汎用可逆圧縮アルゴリズム

現状ではこんなもんでしょうか…?

SDLとDirectX、OpenALについては、HaxeLibにライブラリが用意されています(hlsdlhldxhlopenal)。
Bulletについても、まだHaxelibには登録されていないようですが、HashLinkのGithubリポジトリにhlbulletが置いてあります。
Steamworks APIもBulletと同様、HeapsのGithubリポジトリに置いてあります。

それ以外は、Haxeの標準ライブラリにそれぞれ対応しているものが用意されているはず。多分。

また、Windowsに限り幾つかUIライブラリが用意されています。
一部のUIしかないようですが、アラートウィンドウなど、欲しい所はきちんと用意してあります。


こんにちは世界

いつもの。
とは言っても、普通にtraceするだけです。

あらかじめここからHashLinkをダウンロードしておきましょう。
PATHを通しておくとよりgood、コンパイル用のバッチを書いておくと完璧です。

Main.hx
package;

class Main
{
  static function main()
  {
    trace("Hello, World!");
  }
}
build.hxml
-cp src
-dce full
-hl test.hl
-main Main

これでコンパイルすれば、カレントディレクトリにtest.hlが生成されます。

後は、hl.exeにtest.hlを渡してあげればオーケーです。

hl test.hl
src/Main.hx:7: Hello, World!

ウィンドウを表示してみる

SDLを使って、ウィンドウを表示し3秒で閉じるプログラムを書いてみます。

hlsdlをインストールしましょう。haxelib install hlsdlでオーケーです。
この時に、hlopenalのインストールも自動で始まるはずです。もしされなかったら、手動でhaxelib install hlopenalします。

導入が完了したら、Main.hxを以下の通りに編集します。

Main.hx
package;

import sdl.Sdl;
import sdl.Window;

class Main
{
  static function main()
  {
    Sdl.init();
    var mainWindow = new Window("Test", 640, 480);
    Sdl.delay(3000);
    mainWindow.destroy();
    Sdl.quit();
  }
}

後はコンパイルしてhl test.hlすれば、真っ白なウィンドウが3秒間表示されるはずです。


感想

色々と細かい部分がネイティブのSDLと違っていて戸惑いましたが、なんとかここまで漕ぎ着けられました…

HashLinkの情報に関しては、日本語はおろか英語の公式ドキュメントすらもほとんど整備されていません。
hlsdlなんか皆無ですよ。

幸いな事に、SDLに関しての情報はインターネット上にたくさん載っています。
これとhlsdlのソースコードとを照らし合わせつつ、じっくりと書いていくしか方法はありません。

みんなも、Haxe使おうね!(これが言いたかっただけ


おまけ:ユースケース

HashLinkの使用事例が、既に2件もあります!
…多いのか少ないのか。

まずは、Shiro GamesよりNorthgard
Shiro Gamesは、Nicolas氏とNCSoftの元CEOであるSebastien Vidal氏が設立したゲームデベロッパです。
Evolandが有名ですが、Nicolas氏がいるのだから当然Haxeで書かれています。地産地消とはこの事。

Northgardは、HashLinkとHeapsを使って開発されています。
Heapsとは、Haxe向けのゲームエンジンの事です。これまたNicolas氏が開発しています。過労死しないか心配。

もう1つは、Motion TwinよりDead Cells
Motion TwinもHaxeに非常に関わりのあるゲームデベロッパです。そもそも、HaxeはMotion Twinの社内プロジェクトであるMTASC(ActionScriptの代替コンパイラ)から派生したプロジェクトでした。
同社がリリースしているゲームの多くもHaxeで実装されています。

Dead Cellsも、HashLinkとHeapsで開発されています。
しかし、こちらはなんとPS4、Nintendo Switch、Xbox Oneでのリリースもアナウンスされています。
Steam版のみHashLinkって感じなんですかね。

ちなみに、Heapsのリポジトリの中にhlsteamというのが用意されています。
これは、HashLink向けにSteam APIを移植したもののようです。
恐らく、上記2つのゲームでもこれが使われているのではないかと思います。

…とまぁ、身内での使用事例がほとんどという現状でした。
しかし、HashLink(+Heaps)の可能性は感じられたかと思います。みんなも積極的に使っていこうね。


誰かVSCodeのHashLink-Debuggerの使い方教えてください(小声