まるまるこふこふ

数々の次元が崩壊し、全ての生命が塵と化すのを見てきた。私ほどの闇の心の持ち主でも、そこには何の喜びも無かった。

Electron で手動GCを行う

さいです。
JavaScript と Electron でPC向けの弾幕シューティングゲームを作っています。
C++ と違って JavaScript はGarbage Collection (以降GCと呼称)がある言語なので、
ゲームプレイ中に不定期にGCが発生して、ゲームのパフォーマンスが悪化することがあります。

Object pooling を使って、GCの回数は減らす努力はしているのですが、
それでも(恐らく)GCの発生によって、古いPC等では露骨に画面が止まることが
あるので、Electron上で GCのタイミングを調整したいなぁと思いました。

Electron は Chromium ベースのプラットフォームであり、
Chromium は v8 エンジンを使用しています。
v8 エンジンのGCは Mark-Sweep 方式でのGCです。

v8 エンジンが自分で判断して行うGCを止める方法は
調べたのですが、無さそうです。

よって仮説として、メモリが潤沢にある環境であれば、オブジェクトが必要なくなってもすぐにオブジェクトへの参照を切らずにしておき、リザルト画面などのタイミングで不要なオブジェクトへの参照を切って、それからすぐに手動でGCを発生させることで、ゲームプレイに支障が出る場面でのGCをなくせそうです。

というわけでやっとこの記事の本題に入りますが、Electron 上で
手動GCを行う方法を書きたいと思います。

–expose-gc フラグを立てる

const electron = require('electron');
const app = electron.app;
app.commandLine.appendSwitch('js-flags', '--expose-gc');

app.on('ready', () => {
  // Your code here
})

app.commandLine.appendSwitch('js-flags', '--expose-gc'); を実行することで、Electron のレンダラプロセス上で global.gc() 関数を実行することができるようになります。

メインプロセス上のコードで app に対して、ready イベントが発火するまえに、app.commandLine.appendSwitch() を実行することで、
js-flags に引数を渡すことで、Electron の v8 エンジンに対して--expose-gc フラグを渡すことができます。

この辺は、公式の docs に記載されている。

github.com

global.gc() の実行

上記の方法で、v8 エンジンに --expose-gc フラグを渡すことで、
Electron のレンダラプロセス上で、global.gc() が実行できるようになります。

// 手動GCの実行
if (global.gc) {
    global.gc();
}

サンプルコード

サンプルコードを書いて、GCが行われているか確認してみます。

メインプロセス

// electron エントリポイント
'use strict';
const electron = require('electron');
const app = electron.app;
const dialog = electron.dialog;
const BrowserWindow = electron.BrowserWindow;
const globalShortcut = electron.globalShortcut;

app.commandLine.appendSwitch('js-flags', '--expose-gc');


let mainWindow;

function createWindow () {
        mainWindow = new BrowserWindow({
            "width":          640,
            "height":         480,
        });

    mainWindow.loadURL(`file://${__dirname}/index.html`);
    // Open the DevTools.
    mainWindow.webContents.openDevTools();

    mainWindow.on('closed', function () {
        mainWindow = null;
    });
}

app.on('ready', createWindow);

app.on('will-quit', () => {
    // Unregister all shortcuts.
    globalShortcut.unregisterAll();
});

app.on('window-all-closed', function () {
    if (process.platform !== 'darwin') {
        app.quit();
    }
});

app.on('activate', function () {
    if (mainWindow === null) {
        createWindow();
    }
});

レンダラプロセス

'use strict';

var Game = function() {
    this.frame_count = 0;

    this.bullets = [];
};
Game.prototype.run = function() {
    requestAnimationFrame(this.run.bind(this));

    this.frame_count++;

    // create
    for (var i = 0; i < 100000; i++) {
        this.bullets.push(new Bullet());
    }
    // run
    for (var j = 0; j < this.bullets.length; j++) {
        this.bullets[j].run();
    }

    // reset
    this.bullets = [];

    if (this.frame_count % 600 === 0) {
        if (global.gc) {
            console.log("done gc");
            global.gc();
        }

        console.log(process.memoryUsage().heapUsed);
    }
};

var id = 0;
var Bullet = function() {
    this.id = id++;
    this.frame_count = 0;
};
Bullet.prototype.run = function (){
    this.frame_count++;
};

window.onload = function() {
    var game = new Game();
    game.run();
};

レンダラプロセスは、1フレーム毎に、Bullet オブジェクトを10万個生成しては、その場で破棄しています。
また10秒に1度、GC を実行して、それからヒープ領域の使用量を console.log で出力しています。

f:id:sairoutine:20170513220817p:plain

上記が実行結果です。10秒ごとに GC が実行されているため、
そしてGC 実行後のヒープ領域は常に最小になっています。

f:id:sairoutine:20170513220823p:plain

こちらが、js-flags を追加しなかった場合です。
追加しなかった場合、レンダラプロセスには global.gc() 関数は存在しないので、
GC は実行されずに、ヒープ領域の使用量も不定(レンダラプロセス側の v8 エンジン任せ) となっています。

最後に

この記事を書いていて思ったのですが、メモリ解放対象のオブジェクトがなくとも、
GC時のルートオブジェクトからマーク済みオブジェクトを探索していく処理が、
ゲームに影響を与えるレベルの処理だと上述の方法は意味ないですね…

v8 エンジンが何を持ってGCを走らせてるのか知りたいなと思いました。

告知ツイートをするときに気をつけていること/考えていること

こういった同人誌即売会において、 Twitter 告知をする際に、僕が気をつけていること/考えていることを 言語化して文章にまとめておきます。

僕は同人ゲームを作る人なので、同人ゲームの頒布の際の告知という前提があります。

メッセージ

入れなくちゃいけないもの

  1. いつ頒布するの?
  2. どのイベントで頒布するの?
  3. スペース番号
  4. 作品名
  5. 体験版 or 完成版?
  6. ゲームを一言で表す紹介文

なるべく入れた方がいいもの

  1. 委託があるかどうか
  2. (あれば)特設サイトURL

やるべきこと

  1. 関わってくれた人の名前を上げる

イラストや音楽を他の人に依頼したならば、その旨を、告知へのリプライなどで書きます。 作ってくださった方および、その方達のファンへの敬意を込めて。

告知時間

18~23時くらいに告知ツイートするのが、一番人がTwitterを見ている時間だと思うので、効果的だと思います。

ただ、休日はみんな外出しているからか、その時間はあまり皆Twitterを見ていないイメージ。

また、平日の12時も案外効果的(お昼休みで皆Twitterを見る)

というわけで告知時間は、平日の12時と、18~23時くらいが良さそう。

最初の告知日

イベント開催日からあんまり事前に始めても、みんなまだサークルチェックを行っていないので、 RTとかしてもらえないイメージ。

例大祭(東方Projectオンリー同人誌即売会)であれば、イベント日の3週間前から ちらほらと告知ツイートを見始め、2週間前〜1週間前くらいが告知ツイートの ピークのように見えます。

というわけで、イベント日の2週間前〜1週間前くらいには、 告知ができるようなスケジュールで制作を進められるといいですね。

告知頻度

あまりうっとおしくならないよう、1日1度、告知ツイートをセルフRTする。

サンプル画像

表紙 or パッケージに使うタイトル画像1枚 + ゲームのサンプル画像3枚。

同人ゲームは「中身のわからないものは買いたくない」というのが顕著なコンテンツなので、ゲーム内容についてはネタバレを極力恐れず、惜しみなく画像を提供する。

観点として、 1. どういうプレイをするゲームなのか? 2. どういう点が魅力なのか?

がわかるように画像を選定します。

RT先の反応を見る

僕は、RTされたら、その人のホームを見に行っています。 何かしら告知ツイートに言及がされてるとスゴク嬉しいです。

RTやfavの反応があると、もっと反応が欲しいなあと思うし、 反面、ガッカリされないように頑張ります。

人からの反応を確かめるのは、こうしたコンテンツ制作における 心の栄養だと思います。

一方で、こうした承認は麻薬にも近く、 告知ってツイートしてからその日中、ちょくちょくRTやfavの反応があるので、 ついついTwitterを見てしまって作業が止まりがち・・・。これは反省。

告知は所詮告知

結局告知がどうだろうがゲーム本体の魅力がちゃんとないと、 ゲームは手にとってもらえません(当たり前ですが)。

他の人にもシェアしたくなるコンテンツというのは、 単純なクオリティの高さも一つの指標だと思いますし、 今のトレンドに沿っているとか、あるいは今までに無かった斬新さもあるでしょう。

告知は所詮告知。

最後に

これらは全て僕の所感であり、僕がただやってることに過ぎません。 もしもっとよりよい方法や知見があれば、教えて頂けますと幸いです。

ストレングスファインダーをやってみた

こんにちは、さいです。
ストレングスファインダーというツールがあります。
「あなたの強みを分析しましょう!」というツールです。
皆さんの中にも就職活動の際に、「あなたの強み分析」「適職診断」とかで
そういうのをやった人もいるかと思います。

ストレングスファインダーは、ああいったツールの、
もうちょいいい感じのアドバイスなり情報をくれるツールです。

さあ、才能(じぶん)に目覚めよう―あなたの5つの強みを見出し、活かす

さあ、才能(じぶん)に目覚めよう―あなたの5つの強みを見出し、活かす

上記の本を購入するとアクセスコードを手に言れることができて、
34の強みからあなたの強みTOP5を分析しますという診断が行える(アクセスコードは1度しか使えないので中古じゃダメだよ)。
さらに8000円ほど払うと、34の強みランキング全部見られる。

僕の診断結果は以下でした。

  1. 指令性
  2. 競争性
  3. 内省
  4. 収集心
  5. 達成欲

指令性

「指令性」という資質によって、あなたは主導権を握ります。ほかの人と違い、あなたは自分の考えを他人に強く主張することを苦痛とは感じません。それどころか、ひとたび考えが固まると、あなたはそれをほかの人に伝えずにはいられません。そしてひとたび目標が定まると、あなたはほかの人をそれに同調させるまで安心できません。あなたは対立に怯えることはありません。むしろ、対立は解決策をみつけるための第一歩であることを知っています。ほかの人は不愉快な状況に立ち向かうことを避けようとするかもしれません。ところが、「事実」や「真実」がどれだけ不愉快なことであろうとも、それを示さなければならないと感じます。あなたは、課題が人々の間で明確に理解されていることを求めます。従って、あなたは人に、偏った考えを持たず正直であることを要求します。あなたは彼らにリスクに挑戦することを迫ります。彼らを怖がらせることすらあるかもしれません。これを嫌って、あなたのことを頑固と呼ぶ人もいるかもしれませんが、一方で、進んであなたに主導権を握らせることもしばしばあります。人々は、立場をはっきりと示し、周りの人にもある特定の方向に向けて行動するように求める人に魅力を感じます。だから、人々はあなたに惹きつけられるでしょう。あなたには強い存在感があります。あなたは「指令性」を備えた人です。

おぉ、すごい、自分で自覚してたパーソナリティとピッタリ!
僕は周囲の人間より自分が一番確度の高いことを知ってる/決められるとかいう
だいぶ傲慢なことを思ってる人間なので、この「指令性」が高いというのは納得。

診断結果から、各強みの詳細な情報が見られるんだけれど、
そこで「指令性」について以下のように述べられてる。

指令性という資質を持つ人には、強い存在感があります。状況の主導権を握り、決断を下します。 危険に遭遇したときにも対処できる才能を持っていることを知っています

あーそうそう。現在/未来が不確定でも、確度を高く「決め」と「行動」が出来るのは 指令性が高い人の強みの一つだと思います。実は世の中の人の多くは、わからないことに対して、 「自分が決定を下して責任を追いたくない」「確実でないことに不安になる」といった思いを持っています。 そういった人たちに対して「こうすればうまく行くよ!」と、方針を立てて導けるのは「指令性」の高い人の強みの一つだと思います。

言った内容や言い方によっては、他の人を怖がらせることがあります。おそらくこの効果を利用して、他の人を動かして自分の要求を通しているでしょう。

そうそう。自分の言うことを相手に正しいと思わせるために、自分の影響力を高めようとするんですけど、 それは時として相手を萎縮させてしまうんですよね。正しいことは頭でわかってるんだけれど、身体で実行できないという心情が人間は往々にしてあるので、それに対する共感とか尊重は必要です。

自ら進んで障害を解消してください。他の人は物事を進めるために、あなたの自然な決断力に頼ります。 あなたが障害物を取り除くと、あなたなしではありえなかった新しい機運と成功を生み出すことも珍しくありません。

これは今まで自分は出来てなかったことだなって思います。「決定」が出来て、人をその方向に向かせることができること、そして「決定」を実行するに当たって邪魔な障害を取り除くことは大切にしていきたい。

大義を掲げ、それを貫きます。 抵抗勢力の中で大義を守り抜くという場面で優れた能力を発揮するでしょう。

これも自分は出来てなかったこと。大義を掲げるに当たって、人々が共感できる大義を作ることはとても大切なのですが、自分は出来ていないので、大義を掲げていきたい。

「指令性」に関するいくつかの文章を抜粋しましたが、まだまだたくさんあります。
読みながら、自分が出来ていること/出来てないことが明確になっていきます。

ちなみに、私の強みTOP5のうち、「指令性」以外の、4つですが、
「競争性」は人と切磋琢磨すること、「内省」は考えたり議論したりすること、「収集心」は、知識を求めること、「達成欲」は、多忙で生産的であることですね。

ソフトウェアエンジニアなので、「内省」「収集心」が高いことは納得なのですが、
「競争性」「達成欲」は、どちらかと言えば営業職とかそういうタイプっぽいのが面白いです。

というわけで、ストレングスファインダーの紹介でした。
全ての能力において万能な人はいません。自分の弱い部分は他人に補ってもらって、
自分の強い部分をより伸ばしていくことが、結果的に社会全体の効用最大化に繋がるのではないでしょうか。

2016年振り返り

お仕事

既存サービスに対して、割りと大型の新規機能追加とかやってました。 プランナー1名、デザイナー1名、エンジニア2名で、期間6ヶ月くらいの案件です。

要件的にフロントエンドをしっかりとやらないといけない感じだったので、 WebSocket による常時接続と、JavaScript フレームワーク Mithril を導入しました。

サーバーサイドについては、DDD(ドメイン駆動設計)に基いて設計しました。

新技術の導入であったり、6ヶ月という弊チームではあまり知見のない期間での開発でしたが、 スケジュール的な遅延もなく、また大きな障害もなくリリースすることができました。

一方で、新規機能についてのユーザーは評価が悪く、売り上げが伸び悩みました。 ソフトウェアエンジニアとしての私の能力として、「どう作るか」については、 割りと知見ができてきたのですが、「何を作るか」については、まだまだ稚拙であり、 そうした弱点が露骨に出てしまった結果だと思います。

登壇

カンファレンスや勉強会などで登壇して発表する機会を頂けました。

GameServerDevelopers
Grand Frontend Osaka 2016
JavaScript Performance
ichi-pixel

Mithril

SPA(Single Page Application) 作りたくて、一方 React とか Angular とかがピンと来てなかったのですが、 Mithril に出会い、あっという間に手に馴染んでしまいました。

MVCフレームワークかつ仮想DOMかつ最小限のAPI数で、サーバーサイドアプリケーションの開発と ほぼ同じ概念で学習できるので、何度も言いますが、あっという間に手に馴染んでしまいました。

個人プロダクトや、社内向けプロダクトで色々使ったり、また仕事でも導入したりしました。 代表作は今のところ yukkuri talker という 俗に言うゆっくりボイスをweb上で作成できるサービスです。

同人シューティングゲーム

2月くらいに toho-like-js という JavaScript 製のシューティングゲームを見つけて、ソースコードを読んでました。 3月いっぱい、読んだコードを踏まえて、自分で一度再実装してみたりとかしてました。

それはそれで HTML5 におけるゲームの創り方及びシューティングゲームの創り方がわかってよかったねという話でしたが、 6月くらいに「全ゲ連 交流会」というのに参加し、 そこで、東方Projectオンリーイベント「博麗神社秋季例大祭」にて東方2次創作ゲームの合同試遊コーナー『博麗電脳試遊会』の存在を知りました。

そこで、主催の方に色々教えて頂き、試遊コーナーにてシューティングゲームの体験版を出す話になりました。 (この時点で私は一度もゲームを作ったことがなかったので、今でも自分で驚いています)

結果、UIデザインやイラスト、ドット絵、音楽など、色々な人の手を借りて、 10月の秋季例大祭で体験版の頒布、及び12月のC91冬コミで完成版を頒布することができました。

NES エミュ

3月くらいから NES エミュレータを作ってました。 コンピュータ・アーキテクチャの勉強になりました。

これはブログ記事もバズって、とても楽しかったです。

sairoutine.hatenablog.com

OSSコントリビュート

大きなOSSでは、Mithril と Electron にコントリビュートしてました。 自分が使用していて遭遇したバグのfixとか、ほしいと思った機能の追加が主にコントリビュートの仕方でした。

自分がどう変わったか

今までの自分の行動(技術の勉強とか)って成長意欲に基づく手段的な善だったわけです。 それが、NESエミュレータを作ったり、toho-like-js のコードを読んだりすることで、 それらの行為自体が純粋に楽しいという、手段的善から内在的善に変わるブレイクスルーがありました。

こうなるともう強いもので、コンピュータに関わることを、楽しいという理由だけで インプットやアウトプットを継続できるようになるわけです。

そして、そういったコンピュータに関わることは、自分が楽しいだけのただの自己満足であり、 それを人々に向けて活かす方向性が見えました。

僕の人生はオタクカルチャー/コンピュータエンジニアリングの2つで構成されているわけですが、 この2つが、ゲーム作りという行動によってようやく交差し結びついて一つのシナリオになってきた気がします。

今は作りたいものがたくさんあります。きっと作ることで、技術的なチャレンジも多々できるし、 それは元々僕が所属していた Web エンジニアコミュニティにも何かしら還元できるでしょう。多分。

これから

ゲームエンジンアーキテクチャの勉強

元々コンピュータの低レイヤに興味があって、 OSとかメモリとかCPU周りの情報収集はしておりましたが、 いまいちどういうアウトプットをすればいいのかわからずピンと来てませんでした。

最近、ゲームエンジンアーキテクチャに触れて、そういう低レイヤの知識とか興味を 活かしつつ、アウトプットする(ゲームエンジンを作る/既存のゲームエンジンを改修する)という道が あることを知ったので、やっていきたいと思います。

2D に関しては一通りやった気がするので、次は、3D と物理エンジンをやりたいです。

ブログ記事書く

自分はブログ記事を書くのが苦手(全然バズらない)と思って、あまりやらなかったのですが、 下記のように自分の知見を書いたところ結構たくさんの人に見てもらえたので、 もっと継続して人に見てもらえるような記事をたくさん書いていけたらなと思います。

sairoutine.hatenablog.com

ゲーム作る

やっていきます。オタクカルチャー大好き。 1本作ってみてちょっと思ったのが、僕のゲーム観って下記らしいので、 それに基いて作っていけたらなと思います。

・初心者でも簡単にできるゲーム
・同人誌みたいなゲーム
・ゲームは所詮音楽とイラストのプラットフォームでしかない

何か Web 関連のプロダクトを作りたい

一応 Web の人間なので1個くらいは年内に Web サービス的なものを作りたいなと。 一応サーバーサイドの人間なので、サーバーサイドアプリケーションとか、 サーバー構築/運用周りはやっておきたい。

TechLead

お仕事の話ですね。最近下記のような記事を読んで影響を受けました。

http://d.hatena.ne.jp/higepon/20150806/1438844046

同人サークルをよくしていきたい

同人ゲーム作るにあたって、同人サークルというのもやっているのですけれど、 これをよくしていきたいですね。色々考えてます。

「とにかく数を作ってリリースし、制作ノウハウを貯める」
「ゲームは最終的に規模とクオリティ勝負になってくるので人を増やす」
「ゲームを作りたいけど作れない人に、作れる場を提供する」
「属人化しないゲーム制作体制を目指す。究極的には僕がいなくてもサークルのリソースを使ってメンバーがゲームを作れるようになる」

とりあえず思う所を挙げてみたら、スケールさせることばかり考えてて笑った。 ゲーム制作って、最低でもイラスト/プログラム/音楽の三職種居ないといけないし、 欲を言えばシナリオライターとかディレクターとかスクリプターとか色々居て欲しいので、 どうしてもスケールすることを考えてしまいます。

技術採択のときにやるべきこと

初めに

新規プロジェクト/既存プロジェクトで、新しく使う ライブラリだったり、フレームワークだったり、ミドルウェアを選定してきた経験を通して、 採択する段階でこれはしておいた方がいいなという知見が溜まったので、 メモ書き程度に記述します。

前提として、技術採択についてある程度メンバーに裁量が任せられている風土があり、 かつミッションクリティカルでないシステムに導入する、また自社で事業を行っており、 顧客=ユーザーであるというのがあります。

(この辺の前提条件が違う場合、採択に当たってまた別の観点が必要になってくると思います)

システム要件を満たしているかどうか

なんだかフワっとした言い方になりましたが、例えば Web システムに JavaScript のライブラリを 導入する場合に、Web システムが IE8 に対応するという要件ならば、 そのライブラリが、IE8 でも動くか調査するということです。

これをやらないと、開発期間の後半になって、システム要件を満たさないことが発覚して、ライブラリの変更及び実装したコードの破棄をするとかいう地獄になります

私の場合、例えば JavaScript のライブラリを導入する際は、Github の issue を見て、 ブラウザ依存のバグレポートを検索したりとか、ライブラリを使って簡単なアプリを作ってみて、 社内の検証用端末すべてで一通り動くかどうかチェックしたりします。

採択理由のドキュメント化

ライブラリの採択理由について、きちんと文字に起こして社内のwikiなりなんなりに みんなの見えるところに置いておきます。採択に当たっての関係者説得のために 書かざるを得ないのが大抵でしょうが、求められなくてもきちんと書いておきます。

ドキュメントを書く際の観点は以下です。

  1. なぜ導入するのか?
    →どういう課題を解決するために導入するのか、あるいはどういう効果を見込んで導入するのか書きます

  2. 類似のライブラリ/フレームワークミドルウェアの調査
    →例えば JavaScriptフレームワークなら、 Backbone とか Angular とか React とか、 色々な種類があります。それぞれのフレームワークについて、特徴やプロジェクト導入に当たってのメリット/デメリットを調査します。

  3. 選定の観点
    →自チームに導入する際のより細かい要件について洗います。「1. なぜ導入するのか?」にて、 大まかな要件については洗えていると思うので、「類似のライブラリ/フレームワークミドルウェアの調査」にて調査した もののうち、どれか一つを選べるレベルには細かい要件を洗います。

  4. 結論
    「3. 選定の観点」で記載した観点に従って、「2. 類似のライブラリ/フレームワークミドルウェアの調査」のもののうち、 どれを選定したのか結論を書きます。

これをやらないとプロジェクトが終わった後、導入して良かったのか/悪かったのかが振り返れません

採択したいものを使ったプロダクトを1つ作る

社内向けシステムでも、個人プロダクトでも良いので、採択したいライブラリ/フレームワークミドルウェアを使って、 プロダクトを一つ作ります。ToDoアプリレベルではなくて、できれば人に使ってもらえるレベルのプロダクトを作りたいところ。

これをやらないと導入してみたもののよくわからなくて作りきれないというのが発生します

いやご冗談をと思うかもしれませんが、他の人の話を聞くと、たまにあるねん……

その他"必ず"ではないけど"できれば"導入に際してやっといたほうがいいこと

上記3つは、必ずやっておいた方がいいことです。 以下2つは"必ず"必要なのかちょっとまだ判断しかねていることです

フレームワークミドルウェア/ライブラリ自体の実装の理解

フレームワークミドルウェア/ライブラリ自体のバグを踏んだ際に、原因の特定に時間をかけずに済んだり、 フレームワークにパッチを当てるあるいは、フレームワーク自身にバグfix のプルリクを送る等の対処が可能になります。

導入を手伝ってくれるメンバーを自分以外に2名作る

TED Talk に「How to start a movement」というのがあります。 ムーブメントとは3人揃うとそこから加速的に賛同する人が増えるよって感じの話です。

技術導入は、常に「本当にやる必要があるのか?」「やっぱり止めたほうがいいのでは」という周囲の目線に晒されます。 一人で導入を進めていると、そういう目線に負けやすいので、そういう時に一緒に戦ってくれる仲間がいると、導入が進めやすいです。

Live2D + Electron でデスクトップマスコット作って同人誌即売会で頒布してきました

標題の通りです。まずはこちらをご覧ください。

東方Project という同人ゲームに登場する「宇佐見蓮子」さんの
デスクトップマスコットアプリを作りました。デスクトップ上で動きます。
クリックすると、何かしらの色々な反応をしてくれます。

2016/10/30 の科学世紀のカフェテラスという同人誌即売会で頒布してきました。

Live2D

Live2D WebGLとNW.jsでデスクトップマスコット

Live2D については上記の記事を参考に実装させていただきました。

公式サイトで WebGLSDK が提供されているのでそれを使用しました。
Live2D Cubism SDK 2

Live2D WebGL SDK の解説については下記のスライドがわかりやすいと思います。

Live2D WebGL SDK入門

Electron

デスクトップマスコット用に、ウィンドウ表示を無くし、
背景を透過して、常に最前面に表示する方法ですが、

 mainWindow = new BrowserWindow({
      "transparent": true,  // ウィンドウの背景を透過
      "frame":       false, // 枠の無いウィンドウ
      "resizable":   false, // ウィンドウのリサイズを禁止
      "hasShadow":   false, // 残像が残らないようにする(Mac only option)
      "alwaysOnTop": true,  // 常に最前面
    });

BrowserWindow 作成時に、上記のオプションを設定することで、
簡単に実現することができます。
なお、hasShadow オプションですが、Mac ではデフォルトで、
ウィンドウに影が付くようになっており、このオプションがオンのままだと、
Live2D モデルのモーションに残像のようなものが残ってしまいます。
オフにしましょう。

上記 Qiita の記事では、NW.js を使ってデスクトップアプリ化しているため、
XMLHttpRequest でなく、fs を使ってモデルファイルをロードしていますが、
Electron においては XMLHttpRequest でロードできます。

このため、Electron のメインプロセスのAPIを使用する必要がなく、
レンダラプロセスのみで完結するため、開発中はブラウザ上でマスコットを表示し、
完成後に Electron で build して完成としました。

ライセンス

Live2D のライセンスは結構ややこしいです。下記の内容は 2016/10/30 時点のものです。
最新の内容は、公式サイトをご確認ください。

本デスクトップマスコットアプリは、同人サークルとして頒布したものです。
直近売上高が1000万未満の同人サークルであるため、「一般ユーザー」として
使用することになります。

一般ユーザーであれば「iOS, Android, Flash, DirectX, Unity, Cocos2d-x, WebGL」のSDKを、
商用/非商用問わず利用することができます。

インディークリエーター向けにLive2D Cubismを無償提供。商用利用も可能

DLカード

同人誌即売会での頒布は、DLカード(ダウンロードカード)を
作成して頒布する方法を取りました。

対面電書という Webサービスにて、
ファイルのアップロード及びシリアルコードの発行を無料で行うことができます。
こうして発行したシリアルコードを、バリアブル印刷対応の印刷所(印刷のウェーブ様等)にてカードの印刷を発注しました。

ポストカード(オンデマンド、両面フルカラー)+バリアブルテキスト印字オプションで、
200部だいたい8000円くらいのお値段です。

メール便に対応しているので、注文から手元に届くまで
だいたい4営業日くらいというスピード感です。

感想

Mac を会場に持ち込んで、実際に動いてる様を展示していたのですが、
「すごい」「こんなことができるんだ」といった反応をたくさん頂けました。
(エンジニア冥利につきます)

Live2D を使った作品を作る上での課題は、
やはり元のイラストをどう用意するか、
そしてそのイラストをどうやってモデル化するかだと思います。

今回はそのどちらもを他の人にお願いしてしまったので、
私はモデルとモーションを組み合わせただけなのですが、
逆に言うと、モデルさえ用意してしまえば、このような
デスクトップマスコットアプリを作ることは結構サックリとできます。

JavaScript 製ファミコンエミュレータを公開しました

公開しました(過去系)

github.com

Demo

FaithJS

Screenshot

作ろうと思ったきっかけ

コンピュータの仕組みについて知りたいなら NES エミュ作るのが手っ取り早いと、 優秀な人が強い事を言ってて、僕もコンピュータの仕組みについて知りたかったので、 実装しようと思いました。

まず読んだ本

コンピュータシステムの理論と実装 ―モダンなコンピュータの作り方

CPUやメモリの仕組みを大まかに知ることができる

30日でできる! OS自作入門

OSの仕組みやアセンブラの基本がわかる

自作エミュレータで学ぶx86アーキテクチャ コンピュータが動く仕組みを徹底理解!

こちらもアセンブラに慣れるために読んだ

たのしいバイナリの歩き方

バイナリに慣れるために読んだ

コンピュータの仕組みについて何も知識がなかったので、上記の本を読んで勉強しました

参考にしたサイト

NES on FPGA +そんなベタなファミコンはイヤだ!+

Nesdev wiki

実装してみての感想

OS自作系の知識を応用して、CPUの実装までは容易にできる。その後 PPU APU等の 描画や音楽周りになってくると、ドキュメントを読んでも理解できないことが多かった。

ドキュメントを読んでも実装のイメージがまったく湧かなかったので、 とにかく他人が既に実装したコードを読み漁った。 人によって実装内容が異なり、また実装によって動くROM動かないROMが異なるので、 何を正にすればいいのか戸惑った。

スライド

JavaScript の勉強会で発表した内容です。

www.slideshare.net

他の人のJavaScriptNESの実装

JavaScript FCエミュレータ

GitHub - peteward44/WebNES: NES emulator in Javascript using HTML5 WebGL or canvas. Optimised for Chrome's V8 engine

http://takahirox.github.io/nes-js/index.html