夢の続きを語ろうよ
Emscriptenの逆襲
HTML5編
sun6925 とよしま
ウェブ大好きっ子
低レイヤー大好きっ子
レトロPC大好きっ子
X68000大好きっ子
わーい!すごーい!たーのしー!
知ってますか?
● なぜか 編集部が作ったゲーム
○ 創刊10周年記念 PRO-68K に収録
(雑誌付録ディスク)
○ 編集部制作の強力インフラ
■ MAGIC2 - 3D描画ライブラリ
■ Z-MUSIC - サウンドドライバ
○ ゲーム自体、普通に面白い
○ 25年前!
実演
原作@エミュレータ
あれ?ショボい!
256 x 256 ドット 16 色 ワイヤフレーム
・
・
・
んじゃ、高解像度化しますか
実演
ハイレゾ@ウェブ
bit.ly/sion2
原作をウェブで
Powered by Emscripten
run68 (in C)
sion2.x
(Binary for X68k)
実行
JavaScript VM
実行
互換レイヤー
(in JavaScript)
DOS/IOCS
MAGIC
Z-MUSIC
GVRAM I/O
z-music.js
zmusic.x
(Binary for X68k)
非同期RPC化
ここで気合
ハイレゾ化するぞ!
X68Sound.dll (in C++)
run68 (in C)
基本方針:エミュレータ+黒魔術
高解像度+16:9化
256 pixel
256 lines
ピクセル
アスペクト比
4:3 1080 lines
1440 pixel
4:3
1920 pixel
16:9
アスペクト比補正+ベクトル拡大
+本来見えていなかった部分の表示
ワイヤーフレームは楽勝
スプライトやBGパターンの描画
座標とパタン番号等を拾ってCanvasに高解像度で描画
X : 140
Y : 80
Pattern: 1
Xflip : No
Yflip : No
I/OアクセスからGVRAMの中身を追跡
❏ (140, 8)を表示座標に変換
❏ Pattern 1なら星を描画
ビットマップ文字のベクターフォント置き換え
一部の文字(4×6サイズ)が画像だった
● 仕方ないのでGVRAMのアクセスパタンから文字推定
{ “111010101110101010100000”: 64, ... }
文字コード64
A
内部で使ってる主な技術
● Web App Manifest : ホーム追加・全画面起動
● HTML5 Canvas(2D)
○ requestAnimationFrame : 60fps
○ ダブルバッファ
○ WebFonts : Canvasで正しく使おう
● Gamepad API / TouchEvent
● DeviceOrientationEvent
● Web Audio API : FM音源と音響処理
● Web MIDI API : 外部音源による演奏対応
モバイルでホームに追加・全画面起動
Web App Manifest (manifest.json)
❏ ファイルを置くだけ {
"name": "SION2 HD",
"icons": [ … ],
"start_url": "index.html",
"display": "standalone",
"orientation": "landscape"
}
画面描画
描画ループにrequestAnimationFrameを使う
❏ Emscripten内からはemscripten_set_main_loop(fps=0)を使いましょう
void emscripten_set_main_loop(em_callback_func func, int fps, int simulate_infinite_loop)
Canvas 2面を重ねて交互に表示
❏ display: [none|block]を交互に切り替える
❏ オフスクリーン→Canvas転送は(読み出しが)遅いので避けるべき
WebFontsをCanvasで正しく使う
❏ 遅延読み込みを正しく扱う必要があるので注意しましょう
WebFontsについて補足(1)
遅延読み込みについて
❏ 実際にレンダリングに必要になったときに読み込みが始まる
❏ 読み込み完了までは利用できない
❏ HTMLで使っている分には自動的に読み込み待ちや再描画が行われる
❏ Canvas API経由で使うためには正しく読み込みを待って描画する必要がある
正しく読み込み待ちするための手順(Edge非対応)
1. document.fonts (FontFaceSet)にフォントを登録
2. フォントの読み込みを開始させる
3. フォントの読み込み完了を待つ
WebFontsについて補足(2)
1. FontFaceSetに登録
❏ FontFaceで作成したフォントの場合: document.fonts.add(fontFace)
❏ CSSで指定したフォントの場合、自動的に登録されるので考慮不要
2. フォントの読み込みを開始させる
❏ FontFaceで作成したフォントの場合: FontFace.load()
❏ 登録済みのフォントの場合: document.fonts.load(“50px myfont”)
3. 読み込み完了を待つ
❏ フォント個別: FontFace.load / document.fonts.loadの返すPromiseを待つ
❏ フォント全部: document.fonts.ready : Promise を待つ
Gamepad API
❏ Androidでも利用可能
❏ この手(→)のBluetoothの物が使える
(Amazonで今日現在260円!!!)
❏ Cardboard対応を考えると一家に一台
❏ APIの仕様は極めて単純明快
❏ ただし、WebKit系では利用できない
const gamepads = navigator.getGamepads();
// gamepads[].axes[], gamepads[].buttons[]をチェック
TouchEvent
❏ タッチ対応デバイスならmobile/desktopで利用可能
❏ マルチタッチも対応可能
❏ 基本的にネイティブアプリと同等の処理ができるはず
❏ 使いやすい「方向キー」実現のためにはノウハウも必要
今回利用したアルゴリズム例:
❏ タッチ地点を起点として、移動した方向に入力を取る
❏ 逆方向の移動を検知したら入力キャンセル、起点の取り直し
ノウハウを持った人によるライブラリ化が望まれる
DeviceOrientationEvent
❏ Cardboardを使ってヘッドトラッキング!
❏ この手(→)のスマホ用VRケースが使える
(Amazonで今日現在998円!!!)
❏ EventListenerを登録するだけ
デバイスの傾きがEular角で通知される
→3D計算の視点に取り込めば向いた方向で視点を動かせる
window.addEventListener('deviceorientation', e => {
// e.alpha, e.beta, e.gamma
});
Web Audio API
❏ JavaScriptでリアルタイム波形合成
❏ 現仕様はノイズ耐性が低い(描画負荷やGCに気をつける)
❏ 今年登場すると思われるAudio Workletを使えば改善される
❏ FM音源エミュレーション
❏ とは言いつつEmscriptenでコンパイルしたC++コードでも動いてる
❏ バッファサイズ2048の場合:~42msecごとに1-2msecの合成処理
❏ リバーブ
❏ ConvolverNodeにインパルス応答を渡すだけで実現可能
Web MIDI API
❏ Web MIDI経由で外部音源による演奏をサポート
❏ 中で動いているZ-MUSICに対し、MIDIボードに対するI/O操作を
フックしてWeb MIDIに繋ぎこんでいる
❏ Web Audio / MIDIについて詳しく知りたい人
❏ Web Music Developers JP
❏ WebAudio.tokyo
まとめ
● エミュレータ+黒魔術で昔のゲームを移植
● HTML5でネイティブ同様の作り込みが可能
○ モバイルホーム画面追加・全画面起動
○ 60フレーム+ダブルバッファでヌルヌル描画
○ リッチなフォント
○ ゲームパッド・タッチ操作
○ ヘッドトラッキングによる視点移動
○ リアルタイム合成による音源エミュレーション
○ 外部楽器を用いたBGM演奏
質問など
Emscriptenまめ知識〜その1
描画ループにrequestAnimationFrameを使う
❏ emscripten_set_main_loop()を使いましょう
void emscripten_set_main_loop(em_callback_func func, int fps, int simulate_infinite_loop)
❏ fpsに0を指定するとrequestAnimationFrameが使われる
❏ それ以外の値だとsetTimeoutを使うので注意
❏ 失敗談:知らずにsetTimeoutを書き換えて中からrAF呼んでた
❏ simulate_infinite_loop=1でこの関数から戻らない
Emscriptenまめ知識〜その2
常駐するサービス・ライブラリを作る
❏ emscripten_exit_with_live_runtime()で常駐
void emscripten_exit_with_live_runtime(void)
❏ ひとまず実行終了
❏ ただしatexit()系やリソース解放処理は走らない
❏ JavaScriptからC/C++の関数を継続して呼び出し可能
❏ 空のmain()から呼べば共有ライブラリっぽい物が作れる
Emscriptenまめ知識〜その3
JavaScriptから呼び出せる関数を(確実に)作る
❏ リンク時に-s EXPORTED_FUNCTIONS="..."
❏ "..."にはmainを含めた関数のリストを渡す
例:"['_main', '_myAPI1', '_myAPI2']"
❏ 関数名は"_"のプレフィクスが付くので注意
❏ 数値以外は直接渡せない点に注意
❏ C/C++側のメモリ空間はModule.HEAPU8等でアクセス
❏ Module.cwrap()やWebIDL-Binderなどの道具はある
Emscriptenまめ知識〜その4
JavaScriptのライブラリを呼び出す
❏ リンク時に--js-library myLibrary.jsで組み込む
❏ 渡すJavaScriptは特定の方法で記述されている必要がある
mergeInto(LibraryManager.library, {
myFunc: function(a, b) {
// ここから外の世界は直接触れる(this==Window)
console.info(‘hello my func’);
return a + b;
}, // 以下、同様に関数を定義
});
❏ 登録なしでCから呼ぶとundefined symbolで実行時abort
Emscriptenまめ知識〜その5
実行開始を遅延させる
❏ preInit内でaddRunDependency()を呼ぶ
❏ 対応するremoveRunDependency()が呼ばれるまで待つ
❏ WebFonts読み込みを待つ例
preInit: function() {
Module.addRunDependency("fonts");
document.fonts.ready.then(function() {
Module.removeRunDependency("fonts");
});
},

More Related Content

PDF
8bit 時代のプログラミング事情を訪ねて
PPTX
Summercamp2020 group2
PPTX
Summercamp2020 group3
PDF
楽しいロリコン
PDF
USB MIDI - DMX bridge
PDF
Web MIDI API - the paster, the present, and the future -
PDF
Web MIDI API update
PDF
Oh! java script 夢の続きを語ろうよ〜emscriptenの逆襲
8bit 時代のプログラミング事情を訪ねて
Summercamp2020 group2
Summercamp2020 group3
楽しいロリコン
USB MIDI - DMX bridge
Web MIDI API - the paster, the present, and the future -
Web MIDI API update
Oh! java script 夢の続きを語ろうよ〜emscriptenの逆襲

Viewers also liked (20)

PDF
OSC京都 2015 LT 「テスト自動化の闇と向き合う」
PPTX
three.jsを「遅い」と思わせないデータの扱い方
PPTX
デザイナーにも優しいクラウド型ゲームエンジン"PlayCanvas"
PDF
Onsen UI 2.0とUIライブラリの未来
PDF
20151201 私がSeleniumを使ってスクリーンショットを撮るまでに出会った闇の全て
PDF
TUG 2014 参加体験記
PDF
ぼくのかんがえたさいきょうの Rails スタートダッシュ
PDF
私がSeleniumを使ってスクリーンショットを撮るまでに出会った闇の全て
PDF
Emacs上のターミナルを最強に
PDF
Exploring the Performance Impact of Virtualization on an HPC Cloud
PPTX
WebRTC SFU mediasoup sample
PPTX
WebRTC on Edge
PDF
『BrandSafe はてな』のアドベリフィケーションのしくみ
PDF
クラウドの垣根を超えた高性能計算に向けて~AIST Super Green Cloudでの試み~
PDF
OSvの概要と実装
PDF
The state of sbt 0.13, sbt server, and sbt 1.0 (ScalaSphere ver)
PDF
はてなブックマーク in Scala
PDF
Yahoo! JAPANのサービス開発を10倍早くした社内PaaS構築の今とこれから
PDF
これから必要とされるデザイナーのスキルとキャリアパスについて
PDF
UEFI時代のブートローダ
OSC京都 2015 LT 「テスト自動化の闇と向き合う」
three.jsを「遅い」と思わせないデータの扱い方
デザイナーにも優しいクラウド型ゲームエンジン"PlayCanvas"
Onsen UI 2.0とUIライブラリの未来
20151201 私がSeleniumを使ってスクリーンショットを撮るまでに出会った闇の全て
TUG 2014 参加体験記
ぼくのかんがえたさいきょうの Rails スタートダッシュ
私がSeleniumを使ってスクリーンショットを撮るまでに出会った闇の全て
Emacs上のターミナルを最強に
Exploring the Performance Impact of Virtualization on an HPC Cloud
WebRTC SFU mediasoup sample
WebRTC on Edge
『BrandSafe はてな』のアドベリフィケーションのしくみ
クラウドの垣根を超えた高性能計算に向けて~AIST Super Green Cloudでの試み~
OSvの概要と実装
The state of sbt 0.13, sbt server, and sbt 1.0 (ScalaSphere ver)
はてなブックマーク in Scala
Yahoo! JAPANのサービス開発を10倍早くした社内PaaS構築の今とこれから
これから必要とされるデザイナーのスキルとキャリアパスについて
UEFI時代のブートローダ
Ad

Similar to 第2回html5jゲーム部勉強会 Oh! JavaScript 夢の続きを語ろうよ〜emscriptenの逆襲 - html5編 (14)

PDF
超連射68K 開発日記 -弾幕世代以前の90年代 STG のこと-
PDF
XNAとはなにか?XNAうれしいところ、うれしくないところ
PPTX
日本ゲーム産業史概説
PDF
チームグリグリ メンバーの個性を生かすゲーム作り
PDF
ゲーミングプラットホームのLutris
PDF
GTMF 2016:『刺青の国』 ~SpriteStudioとUnityで開く背徳の宴~ 株式会社ウェブテクノロジ
PDF
開催趣旨・00年代イントロ・パネルディスカッション資料
PDF
Xbox LIVEインディーズゲーム「ピアレビュー攻略」のためのXNAにおける開発のコツと特有の課題
PDF
CEDEC2014 セッション資料「ヘキサドライブ流 OPTPiX SpriteStudio 最適化術!」
PPTX
マリオシーケンサをポケミクに対応した
PDF
次世代ゲームにおける自動生成技術
PDF
【Unite 2017 Tokyo】ゲームAI・ゲームデザインから考えるゲームの過去・現在・未来
PDF
20180330 ガチラボ
PDF
JSAI コミック工学SS 招待講演「機械学習で eBookJapan を加速できるか?」
超連射68K 開発日記 -弾幕世代以前の90年代 STG のこと-
XNAとはなにか?XNAうれしいところ、うれしくないところ
日本ゲーム産業史概説
チームグリグリ メンバーの個性を生かすゲーム作り
ゲーミングプラットホームのLutris
GTMF 2016:『刺青の国』 ~SpriteStudioとUnityで開く背徳の宴~ 株式会社ウェブテクノロジ
開催趣旨・00年代イントロ・パネルディスカッション資料
Xbox LIVEインディーズゲーム「ピアレビュー攻略」のためのXNAにおける開発のコツと特有の課題
CEDEC2014 セッション資料「ヘキサドライブ流 OPTPiX SpriteStudio 最適化術!」
マリオシーケンサをポケミクに対応した
次世代ゲームにおける自動生成技術
【Unite 2017 Tokyo】ゲームAI・ゲームデザインから考えるゲームの過去・現在・未来
20180330 ガチラボ
JSAI コミック工学SS 招待講演「機械学習で eBookJapan を加速できるか?」
Ad

第2回html5jゲーム部勉強会 Oh! JavaScript 夢の続きを語ろうよ〜emscriptenの逆襲 - html5編