ハッピーライフ (feat. nicamoq)

Posted on

たまには曲の話をしようと思います。

曲調やジャケットはいわゆる原宿系?なかわいらしい感じ。
タイトルは「ハッピーライフ」。それに相応しく?クラブハウスで皆でノリノリになれそうな、アッパーなテンポの曲です。

しかしながらそんな表層に騙されるなかれ。

歌詞は
どうしようもなくダウナーで、
どうしようもなく絶望的で、
そして…どうしようもなく現実的なのだ!!!

今日は何曜だろう

幸せも残りわずかだ
明日も朝から 隣町へと 余生を売りにいこう

いまさら いまさら 後戻りなんて無理だね
ことさら ことさら 難しいわけないんだけど

でもそれがまたかわいらしい歌手の声やアッパーな曲調と奇妙にマッチしてていい感じなんです。音楽って面白いですね。

二番になるとさらに統合失調症の隣人(!)が出てくるのですが…

お隣が また騒いでる
アルミホイルを 壁いっぱいに 輝かせてるのさ

ぼくの鳴らす電子音が 悪い電波を発してるよと
ドアを蹴り続けてる

この後、1番にはなかった、隣人がドアを蹴る様子を模した「コン!コン!」という音が執拗に覆い被さるように鳴り始めるところで変な笑いがでてしまいました。この歌詞の気が狂いそうな雰囲気を、こう表現してきたか!


作曲と作詞と編曲が分かれていることが多いですが、すべてを同じ人間がやると、こんな表現もあんな表現もできるんだ!と感心した一曲です。


そういえば。曲を作るようになってから、よく言われているような「歌詞は自分の気持ちの代弁」なんかじゃなくて、明確に鑑賞対象になった気がします。今回のブログのように。

バニラ味の人体をblenderで作った

Posted on

今日は3Dモデリングをしたよ。

vanilla-flavored-human-body.blend: Vanilla flavored human body (blender model)

バニラ味の人体」をコンセプトに、男でも女でもなく、年齢もなく、服も髪も耳1もない、そんな人体をモデリングしてみました。野望としては、これをベースに複数のキャラクターが作れたらいいなと思ってます。

3Dモデリングめっちゃ大変なのじゃー!!

先日Appleも参加したblender、楽しいですよね(雑な導入)。2.8系になって操作体系がフレンドリーになってからというもの、小物や無機物などをちょくちょくモデリングして楽しんでおりました。

だけど、たまには生物もモデリングしてみたい…でも、出ているキャラクターモデリング本はどれも古く、Blender2.8系以前の本ばかり…そんなときに出合いました:

半年程度前に出た本。もちろん、Blenderは2.8系以降です。しかし…買ってみて驚いた。450ページ!?なんだこの鬼のような手間は!!!!心折れるわ。

「NEW GAME!」という3Dモデラーの仕事を描いた漫画2では一日一体作らせようとするシーンが出てくるのですが、…エーッ、そんなん、無理に決まってんだろ!

これはもう「才能」「努力」「慣れ」といったような言葉でなんとかなる範囲ではなく、キーボードやマウスを操作して作成する際の物理的限界として不可能だと思います。

ここで私は考えました。漫画の中では描かれていないだけで、実はベースとなるような3Dモデルが何体か会社で用意してあって、涼風青葉はそれをカスタマイズして作ったのでは、と…。

そんなわけで、今回はこんなことになったわけです。

本にはなかった苦労ポイント

トポロジーの細かい修正・変更をするときはサブディビジョンサーフェスを解除する

この本では常にサブディビジョン・サーフェスを掛けた上で編集画面上でも反映させる、という手順を踏んでいるのですが、この手順ですと細かい頂点の修正はかなり難しいです。サブディビジョン・サーフェスは頂点や辺の位置まで動かしてしまうので、ループカットの位置も表示上の位置と実際の位置はずれてしまいますし、サブディビジョン・サーフェスがきれいに頂点を並べ変えてしまうので、頂点が実際には変な位置にあったとしても気づきにくく、あとで「こんなはずでは…」が発生します。

そんなわけで、サブスクリプション・サーフェイスを解除した上でスムースシェード・フラットシェード両方で観察して、変なところが無いか洗い出す作業を定期的にするといいと思います。

細かいニュアンスの表現にはスカルプティングも併用する

胸の肋骨のふくらみなど、複数頂点にまたがるけど細かい起伏が存在する場合などは、スカルプティングを利用するのも1つの手です。この時はサブディビジョン・サーフェスを掛けておいたほうが陰影などが確認しやすくていいと思います。ただし、頂点の並び(3D業界用語としての「トポロジー」)はかなり汚くなってしまうので、上に書いたようにいったんサブディビジョン・サーフェスを解除して並び替えるとさらにきれいに仕上がります。

関節まわりは難しい!ウェイトペイントは難しい!

関節を仕込んだあと、その関節が曲がった際にどのようにメッシュを変形させるのかを指定する「ウェイトペイント」という工程が存在します。本だとかなりさらっと流されているのですが、かなり苦労しており、いまだに完全に満足する出来にはなってません。

ウェイトはポーズを付けた状態で編集する

本にはなかったのですが、ウェイトを意図通りに編集するには、実際に曲げた状態でウェイトを塗ると便利です。まげてしまった後も、アーマチュアを選択した状態でポーズモードに入り、Aボタンを押して全ボーンを選択して「ポーズ→トランスフォーム→すべてをクリア」を実行すればポーズは元に戻せるのでご心配なく。

関節の折り曲げ

この辺が詳しいのですが、例えば関節を普通に3つに割ってウェイトペイント50%にすると関節を折り曲げたときに関節が細くなってしまいます。

GUILTY GEAR Xrd開発スタッフが送るスキニングのためのモデリング TIPS

これはウェイトペイントが線形補完を使っていることに起因する問題で、うまいことウェイトペイントのパラメータを調整するだけでは原理的に対処できません。本ではこの問題に触れられていなくて、関節周りは単に3つにループカットで割った上で50%でウェイトを仕込んでいるように見えました。

273ページ

この問題の解決には関節の割り方に工夫がいります。1つ目は、補完してきれいに曲げようとするのではなく、めり込ませてやることです。ゲームのCGを観察するとたまに見かけます。

GUILTY GEAR Xrd開発スタッフが送るスキニングのためのモデリング TIPS

もう1つは、折り曲がる部分が凹むのは頂点があるからだ!ということで、降り曲がる部分には頂点を置かないという方法です。

どちらの方法も一長一短なので、好みで決めればいいと思います。ただし、どちらの方法も、サブディビジョン・サーフェスが絡むとうまくいかないことがあります。後述。

手首のねじれ問題

今ためしに手首をねじってみてほしいのですが、手首だけがねじれるわけではなくて、腕全体がねじれているのがお分かりでしょうか。解剖学の細かいところはよくわかりませんが、実際そうなってます。

もちろんしかし、Blenderはそんなところは勝手に空気を読んでくれたりはしないので、そのままだとこうなります。

ギャー!!

この辺も3Dモデリング界隈ではよく知られた問題で、手首のねじれに連動して動くような補助ボーンを設定すればうまくいきます。

しかし、この補助ボーンを動かすための設定はUnityなんかに持ってった時に消滅するっぽく、どうしようかな…と悩んでいるのが現状です。UnityのHumanoidはこの辺よしなに設定してくれるんだろうか?

いまのところ、前腕と上腕にだけ、手首に連動して回転するような設定(ボーン・コンストレイント)を仕込んでいます。

アーマチュア変形を掛けてからサブディビジョン・サーフェスを掛ける

Blenderのモディファイヤは上から順番に適用されるようで、普通に作っているとサブディビジョン・サーフェスを掛けてからアーマチュア変形が掛かります。

が、これを使うと上で述べた関節の割り方の工夫がうまくいきません。

実際の例で見てみましょう。

サブディビジョン・サーフェス→アーマチュア変形

おなかが割れてます。

アーマチュア変形→サブディビジョン・サーフェス

おなかが割れることなくお辞儀ができています。

腕の関節なども、サブディビジョン・サーフェスを掛けてからアーマチュア変形を掛けてしまうと、せっかく関節が細くならないように割ったのもむなしく、サブディビジョン・サーフェスで割られた中点のところが細くなってしまいます。おそらく「50%の罠」がサブディビジョン・サーフェスで発生してしまうせいだと思います。

が、これUnityやUnreal Engineに持ち込んだ時にはどうなってしまうのでしょう???いまのところまだめんどくさくてやってないのですが、今から頭痛が痛い問題です。

膝や肘が細くなってしまう

肘やひざの部分が細くなってしまうのもお悩みポイントです。これも、ウェイトペイントによるメッシュ変形が線形補完でしかないことに起因する問題です。

関節のボーンとポリゴンフローに関するTIPS

Blender内ではPreserve Volumeを使えばいいんですが、他のゲーム・エンジンでもこの変形機能が存在するかというと…?

メッシュは適宜修正しよう

本でもたまに書かれていることではあったのですが、ボーンの配置、ウェイトペイントなどの後工程になってからでもメッシュは適宜修正したほうがいいです。逆に言うと、どうせ修正するので100%完璧を目指してから後工程に進む意味はあんまりありません

大きなゲーム会社では分業化が進んでいて、モデリングをする人とウェイトを調整する人は別らしいのですが、どうやって分業してるんでしょう??謎だ。

Bluetoothキーボードがあると便利

わたしは腱鞘炎対策としてKINESISというだいぶ変わったキーボードを使っているのですが、こういうキーボードは文章を打つにはいいんですが、ショートカットキーを打つのにはあんまり向いてません(例えばY軸にそって移動するGYというショートカットを打とうとすると、左側と右側に分かれているのですんごい打ちづらい)。

楽天でUS配列版のLogitech K380を買って導入してみたところ、かなり快適に作業できるようになりました。道具大事。

今後の見通し

もちろんですが、まだ3Dモデルとして必要な作業はまだまだ残っています。

  • テクスチャ
  • 表情や口パク(シェープ・キー)

この辺は個別のキャラクターの個性が出るところかなと思いますので、今回のリポジトリからForkしてから作りこむ事になるのかなと思います。

「バニラ味の人体」を作るまでに200コミット近くの手間がかかっており、まだまだこれからかと思うと気が遠くなりそうですが、がんばるぞい!

あと最終的に何につかうかも実はあんま考えてなかったりします。Blenderでレンダリングして遊ぶのも楽しそうですが、モーションキャプチャしてVTuberになったりVRChatしたりしてもいいですし、UnityやUnreal Engineのゲームで活用するのも面白そうです。live2dも実は検討してたのですが、マジでVTuberにしかなれなさそうなのでやめました。

Gitでblenderのモデルファイルは管理できる!

blenderのモデルファイルは圧縮が掛かってないようで、git gcすると想像以上に圧縮が効き、リポジトリサイズを現実的なサイズのままに維持できます。200回近くコミットして、body.blendファイルは現在1.4MBくらいありますが、それでもリポジトリのサイズは20MB以下に収まっています。バイナリ・ファイルなのでマージなどはできませんが、それでもこまめにコピーを取っておく代わりにGitで管理するというのは十分に現実的なソリューションだと思います。

実際に何度か git reset –hardのお世話になりましたし、git checkout (適当なコミットID)して昔のファイルを開いて編集前はどうなってたか確認したこともあり、gitの恩恵は十分に得られていると思っています。

gitで管理できるものはgitで管理しましょう。コミットメッセージとtagがつけられるだけでもめちゃくちゃ便利ですよ。

…本当はpsdや.clipもgitで管理したい。

お絵かきおじさんとしての感想

いつも絵を描くときは、いったん頭の中で3Dで思い浮かべてから傾けて描いているので、後工程を勝手にBlenderがやってくれるのは楽だったかも。ただ、結局モデリングも2Dで行うので、頂点・辺・面の選択にはすごい苦労しました。オブジェクトが複雑になってくると、手の頂点を選択したいのにその奥に透けて見える足の頂点を選択してしまったり。そのためには画面をいったん傾けて、奥側に意図しない頂点がまったくない状態に持っていくか、透けない設定にしてぐるぐる回転して選択したりしないといけません。これが結構大変。

あとは液晶を上から見下ろしたり下から見上げたり横から覗こうとしたりしてる自分に気づきました(笑)。水族館の水槽じゃあないんだから!ゲームしてる最中に体うごく人ってこういう感覚なのかな~とちょっと理解…。

きららおじさんとしての感想

NEW GAME!は3Dモデリングのことを何も描いていない。ということがよーーーーくわかった。

…気になって読み返してみたのですが、3Dモデリングソフトウェアの描写はかなりあっさりしてて、「あっ!Mayaだ!」みたいなシーンは殆どなかったです34。そもそも画面が真っ白だったり他のキャラの頭で隠されてたり…。

3Dモデリングの話ではなく、もっと抽象的な「仕事」の物語を作ったからこそ、多くの人に共感され、「がんばるぞい!」で終わることなく、8年間も連載して、アニメも2本も制作するぐらいの人気が出たんだろうなとは思います。

…思いますが、こうしてモデリングした後だと、少し物足りないです。現役時代、得能正太郎がどんなことで悩んでいたのか、あるいは「仕事として3Dモデリングする」とはどういう事なのか、読んでみたかった感じはあります。

その他

VTuberはーーー大変なのじゃーーーー
  1. 言うまでもない事でしょうが、耳はケモミミ、エルフ耳、人間の耳などなど個性の強い一要素です []
  2. だったはずなんだけどなぁ []
  3. アニメではあります []
  4. 一方、お絵かきソフトは明らかにCLIP STUDIO PAINTなのが丸わかりだったりする []

架空のアーケード・シューティングゲーム「ムーンショット」と、そのワンポイント攻略

Posted on

ドリームキャスト互換アーケード基盤「NAOMI」で2021年10月にリリースされない横スクロール型シューティングゲーム「ムーンショット」。今回はこのマイナーなゲームのストーリーを紹介し、そのワンポイント攻略についても行っていきます。

ストーリー

安心安全帝国」 ― 生きる苦しみと不安、虚無を根絶し、安心と安全だけが満ち、全員が活躍できる社会を約束するカルト国家。もともとは極東の小国だったが、自我をもつ国家制御AIムーンショット」が2050年に完成するとすぐに、各地へ宣戦布告。あっという間に制圧し、世界中へ勢力を伸ばした。

内部では時間の止まった理想の社会≪ユートピア≫が実現されていると喧伝されているが、実態は不明。
かろうじて残る国境線付近では今でも大小さまざまな「テロリスト集団」との戦闘が続いている。

そのうちの1つに、「一切皆苦」があった。AIの力を”活用”しても活躍できないとされ「お祈り」された人間、ネガティブであるとされた思考の持ち主、不安や虚無の存在を肯定しようとする元哲学者・思想家などが集まった混沌とした集団だ。

人工知能に対抗しうる最終兵器「天然無能」を開発することに成功した「一切皆苦」は、崩壊しつつある集団の最後の力を振り絞り、「安心安全帝国」への、最後の国家解体作戦を開始する。

一切快苦」の保有する最後の戦闘機、「無明」に、帰還のための燃料の代わりに「天然無能」を積みこむ。最後の挨拶を済ませたパイロットは、明るいLEDライトのきらめく「安心安全帝国」へ退路を捨て飛び立っていく。

 

敵は≪幸福≫。

生きとし生けるものに生きる苦しみを取り戻すための「正義」の戦いが、いま始まる。

ワンポイント攻略

8方向レバー、3ボタン。全5面+真の最終ステージ1面。一周エンド。

パターン要素の強いステージと、ランダム要素の強いステージが極端に分かれています。パターン要素の強いステージで自分なりの攻略パターンを早めに構築し、ランダム要素のために気力を温存しておくのが、基本的な攻略戦略となるでしょう。

真エンド条件は「5面終了時点までノーミス」と、かなり厳しめの設定です。真エンドを見たい場合、敵をなるべくすべて撃破して、いわゆる「スペシャルアタック」のゲージをこまめに貯め、少しでも厳しいと感じたら、すぐにスペシャルアタックを発動し、付随する無敵の効果で切り抜けましょう。

 

次からは、各ステージの簡単な紹介と攻略になります。

Stage 01 「テンシ」

これが、テンシ?人喰いの、間違いじゃないのか。

回収されたフライトレコーダーから

最初のステージ、「テンシ」。このステージでは「安心安全帝国」の国民である「テンシ」が無数に襲い掛かってくる。最初のステージであることや、全員とも優しそうな笑顔を浮かべていることに油断していると、すぐに「テンシ」たちの放つ高密度弾幕に制圧されてしまう。主人公の言葉どおり、「全員を殺す」という強い気概で挑んでいこう。

Stage 02 「ナカマ」

こちら無明、…
敵も無明だ…。

回収されたフライトレコーダーから

次のステージは「ナカマ」。前回プレイしたプレイヤーが鹵獲され、「テンシ」として”生まれ変わった”という設定で襲い掛かってくる。「ナカマ」であった「テンシ」の攻撃パターンは前回のプレイヤーの動きから学習・模倣されたものになるため、ゲームセンターで待っている間も前のプレイヤーのプレイは肩越しによく観察しておこう。

Stage 03 「コウノトリ」

誰でも作れるということは、
誰にも作れなかったということなのだな。

回収されたフライトレコーダーから

第三ステージ、「コウノトリ」。国家制御AI「ムーンショット」が、「望めば誰でも安心して子供を産み育てられる社会」という人間の願いにこたえるために作った、「テンシ」の製造工場だ。「テンシ」は完成するとすぐに高速弾を放ってくるので、完成する前にテンポよく破壊していこう。登場する順番は死んで覚えるしかない。

Stage 04 「デンシン」

一人と戦っているのか、
全員と戦っているのか、

わからない。

回収されたフライトレコーダーから

第四ステージ、「デンシン」。ここの「テンシ」は全員テレパシーを使って以心伝心している。一度倒した方法は次の「テンシ」には効かない。全ての「テンシ」を破壊できるよう、倒し方のバリエーションを事前に準備しておこう。

Stage 05 「ムーンショット」

頼む、持ちこたえてくれ。

回収されたフライトレコーダーから

最終ステージ、「ムーンショット」。名前通り、「安心安全帝国」の中枢にある国家制御用AI「ムーンショット」を破壊するのがミッションだ。気象をもコントロールする人工知能が、津波、地震、土砂崩れ、台風、ハリケーンなど自然災害すら用いてステージの地形を変形させていく。弾避けに使っているオブジェクトはすぐに破壊されてしまうから注意しよう。

Stage -1 「シアワセ」

脳が痛い。胸が痛い。視界もはっきりしない。意識が朦朧とする。
俺は、一体今まで何と戦ってきたのだ。

だが、まだ生きているというのだけは分かる。
まだ戦わねばならない事もはっきりしている。

回収されたフライトレコーダーから

そして条件を満たしたときにあらわれる真・最終ステージ、「シアワセ」。

人工知能」である「ムーンショット」に対抗する「天然無能」。その名は「生老病死」であった。 この「生老病死」 を起動し、ブートが完了するまで、守り抜くのがミッションだ。残機がいくらあったとしても、死んだ瞬間に守りがほころび、ほぼ間違いなくゲームオーバーになってしまう。このステージではコンティニューもできないので、「人生は一度しかない」と念じながら最後までやりきろう。

参考資料

アナザーエンド

ラストステージは、頭のアンパンから餡が飛び散りきるまでに「安心安全帝国」の管理AI「ムーンショット」を破壊するミッションとなっている。ここだけはコンティニューできず、残基も自動的に0になるので、気合を入れて攻略しよう。たとえ、胸の傷が痛んでも。

https://sabbat.hexe.net/notice/ABuOy9yYFwEfd7EkrI

Value DomainでLet’s encryptのワイルドカード証明書を発行する

Posted on

今北三行

現状

公式では対応してなかったので、対応させるプルリクを投げてる最中です。

そのかわり、使えるようにしたDockerイメージを用意しました。マージされるまでのつなぎにどうぞ。

Dockerイメージの使い方

使うには、こんな感じのdocker-compose.yml書いて:

---
version: '3.7'

services:
  certbot:
    # つくった
    image: 'ghcr.io/ledyba/certbot-with-dns_valuedomain:latest'
    network_mode: 'host'
    volumes:
      - ./data:/etc/letsencrypt
      - ./conf:/etc/certbot

networks: {}

conf/valuedomain.ini

  • 所有者root:root
  • パーミッション0600

で作成して、Value Domain APIのページから持ってきたトークンをこんな感じでコピペして:

dns_valuedomain_api_token=(your-token)

最後にこんな感じでコマンド打って証明書を発行してもらう:

docker-compose run \
  --rm certbot \
    certonly \
      -vvv \
      --agree-tos \
      --email <your-email-addr> \
      --non-interactive \
      --preferred-challenges dns-01 \
      --dns-valuedomain \
      --dns-valuedomain-propagation-seconds=90 \
      --dns-valuedomain-credentials=/etc/certbot/valuedomain.ini \
      --keep \
      -d example.com *.example.com *.foo.example.com

renewするには:

docker-compose run --rm certbot renew -vvv

無料でワイルドカード証明書が欲しい!

TLSで暗号化せざるをえない(?)昨今、どうせ証明書を作るならワイルドカード証明書が欲しくなります。

実験で新しいウェブアプリを書いてドメイン名が必要になった時、通常のHTTP認証を使った証明書を使う場合は、実験用のドメイン用にlet’s encryptのコマンドを追加でたくさんたくさん叩かないといけません。

一方、ワイルドカード証明書ならA/AAAA/CNAMEレコードを1つか2つ追加すればすぐに使えます。

楽です。楽であることは正義です。

certbotが対応していない

certbotにはDNSプラグインなる仕組みがあり、Route53などの有名どころにはすでにプラグインが存在し、各サービスのパスワード的なものを用意すればプラグインを使ってワイルドカード証明書が発行できるとのこと。

じゃあ我らがValue Domainはどうなのかというと…

% certbot --help certonly
usage: 

  certbot certonly [options] [-d DOMAIN] [-d DOMAIN] ...

....

  --dns-cloudflare      Obtain certificates using a DNS TXT record (if you are using Cloudflare for DNS). (default: False)
  --dns-cloudxns        Obtain certificates using a DNS TXT record (if you are using CloudXNS for DNS). (default: False)
  --dns-digitalocean    Obtain certificates using a DNS TXT record (if you are using DigitalOcean for DNS). (default: False)
  --dns-dnsimple        Obtain certificates using a DNS TXT record (if you are using DNSimple for DNS). (default: False)
  --dns-dnsmadeeasy     Obtain certificates using a DNS TXT record (if you are using DNS Made Easy for DNS). (default: False)
  --dns-gehirn          Obtain certificates using a DNS TXT record (if you are using Gehirn Infrastructure Service for DNS). (default: False)
  --dns-google          Obtain certificates using a DNS TXT record (if you are using Google Cloud DNS). (default: False)
  --dns-linode          Obtain certificates using a DNS TXT record (if you are using Linode for DNS). (default: False)
  --dns-luadns          Obtain certificates using a DNS TXT record (if you are using LuaDNS for DNS). (default: False)
  --dns-nsone           Obtain certificates using a DNS TXT record (if you are using NS1 for DNS). (default: False)
  --dns-ovh             Obtain certificates using a DNS TXT record (if you are using OVH for DNS). (default: False)
  --dns-rfc2136         Obtain certificates using a DNS TXT record (if you are using BIND for DNS). (default: False)
  --dns-route53         Obtain certificates using a DNS TXT record (if you are using Route53 for DNS). (default: False)
  --dns-sakuracloud     Obtain certificates using a DNS TXT record (if you are using Sakura Cloud for DNS). (default: False)

してなーい!

じゃあさせるぞ!

Certbotが依存しているlexiconを対応させる

一番最後の行に出てるsakuracloudが一番近そうなので、これを適当に模倣します(プルリク)。

仕組みがどうなってるのかよくわかんないんですが(笑)、実装であるlexicon/providers/valuedomain.pyと、そのテストlexicon/tests/providers/test_valuedomain.pyを用意すれば基本的には終わりです。

あとはこのコードが正しいかどうか調べるためのユニットテストを通すために、tests/fixtures/cassettes以下にテスト用に通信を記録したファイルを配置しないといけないんですすが、これはルートフォルダにあるtox.ini

setenv =
    PYTEST_ADDOPTS = {env:PYTEST_ADDOPTS:--numprocesses auto}
    PYTHONHASHSEED = 0
    LEXICON_VALUEDOMAIN_AUTH_TOKEN = <token>
    LEXICON_LIVE_TESTS = true

みたいな感じで書いとくと勝手に生成されるようになります(どこにも書いてなかったのでメモ)。ただし、結構ユニットテストの数が多くてレートリミットが掛かってしまうので気をつけて…。その時はレートリミットのせいでエラーになったテストのファイルだけ削除してテストを再実行すればOKです。ファイルを削除したテストだけ、実際のHTTPリクエストが発生するのでレートリミットが掛からなくなります。

toxがオールグリーンになったのでおしまい。次いこう次。

Certbotはほとんどlexiconに丸投げ

certbotに関してもほぼSakuraCloudプラグインをコピペしてvaluedomainにrenameしているだけです。正直いうとgrepしてsakuracloudの文字列がないか調べて片っ端からvaluedomainに書き換えてるだけに近しい。

びっくりするぐらいとくに何も言うことがない。おしまい。

Dockerがあるから自分で改造したコードを使うのが楽になった

コードを変更したら、それが取り入れられる前に自分の手元で簡単に動かして実際に使えるようになったので、楽な時代になったなぁと思いました(こなみかん)。Docker imageを作ってしまえば、冒頭に書いたように公式の用意したdockerイメージの名前を自前のものに書き換えるだけであとは同じように使えます。

昔だったら…そうさね、Virtualenvみたいなので済めばいいけど、サーバに色々細工して環境を汚しまくらないとダメだったかもわからんね…。

SHA256でデータが混ざる様を”混色”してみた

Posted on

暗号学的ハッシュ関数、使ってますか。わたしはよく使ってます。たとえば、このブログでは画像のファイル名として、その中身をMD5ハッシュに掛けたものを使っています(そういうWordPressプラグインを作りました1

で、今日は暗号学的ハッシュ関数の中でもまだまだ現役のものの1つ、SHA256でデータが混ざり合う様を色を使って可視化してみました:

githubリポジトリはこちら:

今回はCanvas 2Dを使ってます。実際に動くデモサイト

入力は512ビット

SHA256は入力として512ビット( = 32bit × 16)の「ブロック」を単位としてを受け取りながら計算します。今回は便宜上、1ブロックだけ与えられた事にしました。左上の「input」の下にかかれている点々(512個あります)がその入力のビット列です。ビットには、それぞれに異なる色を塗って区別できるようにしてあります。

前準備

SHA256では、次の疑似コードにそって「w」と呼ばれる2048ビットの値を計算します:

create a 64-entry message schedule array w[0..63] of 32-bit words
(The initial values in w[0..63] don't matter, so many implementations zero them here)
copy chunk into first 16 words w[0..15] of the message schedule array

Extend the first 16 words into the remaining 48 words w[16..63] of the message schedule array:
for i from 16 to 63
    s0 := (w[i-15] rightrotate 7) xor (w[i-15] rightrotate 18) xor (w[i-15] rightshift 3)
    s1 := (w[i-2] rightrotate 17) xor (w[i-2] rightrotate 19) xor (w[i-2] rightshift 10)
    w[i] := w[i-16] + s0 + w[i-7] + s1

真ん中にある「w」と書かれている下の点々の塊の部分がそれです(上から下に行くにつれてiが増える方向になっています)。計算式を見ると分かるのですが、すこし前(w[i-15]とw[i-2])の値を混ぜ合わせながら計算されているので、下の方に行けばいくほど色が似たりよったりになって、くすんでいきます。

圧縮関数

wの計算が終わったら、SHA256では「圧縮関数」と呼ばれる、次の64回のループを行います(h0〜h7は素数の平方根の小数部分だそうで、つまり定数です)。

Initialize working variables to current hash value:
a := h0
b := h1
c := h2
d := h3
e := h4
f := h5
g := h6
h := h7

Compression function main loop:
for i from 0 to 63
    S1 := (e rightrotate 6) xor (e rightrotate 11) xor (e rightrotate 25)
    ch := (e and f) xor ((not e) and g)
    temp1 := h + S1 + ch + k[i] + w[i]
    S0 := (a rightrotate 2) xor (a rightrotate 13) xor (a rightrotate 22)
    maj := (a and b) xor (a and c) xor (b and c)
    temp2 := S0 + maj
 
    h := g
    g := f
    f := e
    e := d + temp1
    d := c
    c := b
    b := a
    a := temp1 + temp2

この時に出てくる、a〜hまでの変数を右に並べました。それぞれ32ビットの値なので、32個の箱が上から下に並んでいます。ステップごとに最初はがやがやしてた色が、途中ぐらいからくすんだ紫一色になっていくのがわかります。

出力

で、64回のループが終わったら、次のコードでh0〜h7を更新して、h0〜h7を連結して256bit(=32bit ×8)の「ハッシュ」が得られる、という仕組みになっております:

    Add the compressed chunk to the current hash value:
    h0 := h0 + a
    h1 := h1 + b
    h2 := h2 + c
    h3 := h3 + d
    h4 := h4 + e
    h5 := h5 + f
    h6 := h6 + g
    h7 := h7 + h

Produce the final hash value (big-endian):
digest := hash := h0 append h1 append h2 append h3 append h4 append h5 append h6 append h7

虹色が紫になった

そんなこんなで、無事SHA256というポテトミキサーで混ぜ合わせたビット列は、元の虹色を失って、よくわからんくすんだ紫色の256個のビットとなりまあしたとさ。

なぜ紫色になるのか?

オリジナルの512個のビットの色を平均したら(80, 80, 80)になっているのは確かめたのですが、SHA256にかけてみたら(149, 81, 145)というくすんだ紫色になってしまいました。doubleの誤差のせいとかなのか、彩色ルール(後に書く)のせいなのか、そもそもそういうもんなのか、何か実装がバグってるのか、…それはよくわかりませんw

(一応、空っぽの入力を入れた時にWikipediaに書かれてるのと同じ値が得られる事は確認してあるので、バグではないと思うのですが…)

追記:色の塗り方の縦横を入れ替えると灰色になった

わからん、全然わからん。でもこっちのほうが見ていて楽しいですね。

参考:彩色ルール

二項演算子に関するルール

ビット同士で下記の演算が起こった時は、結果のビットの色はそれぞれの平均とする:

  • add(繰り上がりが有るときは、色は3ビットの平均)
  • xor
  • and

ただし、定数やゼロクリアされた後のビットなどは「無彩色」とし、これらと演算するときは平均する時には考慮しない

例:

  • 無彩色のビット同士で演算が行われたら結果は無彩色のビットになる
  • 無彩色のビットと赤色のビットをandしたら、同じ赤色のbitになる
  • 赤色のビットと青色のビットをxorしたら、結果は紫のbitになる

単項演算子に関するルール

not演算(1の補数)や単項マイナス演算(-x)、シフト演算が行われた時はビットの色の情報は変化しない。

  1. MD5はもはや暗号学的には全く安全ではないそうですが、べつに改ざんの検出を行いたいわけではなく、単に重複しないファイル名を考えるのを自動でやってほしいだけなのと、出てきた結果が20バイトと大変短いことから採用しています。 []

パースのついた円とマウスの当たり判定をする

Posted on

本サイトの姉妹サイト、「妖精⊸ロケット」では、WebGLを使ってウェブサイトを作るという実験を行っています:

これは「季節の歯車」です:

「季節の歯車」って、いったいぜんたい、何なのかって?

季節が毎年毎年一周してるのは、みなさんもご存知でしょう。ちかごろは、もう桜も散ってしまいましたもんね。

ところで。

なんで季節がきっちり正確に毎年一周しているのか、不思議じゃありません?

実はですね、…ここだけの秘密ですよ。

「季節」を動かす歯車、「季節の歯車」が毎年なんとなく一周しているから、季節は毎年一回だけ巡るのです。

じゃあ、その歯車が回るのはなんでなのかって?

それは、春香、夏美、秋葉、冬音の4人の精霊たちが、いつもは仲良く、時にはケンカしながら、「せかいの裏」でくるくる回しているからです。これも秘密ね。

春の次に夏がやってくるのは、春香と夏美が仲良くやってくれたから。

夏の最中に突然秋みたいな日がやってきたり、季節外れの台風がやってきたりするのは、…きっと、夏美と秋葉がたぶんちょっとした事でケンカしたんでしょうね。

でも大丈夫。ケンカしたら、仲直り。いつもそうやって、季節は巡ってきたのですから。

季節の歯車

…という創作神話(?)を元に、この季節を決める歯車である「季節の歯車」と、その結果生まれる「季節の巡り」をWeb上で表現してみようとしたのが、このWebサイトです。

もう少し常識的に言うと、左上の「歯車」の円周上に、それぞれの季節ごとの写真や絵、文章が並んでいます(これを「モーメント(瞬間)」と呼びます):

春はピンク、夏はみどり、秋はオレンジ、冬は青。…うーん、変えてもいいかな。

ここみたいな、いわゆる「ブログ」と違うのは、時系列で並べているわけではないことです。例えば、同じ「10月1日」の「モーメント」は、10年前のものでも今年の物でも、同じ角度のラインの上に並んで表示されます。

さらに、どの「モーメント」が表示されるかは、毎回ランダム(ガチャ)です。10年前の「モーメント」が表示されて今年の「モーメント」が表示されない事もあるし、逆もある。角度は同じでも、歯車からの距離は更新するたびに変わります。この点でも、2018年のページをクリックすれば必ず2018年のページが表示される「ふつうのブログ」とは異なります。

WebGLでウェブサイト作ろうぜ

えー。「季節の歯車」の紹介はこれぐらいで置いておいて。この季節の歯車を表現するための技術について、がこの記事のテーマです。

このウェブサイトは基本的に全部WebGLと、素のECMA Script 6で書かれています。くるくると回る「歯車」も「モーメント」も、全部WebGLで描いていて、HTMLの<img>タグとかは使ってない、と言うことです。もちろん、WebGLはCanvasの中身をOpenGLで描ける、という技術ですので、他のHTMLの技術と、簡単に組み合わせることもできます。「季節の歯車」では、「モーメント」の上にマウスが乗ると、タイトルが表示されるようになっています。この表示に使われているのは、いつもの<div>要素です:

この「モーメント」はこちら

3Dオブジェクトの当たり判定

さて、これで困るのは、マウスの判定です。つまり、マウスがどの「モーメント」の上にあるのか(あるいは無いのか)のチェック関数、です。

HTMLのmouseoverイベントは使えません。「モーメント」は全て、HTMLの要素ではなく、1つのcanvas要素の上にOpenGLで描かれている「絵」に過ぎないからです。

canvas要素のmousemoveイベントを使えば、canvas上でのマウスの座標を得ることはできますが、この座標もそのままでは使えません。というのも、「モーメント」も左上の歯車と同様、「遠近法」が掛かっている立派な「3Dオブジェクト」だからです。

まぁ、わざわざ「遠近法が掛かっています」と上でわざわざ書いたように、事実上ほとんど掛かっていないので、2Dだと思って当たり判定を書いてもほとんど困ることはない(見ている人が気づくことはない)かもしれません。

でも、せっかくだから「正確」に判定してみたい。趣味のプロジェクトですしね。

さて、こういう「3Dのオブジェクトとマウスの当たり判定」じたいは、ゲームではよくることです。3D空間内のアイテムをマウスでクリックして取得したり。このためのテクニックは「Object picking」と呼ばれているそうで、よくある実装は、「当たり判定」のための専用の画面を作ってしまうというものです:

OpenGL Picking Tutorialから引用

まず、オブジェクトごとに相異なる色で塗った「別の画面」を作ります。この画面は、ユーザーには見せません。ただし、あたり判定をする時は、この隠れた画面からマウスの位置にあるピクセルを読んで、「何色」になっているかを調べます。この色が何色かで当たり判定をする、と。例えば上の例だったら、一番明るい灰色だったら右のチェス、真っ黒だったら背景(何とも当たっていない)、といった感じです。

うーむ。たしかに、チェスの駒とか、人間、動物みたいな、複雑な形のオブジェクトがたくさんある中から当たり判定をしたいならわかります。むしろ、この方法を取らざるを得ないでしょう。

でも、ただの「パースのついた丸」のためにこれをやるのは何だか大げさというか、資源の無駄遣いな気がします。単純に2回絵を描かないといけないですし。「相異なる色」を用意したり、半透明になったりしないように配慮した別の描画プログラムをもう一つ用意しないといけないのも大変です。

もっといえば、この「別の画面を用意して、あたり判定を行いたいオブジェクトごとに色を塗る」という力技で当たり判定ができるのは「当たり前」すぎるように感じられます。ちょっと面白くない。

そこで今回は、それとは別のアプローチを考えてみましょう。

「遠近法」のおさらい

その前に、まずコンピューター3Dにおけるいわゆる「遠近法」をおさらいします。

「いわゆる」とつけたのは、「遠近法」と言えそうなものは、このコンピューターの世界の中だけでもたくさんあるからです。わたしの考えでは、ラスタースクロールも遠近法ですし、ゼビウスのゲームシステムも、「空気遠近法」と同じくらいには、りっぱな遠近法だと思います。

とはいえ、「季節の歯車」では、コンピュータ3Dの世界で「遠近法」という言葉で指すものの中では最もおなじみであろう、「透視法射影」を使っています。

これはどんなものだったのか、と言えば、表示したいモデルの頂点の三次元空間上の座標、x y z、そして最後に1を立てたベクトル(x y z 1)に、モデルごとの変換行列Mを掛けて、出来たベクトルをさらに最後の要素( wと呼ばれる事が多い)で割り、出来た(x’/w’ y’/w’)が画面上での最終的な座標となるのでした。

わかりにくいので、ちょっとベクトルがどのように変形されていって最後のxy座標になるまでを図にしてみました:

それぞれの操作を、数学で写像で移される時元の対応を表す、のマークを流用してその処理の流れを表現してみました。えっ、数学の世界でそんなに繋げるような記法は普通しない?まぁまぁ。うまい表記が思いつかなかったので、おもいついた人は教えてくださいな。

行列Mについて少しだけ話をさせてください。このMをうまく作ることで、モデルの平行移動や、回転、拡大縮小を表現できるだけでなく、最後にw’で割るという、行列のかけ算だけでは表現できない非線形な操作と組み合わせることで、遠いものほど小さくなる「遠近法(パース)」が再現できます。上手く作る、といっても、glMatrixなどのいわゆる3D向け行列ライブラリを使えばそんな難しくないです。とりあえず、この話はまた別の機会にいたしましょう。

さて、元々やりたかった事は何かというと、パースの掛かった「丸」とマウスのあたり判定でした。

ふむ。残念ですねぇ。何がって?パースの掛かった「三角形」とのあたり判定だったらすごく楽だったからです。あたり判定の対象が三角形であれば、上の操作で作ったスクリーン上の3つのXY座標で囲まれた三角形の中にマウスの座標があるかどうかを判定するだけで済みます。とはいえ実はその判定はそこまで簡単でもないんですが、やること自体は直感的です。

一方、パースのかかった丸となると、どうすればいいのやら。斜めになってるとぐにゃぐにゃした形になっていて、何をどうすれば内側になるのか判定できるのか、よくわかりません。

スクリーン空間からモデル空間へ

遠近法をつけた丸はぐにゃぐにゃしてて、なんかよくわかりません。となると、遠近法を付ける「前」の丸とマウスの当たり判定を行う作戦を取らざるを得なさそうです。遠近法を付ける前なら、単に「円の中心とマウスの座標の間の距離が円の半径以下か」判定すれば良いだけですから、三角形の内側にあるかどうか判定するよりも更にラクです。まぁ、点と点の距離を調べるのも、実は言うほど簡単じゃあないんですが…。

閑話休題。そうなると、問題は「マウスのポインタは、元のモデル空間では一体どこに存在するのか?」になります。さっきの図はモデル空間からスクリーン空間の話でしたが、今度はその逆、スクリーン空間からモデル空間への話を考えねばなりません。二次元から三次元上の位置を推定しないといけないので、ややこしそうです。

一つずつじっくり追い込んでいきましょう。まず、モデル空間上にあるマウスの点を(xm ym zm)、液晶画面上のマウスの座標を(xs ys zs)とします。マウスの座標にZ軸なんか存在しないのですが、あとで計算するときに便宜上必要になりますので「未知だが、存在する、何かしらの数」として導入します。

さて、目からマウスポインタを結ぶ線は液晶モニタの平面を貫通し、最終的に液晶モニタの後ろにある(笑)1モデルへとぶつかります。図にするとこんな感じです:

これらの(xm ym zm)と(xs ys zs)の関係を、書いてみます:

この図自体は最初に描いたものとほぼ同じです。

なかなかややこしいので、wsという(未知の)変数を新たに導入した上で(といってもw’mのエイリアス)、まず波線を引いた部分を変形します。

行列を掛けて出てきた、素性のよくわからんx’m, y’m, z’mを、すでに分かっているxsやysなどにできるだけ置き換えいって整理しようという作戦です:

さらに波線のwで割ってる部分も、xs や ws を使って割ってない所まで戻します。

すると、「モデル空間上の座標に変換行列Mを掛け算して移すと、スクリーン空間上の値を使ったよくわからんベクトルができる」、という図になりました(少なくともわたしはそういう意味でこの図を書いてます)。波線の引いた部分は「矢印の左側でベクトルに行列をかけると矢印の右側のベクトルになる」、という意味で使ってますので、おなじみの等号に書き直します:

未知変数の部分に赤線を引いてみました。xm ym zs wsの4つが未知で、Mは4×4の行列ですから、この行列とベクトルの式は実際には4本の連立方程式です。未知数が4つで、式が4本。原理的には解けます。やったね。zmは未知じゃないのかって?あー、言い忘れてました。今回の丸は、モデル空間上ではXY平面上にあることにしましょう。なので、zmはzm=0の定数です。

さて、この式は前述した通り解けるので、xm ym zs wsを求めたら、zsとwsは単に便宜上入れた要らない変数なので捨ててしまいましょう。モデル空間上のマウスの座標である、xmとymを使えば、無事円との当たり判定ができます。

はいおしまい、QED。

と言いたい所だが、この行列は実際一体どう解いたらいいのか?右にも、左にも未知変数があります。逆行列を一発キメたら終わり、みたいな、そういう生ぬるい式ではなさそうなのは確かです。かといって、プログラムに組み込んで自動で解かなければならない以上、「頑張って手動で連立方程式を変形して解く」みたいな高校生的解法は使えません。捻りが必要です。

頑張って式を変形するぞい

まず確認です。行列とベクトルの掛け算とは、行列の各行ベクトルを、もう片方のクトルのそれぞれの値で重み付けをして足し合わせることだと見なすことができます。

左辺

まず左辺をこれを使って変形します。Mを、M1からM4までの4つの縦ベクトルが横に並んだものだとみなすことにしました:

右辺

次は右辺です。右辺は、まずwとx y zが掛かっていて複雑なので、wをくくりだします。

赤線を引いた未知変数がだいぶ減って気楽な感じになりましたが、まだベクトルの中と外に未知変数が入っていて扱い方がわかりません。さらにこれをこんな感じで2つのベクトルの和に変形します。

するとどうでしょう。右辺も左辺も、「「未知のスカラ量 x 既知のベクトル」の和」に変形できました。

なんとなく、これなら扱えそうな気がしてきません?

最後の一捻り

さっき変形した右辺と左辺の式を使って、再度等式を書いてみます:

するとただの和なので、簡単に未知変数を左辺だけに集約することができます:

で、ここで最後の一捻りです。

さっきの

行列とベクトルの掛け算とは、行列の各行ベクトルを、もう片方のクトルのそれぞれの値で重み付けをして足し合わせることだと見なすことができます。

というのを、今度は逆回しにします。つまり、こんな感じでもう一度「行列とベクトルの積」に書き戻します:

ここまでくれば、もう簡単。赤線が引いてある未知変数が詰まってるベクトルの値は、逆行列を掛ければ一発で求められます。

長かったですけど、纏めてみると結構綺麗な解法のような気がする。…どうかな。

JavaScriptで最小のデモ作った

「季節の歯車」だとここで実装してるんですが、流石に他のコードも多くてわかりにくいだろうという事で、この当たり判定の部分だけ切り出したサンプルを作ってみました:

github.com/ledyba/__sample__3d-picking-without-shaders
パースのついた円とマウスの当たり判定をする

実際に動いてるデモのページはこちら

  1. でも、最初にプレステのゲームを遊んだときは、そんな感じがしませんでした? []

ChromeでSVGを背景にすると遅い

Posted on

ブログのタイトルに合わせて、月と夕焼けをイメージしたテーマを自作してブログの模様替えをしてみました。

ソースコードはgithubで公開中です:

ledyba/wp-lunar-theme: theme of 7io.org

作り方は割と簡単で、次のファイルを作り…

ファイル名用途
function.phpテーマの各テンプレートから参照できる関数
初期化、サイドバーの定義など
index.phpトップページの表示
page.php固定ページの表示
single.php各ブログ記事の表示
archive.phpアーカイブ(月別、カテゴリ別)の表示

さらに、これらから参照されるサブテンプレート用のphpファイルと、CSSを用意すれば完成です。

公式のWikiにあるドキュメントもよくまとまってます。詳細は公式をチェックだ(書くのがめんどくさくなった)。

SVGの背景が遅い、どうしようもなく遅い

問題はここからです。今回のテーマ作成のサブテーマとして「ラスター画像(SVG)しかテーマには使わない」という縛りをなんとなく課してみまして、背景もSVGで用意しました。左に見える月の画像もSVGです。

Firefoxから見ると何の問題もないのですが、Chromeから表示するとどうしようもなく遅い事に気が付きました。Ryzen Threadripperを使ってAMDのDiscrete GPUを使っても、フレームレートが落ちてるのが目で分かるぐらいに遅い。

計測してみると、1フレームを描画するのに100ms弱掛かっってました。これはいけない…。

しかもiPhoneでは背景が表示されすらしない。どうしようもねぇ〜。

mac OSのSafariだと見えるんですけどね、中身違うのかな

CSSで同じことをするとなぜか爆速になる

うーんどうしたもんか、と思って。CSSのlinear-gradient書き換えてみました

とはいえ、

メモ: CSS グラデーションにおける色経由点の描画は、 SVG グラデーションと同じ規則に従います。

linear-gradient() – CSS: カスケーディングスタイルシート | MDN

だそうなので、SVGと一緒ならやっぱ遅いんじゃないかなぁ、と思いながらダメ元で。

しかし…どういう事でしょう、Paintingに掛かる時間が70倍近く速くなり、ほぼ60FPSを達成できるようになったのです…(!?)

iPhoneからも背景がきちんと見れるようになりました:

スマホ、画面ちいさくね?マジでみんなこれ毎日使ってんの?

SVGにはまだChrome/WebKitには早すぎるのかもしれない

たぶんですけど、SVGを背景に設定すると毎フレームSVGからbitmapにラスタライズするんでしょうね。他にもWebKitはSVGは遅いと6年前に言ってる人はいて、とくに改善されないまま現在に至ってるようです。

…はぁ。EdgeもChromiumに乗り換えてしまったし、ラスター画像大好きおじさんには苦しい時代が続くかもしれません。

Firefox頑張ってくれ〜〜〜〜〜このブログはFirefoxとフォクすけくんを応援してます!一番好きなブラウザです(やけくそ)!

ffmpegでコマごとに表示時間が違うアニメを作る

Posted on

ffmpegで静止画(pngとか)から動画を作る方法といえば、連番画像を使う方法が有名です:

ffmpeg -framerate 10 -i %03d.png -vf scale=784x1024 -vcodec libx264 -pix_fmt yuv420p -r 30 out.mp4

これを使うとすべての画像が同じ間隔で表示されてしまいます。上でいうと、000.pngも001.pngも002.pngも、全部0.1秒ずつ表示されます。

大半の場合はこれで困らないのですが、自作でアニメを作ったりしていると困ることがあります。たとえば、今回こんな感じの動画を友達と作りました:

首をかしげて, pixiv

このアニメは、最初のコマだけ1秒、最後のコマだけ3秒、他のコマは0.25秒表示されています。

こういうコマごとに表示時間が異なる動画を作るにはどうすればいいか、あんまり情報がなかったので備忘録的にメモって起きます。

1.jpegから5.jpegを使って上の動画を作るという設定で説明します。

githubリポジトリにデータ付きでアップロードしておいたので、よろしければそちらも参考にしてください。

タイミング情報を纏めたファイルを作る

file '1.jpeg'
duration 1
file '2.jpeg'
duration 0.25
file '3.jpeg'
duration 0.25
file '4.jpeg'
duration 0.25
file '5.jpeg'
duration 3
file '5.jpeg'

こんな感じのファイルをinput.txtみたいなファイル名で作成します。5.jpegを3秒間表示するために、最後にもう一度5.jpegを書いてる点はちょっと注意です(これを書かないと5.jpegが1フレームしか表示されません)。

適切にコマンドを実行する

ffmpeg -f concat -i input.txt -vf "scale=-1:1024" -vcodec libx264 -pix_fmt yuv420p -r 30 out.mp4

いくつか解説です:

  • -f concat を忘れないでください
  • scale=-1:1024を使うと縦1024ピクセルにした上で横幅はアスペクト比に応じて自動で決定してくれます。
  • -r 30は出力動画のフレームレートです。

「さきゅばす」の開発をやめて悪魔を祓い、苦楽を共にした彼女を追悼する

Posted on

かつてわたしと苦楽を共にし歩んできた「さきゅばす」は、いまやゾンビとなり、インターネットの地下倉庫で、苦しそうに彷徨っている。

だから、せめて…生みの親であるわたしがシャベルでその息の根を止めて埋葬し、わたしは新天地へと向かわなければならない1

さきゅばす」とは何だったのか

「さきゅばす」は、「ニコニコ動画レコーダー」である。

一言で伝えられる短いキャッチコピーを考えるのにも10年掛かり、最近やっとここに着地した。やめるけど。

えーっとね。ニコニコ動画の動画ビューワは、投稿された動画の上にコメントの文字列を再生するたびに毎回重ね描き2して表示しているんですが、その代わりに既に最初からコメントが描きこんであるような動画を生成するソフトウェアです。

こんな感じの動画が作れます:

レッツゴー陰陽師

きしめん/Nursery Rhyme

12年半ほど間欠泉のように開発してきたこのソフトウェアですが、もういい加減、開発・メンテという形で関わるのは、もうやめようと思います。

わたしは株式会社ニワンゴ・ドワンゴ・カドカワとは雇用契約以外も含めた一切の金銭的な関係を持ったことはなく、決してこれは退職エントリではありません。そもそも、ただのOSSだし。

とはいえ、ある意味では雇用契約よりもはるかに強い、「悪魔と契約純粋な趣味として」して作ったソフトウェア3ですので、強いていうなら「退魔・追悼エントリ」でしょうか。てなわけで、こんなタイトルになった。でも俺は悪魔と契約しちまった以上、死ぬまで魔女はやめねーかんな。なぜなら、悪魔との契約は生涯有効だからだ。

引き継ぎ資料

さてさて。とはいえ、「さきゅばす」をまだ必要としている人はまだいるでしょうし、開発を引き継いでくれる人がいるなら、それが一番なのは間違いありません。そんなわけで、引き継ぎ資料を作りました。

ただしおそらくこのドキュメントを見てコマンドを打つだけでは、ビルドと実行まではできても、最後まで動画を変換しきることはできず、いくつかの箇所でエラーでコケると思います。(引き継ぎたいあなたへ:悪魔と契約するんだ、デバッグとソースコードの修正をする覚悟ぐらいは持っておくれ)

さて以下では、こんな感じで10年間降り積もった同窓会的なよもやま話を延々といたします。どんな気持ちで作ってたのか知りたかったら、読んでみてね。長いよ。

どうしてやめるのか?

他にやりたいことがあるから

やりたい事・作りたいものが、たくさんあるからです。

死ぬまでに作りたいもの、上手になりたいこと、知りたいこと、研究したいこと、描きたいこと、記したいこと、見たいもの、…そんなものが両手で数え切れないほど、たくさんあります。でも、人間には寿命があり、いつかは死んでしまいます。すべてを行うことも、見聞きすることも出来ません。最近ついにそこに気づきました。

そうして天秤に掛けた時、「さきゅばす」からは、…「彼女」からは、もう、知りたいことは全部教わったし、作りたいものは全部作ったし、描きたいものは全部描いたし、研究したいことは研究しつくしたし、見たいものはもう全部見せてもらいました。

…つまるところ、さきゅばすでやりたいことは、わたしには、もう残っていないのかなぁって。

ニコニコ動画を見ていない

ニコニコ動画を(古いお気に入りの動画をふとたまに見たくなった時以外)全く見ていない事に気がつきました。すこし昔は「アニメを見る時ぐらいはニコニコ動画」だったような気がするのですが、最近はそれもやめ、アニメを見る時は1人でじっくり鑑賞し、噛みしめるように見ています。

そんなわけで、ニコニコ動画を使っていないわたしには、ニコニコ動画の作りやすいツールは、流石にもうこれ以上作れないと思いました。…せいぜい動き続けるように、メンテできるだけ。

でもそれって、「ゾンビ」そのものじゃないですか。わたしは、そんな彼女の姿を見たくはありません。

必要性が薄まった

さきゅばすは元々は100万回もダウンロードされるために作ったソフトウェアではなく、2007年6月当時の個人的な欲望と興味と関心を具現化するため、高校にもロクに行かずに引きこもりながら実験的に作ったソフトウェアです:

  • PSPでニコニコ動画が見たかった
    (PSPにはニコニコ動画アプリのようなものが無かった)
  • 2007年当時の環境では、弾幕4が重く、PCの性能不足でプレイヤーがコマ落ちしてしまった

でも、2019年現在では、スマホアプリも、各種ゲーム機向けのプレイヤーもあります(端末別ヘルプ、PSP向けはついぞ出なかったようですが)。お気入りの端末でニコニコ動画が見られない、なんて事は、もう無いと思います。変換した動画ではなく、各アプリなら、コメントを見る見るだけでなく投稿することだってできますし、他の動画の検索だってできます5

性能面に関しても、2019年のスマートフォンでも十二分すぎるほどの性能があります。実はスマホをもう持ってないので分かりかねるのですが、「コメントがたくさん出たら画面がカタカタになった」なんて事態は、おそらく流石にもう無いんじゃないでしょうか。少なくとも聞いたことない。

投稿されたコメントアートを残したい、という需要があるということが、orzさんやそれを通じて知り合ったコミュニティを通してわかったのですが、2019年現在では、2019年に投稿されたコメントアートを保存する最善の方法は、おそらく単に録画する事のような気がします。もっと言うと、2019年のパソコンには、それをやるだけの十分な計算資源があります(逆に言うと、2007年当時は、再生された動画をリアルタイムに録画するのはとーっても大変でした)。もちろん、過去に投稿されたコメントアートを今ここで再生・保存したいなら、当時の挙動を再現するコードを書くしかなく、そこに「彼女」の居場所が生まれうる、とは思います。

デフォルトでは動画全体を通して最大1000コメントしか表示されないところを、無理やり数万コメントを突っ込んでコメントで溢れさせる弾幕動画を作るのは…もういいかな。やりたい人が居たら、わたしの代わりに、彼女を召喚ビルドしてお願いしておくんなし。

うーん。

こうして箇条書きにして当時の「モチベーション」とやらを書き出してみたのですが、いくら書いても、ここからこぼれてしまう部分があるような気がします。人はそれを、「情熱」とか「熱意」と呼ぶのでしょうか…。よくわかりません。

…なんだろ、tcpdumpでdumpしたパケット眺めてさ、ActionScriptを逆コンパイルしてさ、ffmpegのソースコード読んで書き換えてコンパイル通してさ、ニコニコ動画の弾幕コメントを表示させるのは、仮に何の意味もなくても、確かにどうしようもなく楽しかったよ。

誰も認めてくれなくても、それがわたしの青春の1ページだ。

さきゅばすの作り方

「資料なんかどこにもないのに、どうやって作ったんですか?」と以前聞かれた事があるので、文章にして残しておきます。

WebAPIの叩き方→tcpdump

ニコニコ動画のサーバから、動画とコメントをダウンロードする方法は、単にブラウザの挙動を追いかけて推理しただけです。ただし、F12を押すと出てくる「開発者ツール」のような便利なものなど存在しない時代だったので6、tcpdumpを使って、ニコニコ動画のサーバと自宅のブラウザが交換するパケットストリームを眺めて観察しました。観察した結果を元にAPIの使い方(リクエストを投げる時のXMLの書き方とか)の仮説をたて、それを確かめるためには、時にはtelnet nicovideo.jp 80ってやって直接手でHTTP/1.1のリクエストを投げて確かめてた気がします。今ではニコニコ動画もHTTPSに対応してしまい、通信はすべて暗号化されてしまったので、今では絶対できない方法ですね…。懐かしや。

コメントの配置方法→逆コンパイル

コメントの配置の仕方は、FlashのプレイヤーのActionScriptを逆コンパイルして、それをそのまま実装しました。今思うと、ちょっとヤバかったかも。でもそのおかげでそこそこ再現性は高かったんですよ。逆コンパイルすると変数名とかが全部「var1」とかになったソースコードが現れてきて、一般に解読はなかなか大変なのですが、当時はゲームのコピープロテクト外しも夢中だったので、「アセンブリじゃなくて、ちゃんとif文やfor文が出てくる!なんてわかりやすいんだ!逆コンパイラってすげー!」みたいな感じでした。…いまやれって言われたら、できるかなぁ。

コメントのレンダリング→適当 or 逆アセンブル

コメントの描画の仕方は、最初はSDL_ttfを使って適当にMSゴシック使って描いていたのですが、後にFlashそのものを逆アセンブル・解析して、ExtTextOutWというWin32APIを特定のパラメータで叩いてることを突き止め、cairoというライブラリでなるべく同じようにWin32APIが叩かれるように実装しました7。これも、今思うとちょっとヤバかったかな。ただ、この解析結果が実装されているのは、ゼロから書き直したSaccubus2だけで、引き継ぎ資料でビルドしてるSaccubus3は初期のバージョンである1がベースなので実装されていません。やりたかったらやってみてね。

ffmpegの改造方法→素直にソース読む

ffmpegの改造の仕方は…普通に変換してるところのソース読んで追いかけて、その結果をもとに、さきゅばす用にちょびっと改造しただけです。話を整理してみると、実はここが一番簡単かつ素直だったことが分かります。ただ、変化の激しいffmpegを改造して維持つづけるのは中々大変でした。この話はまた後でします。

アーキテクチャ図

ちなみに、全体のアーキテクチャはこんな感じです:

この図にして見ると結構複雑なアーキテクチャはどう思いついたのか?…うーん、思い出せません。でも結構素直ではあると思うんですが、みなさんはどう思います?

さきゅばすの思い出

ここからはさらに個人的な思い出話です。ガンガン回顧するぜ。

自宅サーバから配布しすぎてISPからアカウントを永久凍結された回

さきゅばすを開発した当初、このウェブサイトは自宅サーバの上でホスティングされていました。なので、開発したソフトもその自宅サーバから配信してました(当時のブログ記事)。

公開してしばらく経ったある日、とある「個人ニュースサイト(これも懐かしい響きだ)」で取り上げてもらって突発的にすごい人気が出て(今で言うとバズって)一週間で数万回とかダウンロードされるようになりました。

…それはそれでとーっても嬉しい話なのですが、5MBぐらいあるソフトウェアが1万回ダウンロードされると、50GBのアップロード・トラフィックが発生します。当初使っていたプロバイダは(安い代わりに)月々5GBまでしかアップロード・トラフィックを出してはならないという規約になってまして、そのうち見事にアカウントが凍結されてインターネットに繋げなくなり、ウェブサイトも公開できなくなってしまいました。そしてアップロード・トラフィックなんか気に掛けた事無かったので、理由もわからないままある日突然繋げなくなってすごい焦った…(そしてプロバイダからの紙のお手紙が後に届いた)。

当時は「なぜアップロードが…?」と思っていましたが、10年後ぐらいにデータセンターの運営をやるようになって納得しました。インターネットでは、電話と同じで、アップロードする側がお金を払う

つまりISPは、ユーザーがアップロードすればするほど損をするんですね。昔、ISPがP2Pを嫌がって規制したりしてたのも、結局最終的にはそこ(アップロードの増加による経済的損失)だったのか、とかも芋づる式に完全に理解しました。

毎月パソコン雑誌がなぜか家に届く回

人気が出た結果、複数のパソコン雑誌に定期的に収録してもらえるようになりました。収録されるとソフトの開発者は無料で献本してもらえるという習わしがあったので、ほぼ毎月のように様々なパソコン雑誌が届いてた時期がありました。しかし毎月毎月同じソフトが別の雑誌とはいえ収録されるというのも、今思うと不思議な話だ…。

Flash黄金期である2000年代前半に「ぶっこ抜き」という標語と共に生きていた世代だったので、「ネトラン」に収録されたときはちょっとした謎の達成感(?)はありました。

…何もかもが、懐かしい。

ユーザーは説明を読んでくれない

「さきゅばす」は上にも書いた通り「実験」として作ったソフトウェアでしたので、当初のUIは限りなく適当でした。どれぐらい適当かというと、文字を描くためのフォントのパスを自分で打ち込まないと変換できないぐらい、適当なUIのソフトだったのです。

そんなソフトですから、人気が出ると、すぐに「変換できません」という投稿でコメント欄があふれてしまいました。対応策は分かっていて、WindowsのMSゴシックのパスをデフォルトでハードコードしておけば、ぶっちゃけ大半のケースでは困りません。

が、せっかくJavaで書いたのにそれで乗り切るのは負けな気がして8、かといってWindows/Mac OSX/Linuxのすべてで適当なフォントを探すためのJavaコードを書くほどの気力もなく9、「Windowsの人は次にあるMSゴシックのフォントを打つか、フリーのフォントをダウンロードしてそのパスを入力してください」とダウンロードリンクのすぐ上に赤字でデカデカと書くという、今になって冷静に考えると一番ダサい解法で乗り切ろうとしたのですが、デカデカと書いたのにも関わらず、「動きません」というコメントの勢いが衰えることは一切ありませんでした。読んでくれないんだね。町中でダサいテプラを見るたびに、いつもこの事を思い出して、テプラ貼った人に心の中で同情してしまいます。

結局、最終的には腹をくくってWindowsの時はWindowsのシステムフォルダの中にあるMSゴシックのフォントのパスを発見してくるコードを書きました。

とにかく自動でとりあえず大半のケースでは動くようにすることがすごい大事で、人はとにかくログは読まないし、エラーメッセージも読まないし、ドキュメントも読まないし、でもコミュニケーションはする、という、人間へ対するある種の諦観を、このとき手にいれました。この諦観は、この後、他のフリーソフトを書いたり、仕事としてソフトを開発・運用をしたりする中で、何度も何度も強化されていったような気がします。

特定のCPUでクラッシュする

一時期、Crusoeの載ってるVAIO(まだSONYが作ってた頃!)を併用していたのですが10 、さきゅばすはこのPCでだけ、ときたまクラッシュすることに気づきました。トラブルシュートした結果、最終的にSDL_ttfのgccのコンパイルオプションでSSE2かなにかを無効にすると再現しなくなったので、おそらくSIMD命令の互換性がCrusoeでは怪しいのだろう、という結論に。

ただそれだけなんですが、なんというか、パソコンの裏側の、そのまた裏側を覗いてしまったような…見てはいけないものを見てしまったような…何か隠れていたものを掘り起こしてしまったような、そんな気持ちになったエピソードです。

cygwinとmingwの思い出

Windows上でPOSIX互換のプログラムを書くためのソフトウェアツールキットとして、MinGWcygwinがあります。前述したように互換性厨だったので、C言語で書いてあるコメントを描画する部分については、Win32APIを叩くのではなく、こちらを叩いて実装しました。MinGWだとpthreadが無いとかで(詳細は忘れた)、もっと楽なcygwinで当初は開発・配布してました。

cygwinを使ってコンパイルしたバイナリは、cygwin-1.dllに必ず依存するようになります。それ自体は別に問題ではなく、一緒にcygwin-1.dllを配布すればよい…のですが、ただ、他のソフトと同時で起動した時に、そのソフトが別のバージョンのcygwin-1.dllに依存していたりすると、異なるバージョン間で何かがぶつかりあってクラッシュしてしまうらしく、定期的に「動かないのですが」のコメントが来ていたので、頑張ってMinGWで動くように改修した記憶があります。もっというと出来る限り全部をstatic linkするようになっていった記憶が…あります…。

ソフトウェアのバイナリを配布して動かしてもらう場合、相手の環境は前もっては分からないので、かなり想定外な…ともすれば理不尽なエラーに出くわしたりします。…スマホの時代になっても、そのへんはあんまり変わらないかもしれませんねぇ。

ffmpegを改造しながら4〜5年毎日Jenkinsでビルドした

ffmpegの改造自体は結構簡単だったのですが、ffmpegは頻繁にアップデートされ、内部構造も結構大胆に変わります11。それに毎日追従して改造しつづけながら何年間も毎日Jenkinsでビルドし続ける、というのをしてました。ぶっちゃけ、この作業が一番大変だったな。

今思うと、別にそこまでする必要無いよな〜。でもDaily buildとかContinuous Integrationって文字列が、なんか、こう、かっこよくて…やってみたくてさ…。

コメント描画フィルタを実装する3つの方法

最初は、コメントを描画するために「vhook」という、画像から画像に変換するフィルタをDLLで注入できる機能を使っていたのですが、これはすぐになくなりました12

しょうがないので、avfilterでvhook相当の機能を足すvhextというfilterを書いてffmpegのソースに入れました。使うためのドキュメントはあっても作るためのドキュメントがなくてよく分からず、とにかくソースを読みながら手探りで入れたような記憶があります。

が、libavfilterを改造する方法だとかなり頻繁にコミットがコンフリクトしてその度に解決するのが辛かったので、Saccubus2ではまた方法を変え、libavdeviceにsaccubusという名前の仮想入力デバイスを作って、その仮想デバイスが動画のデコードとコメントの描画をした上で、後段のffmpegのエンコーダに渡す、という実装に変えました。

仮想デバイスの追加先であるlibavdeviceはそんなに頻繁に更新されないようで、あんまりconflictに悩まされなくなったような記憶があります。

さらに仮想入力デバイスにしたおかげで、動画のfpsを自在に変えられるようになったり、結構柔軟性は上がりました。ffmpegのAPIたくさん叩かないといけないから、大変だったけどね。

動画の長さをDLLへ渡すための、いくつかの方法

そうそう、コメント描画部分にわたさなければならない情報として、動画の画像とその時間やコメントそのもの以外に、「動画全体の長さ(秒数)」があります。

というのも、ニコニコ動画のコメントは投稿されたタイミングの1秒前から3秒間画面を流れるのですが、その3秒後が動画終了より後だった場合、コメントの描画開始タイミングを前倒しして必ず3秒間表示するようになっています13

この挙動を再現するには、コメントを描画しはじめる前に動画の長さを知っておかなければなりません。

そのために、当初はffmpeg.cの中で動画の長さが取得できるようになったタイミングの箇所を見つけて、そこに動画の長さを後で使うために記録しておくコードを挿入していた記憶があるのですが、ffmpeg.cはあんまりにも書き換えられまくってコミットがコンフリクトしまくるので、結局諦めて変換のためにffmpegを叩く前にffprobeコマンドを使って長さを調査する実装に変えたような…。

「ffmpegのプロセスを実行する回数はできるだけ減らしたい」みたいな、(今思うと無意味かもしれない)妙なこだわりがありました。その後に作ったSaccubus2でも仮想入力デバイスが長さを取得・計算していて、やっぱりffmpegのプロセスは変換ごとに一回しか起動しないようになってます。

追従し続けるにはmergeではなくrebaseするしかなかった

途中からgitを使ってffmpegの改造ソースも管理するようになったのですが(それまでは…どうしてたっけ…)、forkしたさきゅばす用ffmpegのリポジトリを本家に追従させるために、mergeするのではなく、定期的に毎回本家のmasterブランチからrebaseするという方法に落ち着きました。

「rebase絶対許さないマン」がいるのは知ってるし、その理由も頷けるんですが、1年に数千〜万コミットされるソフトにパッチをちょこっとだけ当てるというケースでは、rebaseにしておかないと、自分たちが加えた変更のコミットは大量のコミットログの中に埋もれていき、conflictを解消するだけのmergeコミットが数千コミットに一回ずつ現れるようになり、コミットIDも段々とぐちゃぐちゃになり、最終的に訳がわからなくなったので…。

歴史の管理をする、メタ・歴史管理ソフトがほしいです。

ニワン語の実装

わたしにとっての、初めてのプログラミング言語処理系の実装。それがニワン語の互換処理系(インタプリタ)である「ねこまた」でした。

ニワン語のsyntaxとsemanticsをまとめた不思議なサイトがあったので、だいたいそのとおりにC++でパーサとインタプリタを実装して、細かい部分に関しては、ニワン語で書かれた音ゲーを実際に動かしながら「文法エラーにならないように」syntaxを調整し、「実行した見た目が同じ挙動になるように」semanticsを調整していく、という感じで細部を詰めていきました。音ゲーが最後まで動いた時は嬉しかったな。

ココロの肩書きは一生有効です」と昔CPUの本の人は書きましたが、「初めて書いた本格的なインタプリタが、仕様書もなければ処理系のソースもないプログラミング言語の互換処理系であり、ゲームがちゃんと一本動いて遊べた」という、中々レアな肩書き(?)は、わたしのココロの中で、誰にも理解してもらえないかもしれないけれど、それ故に誰からも曇らせることができない、きれいで澄んだ輝きを、いまでも放っています。ええ、この文章を書いている瞬間もです。

ニワン語は、未踏で作ったシステムの一部であるプログラミング言語「ど〜なっつ」のアイデアの原型にもなっていますし、それは更に、今友達と書いてる小説と、そのゲームにもつながっています。

間違いなく、ニワン語とそのアイデアは、わたしの血肉の一部です。

そういえば元々のニワン語を作った人もなかなかのカワリモノで、結局ドワンゴを辞めてしまったと聞いたのですが、今はなにをしてるんだろう。一回一緒にご飯を食べながらお話したいなぁ。もしもこれ読んでたらTwitterでもMastdonでもメールでもこのコメント欄でもなんでもよいので、連絡してくだされ、頼む。

追悼の一環として、動いた音ゲーのTAS動画(フルコンプ)を再掲します:

このゲームの実装されていた元動画を今見たら、ふつうのPVに戻ってしまっていました。もちろん、もうニワン語は公式にサポートしなくなったのでそれが正しい挙動…なのですが。諸行無常。

このゲームだけでなく、他のニワン語を使った動画のプログラムも動いてました:

こっちも今みたら、普通の動画になってしまった…寂しい。

ニコニコ学会βとニコニコ超会議

そんな感じでだらだらソフトを書いていたところ、ニコニコ学会βというところで喋らないか、というお話を頂いて、2回(第二回最終回発表させていただきました。最初はさきゅばすの簡単な紹介とver2.0の自慢(笑)、次は、その後の近況報告みたいな感じかな。

…かわいいお洋服を着て好きなことが喋れたので、余は満足じゃ。

今では在宅勤務して働いてるぐらいには根っからの「ひきこもり」なんですが、大勢の前では意外と喋れるなぁと思って、そこが面白かったかも。

orzさんの貢献とコメントアート

途中から、orzさんという方がコミットしてくれるようになりました。なかなかシャイな人でどんな方かは分からないまま、いつのまにか見なくなってしまったのですが…お元気ですか。

orzさんが貢献してくれたのは主にコメントアートへの対応で、ソースコードを読んでバイナリを解析してるだけでは到底できない、コメントアートコミュニティの知見(例えばこういう知見)を踏まえた改修(や、ニコニコ動画のWeb APIの変更への追従)をしていただけました。ニコニコ学会βやorzさんを通じてコメントアートコミュニティの方とも知り合いになったり…ほんと、フリーソフト開発って何があるかわからないです。

ただ、正直に言うと、最終的にコメントアートはどうしても理解しきれませんでした。色々な意味で。ニコニコ動画への興味が失われかけてた頃に知ったからかなぁ。とはいえ、こういう事に真剣に取り組んで表現・実践・議論している人たちが眼の前にいるんだなぁ、というところを目撃できたのは、いい経験だったと思います。

ところでなんで「さきゅばす」なんですか

これも、

  • 「そもそも「さきゅばす」ってなんですか」

って聞かれるパターンと、

の2パターンがあります。ソシャゲの流行に伴ってえっちなサキュバスの知名度がむちゃくちゃ上がったので、近年は後者のパターンが増えました。10年以上も変わった名前のソフトを作ってると、そういうこともあります。

ではなぜ「さきゅばす」なのか。辞めるわけだし、そろそろ文章として残しておいても良い頃でしょう。

初期のバージョンを作ってた時(2007〜2008年ごろ)に、ニコニコ動画で違法にアップロードされた「ひぐらしのなく頃に」と「涼宮ハルヒの憂鬱」のコスプレAV14を見るのがお友達の間で流行っていて、その時にひらめいた連想ゲームです:

味のある演技15のコスプレAV→「えっち(?)だけど、なんかこわくて、夢の中に出てきそうな、おんなのひと」→サキュバス→「さきゅばす16」。

…そういえば気がつくとニコ動はホモビデオばっかになってノンケは完全に閉め出されてしまったな。あくしろよ。おっそうだな?

ちなみにアプリのアイコンがポケモンのムウマだった17のは、サキュバスは夢魔で、ムウマも夢魔だからです。

こういう連想ゲームは、今でもずっとやってますね。働いてる会社で流石にやりすぎって戒められた事もあるぞい。人間、そうそう変わるものではない。

最後に

これを書いている間、ずっとsm9「レッツゴー陰陽師」を聞いていました。当時は「電波ソング」とゲラゲラ笑いながら聞いていたのですが18、今聞いてみると…結構いい曲だなって思っちゃった。となると、このブログ記事も「電波ゆんゆん」でしょうか?

というわけで、最後に「レッツゴー陰陽師」の気に入ってる一節を引用して終わります。矢部のピコ麻呂に「さきゅばす」も成仏させてもらうか、そこまでは許してもらうか、わたしの中ではまだ結論はついておりません。

辛い時、悲しい時、人はそんな時心の隙間に闇が出来る。
その心の闇に”魔物”達は容赦なく入り込んでくるのだ。
だから、苦しくても、くじけるな。落ち込むな。くよくよするな。
何事にも屈しない強じんな心こそが、最強の武器なのだから。

カドカワ、最近は元気がないようですが頑張って。陰ながら、応援しています。

  1. 元ネタ: https://gakkougurashi.com/ []
  2. 初期はFlash、今はWebはPixi.JS、スマホやゲーム機は、またそれぞれ別の技術 []
  3. あとで書きますが、サキュバスは悪魔の名前です []
  4. たくさんのコメントが一画面上に同時に表示されること []
  5. 「あえて出来ないのがよい」という価値観も、わたしの中に無いではないんですが []
  6. JavaScriptのデバッグのためにalert()使ってた時代といえば伝わるかな []
  7. どうしてWin32APIを直接叩かなかったのかはちょっと思い出せない []
  8. 当時は移植性厨だったので []
  9. そもそもmac持ってなかったし []
  10. バッグに入れてイヤホンつないで音楽聞きながらちゃりんこ乗ってたぜ。スマホで聞きながら走ってる連中より10年早くな! []
  11. libavというフォークもこの間に生まれた…まだ仲直りしてないのかお前ら []
  12. 最初のリリース時点ですでにdeprecatedだったのでしょうがない []
  13. なので最後の3秒だけは特にコメントの密度が高い []
  14. 流石にR18のところはカットされてた気がする []
  15. 穏やかな表現 []
  16. 英語表記のsaccubusも、普通の表記のsuccubusからちょこっと捻ってます []
  17. 今思うと著作権的に完全にアウト []
  18. この言い回し、最近聞かなくなりましたね []

俺もココアだ―「ご注文はうさぎですか?? Wonderful party!」

Posted on

今日一週クリアしたんですが、エンディングの日はちょうどクリスマスの朝だったので、スケッチするように感想をさっと書き留めておきたいと思います。

ネット上ではこの画像で(一部で)有名なゲームです:

ですが、このゲームは実はココアさん「だけになる」わけではないです。いわゆる「個別ルート」に入って以降は、あなたはチノちゃん、リゼちゃん、千夜ちゃん、シャロちゃんのそれぞれに「なります」。いいか、なるんだよ

原作と同様、物語に大きな起伏があるわけではありません。異世界チートもないし生死を分ける戦いもないです。

前半では、あなたはココアさんとなってチノちゃんの誕生日を最高のものにすべくバイトとチラシ配りを一生懸命がんばって誕生日パーティを開き、
後半では、(チノちゃんルートでは)あなたはチノちゃんとなって、誕生日のお返しとして、たのしいクリスマスパーティを開くべく、人付き合いの苦手な彼女なりに奔走する。

それだけです。あえて悪く言うと、淡々としてます。人によっては退屈だと思うかもしれないくらい。

ですが、それでいい。

「グッドエンド」と呼ばれているものも、いわゆる普通の美少女ゲームと比べたらなんてことないです。「日常のささやかな一コマ」の範疇に収まってしまうかもしれません。でもそれでいいんです。なんでそれでいいのかわかりませんが、それでいい。

物語は、ココアさんがチノちゃんの誕生日(12月4日)が数週間後に近づいていることを知るところから始まります。

そしてココアお姉ちゃんは決心します。今年のチノちゃんの誕生日を、最高のものにしよう、と。

そのために、バイトを頑張って、あとコスプレしてチラシ配りをして、ラビットハウスの知名度をあげて喜んでもらおう、と。

…かなり発想が飛躍しています(たぶんシステムが決まってからシナリオが逆算されたんだと思う)。が、物語の中で「あれ?なんでチラシ配りしてたんだっけ??」ってココアさんも忘れる描写があるのでOKです。これを書いてて、わたしもなんでチノちゃんの誕生日のためにチラシ配りしてたのか忘れました。俺もココアだ

バイトのパートは正直難しいです。たくさんのオーダーにワーキングメモリが押しつぶされそうになります。でも、それもチノちゃんの誕生日を最高のものにするためです。バイトがうまくいってラビットハウスの知名度が上がるとなぜかうれしいのです。

チノちゃんの誕生日までに特定のキャラクターとの親密度をあげるか、ラビットハウスの知名度を最大にあげないと、(チノちゃんは喜んではくれるのですが)そこで物語は終わります。ここで「もっとチノちゃんに喜んでもらえる、最高の誕生日にできたはずなのに」という、悔しさにも似た感情が発生します。チノちゃんにモテなくて悔しいんじゃない、チノちゃんの誕生日を最高のものにしてあげられなかったことが悔しいんだ。これでは俺はお姉ちゃん失格だ。

チノちゃんの誕生日を最高のものにすることができたら、そのお返しとしてのクリスマスパーティを準備する、第二の物語が続きます。
この時は、(チノちゃんルートの時は)わたしはチノちゃんになります。

システム自体はいわゆる普通のギャルゲーで、三択したときに正解だと「友情度」が上がってエンディングが分かれるやつです。

でもそんなのはどうでもいい。チノちゃんになれば、自ずと選ぶべき選択肢はわかります。少なくともそんな気持ちになります。ほんとです。

あんなに素敵な誕生日を用意してくれたココアさんにお返しがしたい。でもわたしは、みんなでわいわいするパーティなんて開いたことないし、そもそもクリスマスといえばもっと慎ましく過ごすものだと思ってた。でも、そんなクリスマスじゃ、きっとみんな退屈しちゃう…どうしよう…。

チノちゃんは人に頼るのが苦手です。ですから、相談するのもいちいち憚ってしまう。ココアさんは相談してねと重ね重ね言ってくれるけれど、ココアさんにお返ししたいのだから、ココアさんには頼れません。最終手段です。

ラビットハウスはクリスマスももちろん営業があります。だから、一日貸し切って、なんてこともできません。仕事の後にパーティを開くしかない。そこがまたリアルなんです。

そんな彼女が出した「クリスマスパーティ」の答えは何か?これはもちろん遊んで確かめてほしいのですが、ココアさんのようなみんなを巻き込んだ盛大なものでは決してない、彼女なりのささやかな、でも一生懸命な素敵な答えです。


パジャマパーティーたのしそう

前半パートでは、毎週末集まってパジャマパーティがあります。これがまた楽しい。

そしてわいわい遊んだ後は、ココアさんとほかの誰かで一緒の布団で寝ます。添い寝しながら楽しく喋って寝る、それだけです。エロゲーは理解できなかったわたしでも、これなら理解できる。「ココアさんになれ」ました。楽しい。

「2人で一緒に寝たら残りの3人はどうしてるんだろう」と思わないではないが、そこは…きっと描かれてない3人の物語があるに違いない。


俯瞰してみると、「モバ美ちゃんPV」と同じく、「美少女 ⇔ 消費するオタク」みたいな構図を極力避けるようなシナリオとシステムになっています。ココアさん「だけ」になるんではなく、後半はほかのキャラクターにもなるので、一切片方向の視点で終わることがありません。ココアさんだけの視点でゲームが最初から最後まで完結していたら、きっとココアさんが実質的に「モテる主人公」になってしまっていたかもしれません。でも、このゲームでは、後半ではココアさんのために奔走することになります。ここがいやな感じが一切しない。