KLabGames Tech Blog

KLabは、多くのスマートフォン向けゲームを開発・提供しています。 スマートフォン向けゲームの開発と運用は、Webソーシャルゲームと比べて格段に複雑で、またコンシューマゲーム開発とも異なったノウハウが求められる領域もあります。 このブログでは、KLabのゲーム開発・運用の中で培われた様々な技術や挑戦とそのノウハウについて、広く紹介していきます。

このエントリーは、KLab Advent Calendar 2017 の12/4の記事です。

今年のISUCONはKLabが作問するということで、ゲームが題材だと予想していた方も多かったと思います。 その期待(?)に応えるべく、本選ではCookie Clickerを元にしたゲームを出題しました。 これを複数人で協力プレイできるようにして、WebSocketを使っていて、クッキーではなく椅子を増やし、椅子の数が多倍長整数になる、というゲームでした。

この記事では @hasi_t がISUCON7本選の作問でやったことを書きます。

プロトタイプ作成

まずプロトタイプ作成を担当しました。 Cookie Clickerを元にする、という案が出ていたので、自分がやりたい要素を入れたプロトタイプを作りました。

一つ目の要素は未来計算と操作遅延です。 サーバが未来の値を計算できるようなデータを返し、クライアント側で各時点での値を計算するようにする、という設計です。 そして操作を遅延させることで可能な限り同時刻での見え方が同じになるようにしました。 このような設計によって通信頻度を下げる、というのは、 CEDEC 2015で発表したことの実践で(参考)、 それを実現するための技術や開発体制について普段の業務で日頃考えていたりするのですが、 その実態を見せる機会と考え、この要素を入れました。

二つ目の要素は多倍長計算です。 以前、 ICFPC 2016 というプログラミングコンテストに参加したときに多倍長有理数を使って、 こういう多倍長計算を使った問題を作りたいと思っていた、というのがあります。 あと、メモリを消費させて、ただキャッシュするだけでは駄目なようにしたい、というのも考えていました。

ちなみに、作問チームのうち3人 (@mecha_g3, @___Johniel, @hasi_t) はここ4年ほど、この3人だけではないですが、DiamondPrincessというチームでそのICFPCに参加しています。そして今年は2位でした!

プロトタイプの時点ではWebSocketではなく、普通のHTTP通信で、サーバはPHPで雑に書いた状態でした。 ver0とver1を作ったのですが、ver0の時点ではミリ秒単位ではなく秒単位だったりしました。 あと、命名が雑すぎて抽象的な一文字変数名だらけになっていたので、本実装時に名前の調整が結構大変でした。

本実装作成

WebSocketを使うことになり、初期実装は他の人に任せて、 ゲーム画面を作るためにJavaScriptコードをロジックとビューに分割したり、 いい感じのフォントを探したりしていました。

ベンチマーカのバリデーション作成

未来計算の設計時点で、ベンチマーカから見て検証可能にすることを考えていました。 誤差を許容するには、許容範囲やそれに合わせた計算など、考えることが多く、それを避けた結果、厳密な検証になりました。 そのため、値が1でもずれるとfailするという厳しいコンテストになりました。

負荷走行前の検証はaddIsu, buyItemに対するレスポンスが必ず存在するので良かったのですが、 負荷走行後の検証はタイムアウトなどでレスポンスが無い場合を考える必要があり、 上限と下限を考えて検証する必要があってちょっと大変でした。

エラーメッセージを参加者にとってわかりやすくする、という作業をするのがぎりぎりになってしまい、 初期実装作成者には苦労をかけてしまいました。

ベンチマーカのチューニング

当然といえば当然ですが、初期実装そのままで検証していたら、 負荷走行後の検証の実行時間が長すぎる問題が発生し、高速化をしました。

やったこととしては、指数表記変換関数の高速化、item価格と生産速度のキャッシュ、1000回ループの回避、指数表記変換関数内の10のn乗のキャッシュ、addingの累積和を使う、などです。

実装は以下の通りです。指数表記変換関数(big2exp)はutil.goにあります。

とりあえず、Go言語のbig.Intは、つらい、という感想でした。

マスタデータ調整

いい感じのマスタデータにしないと多倍長使う意味が無い、と思っていたので、 1分間のベンチマークで10の10万乗ぐらいまで到達できるようにマスタデータを調整しました。 調子に乗って1個目の購入価格が10の10万乗ぐらいあるアイテムを作ったら、 初期実装の時点でそこが重すぎて、リハーサルやってみたけどまともにチューニングできない、 みたいなことも起きたりして申し訳ない感じだったりしました。

ちなみに、Excelで値を調整して、Pythonスクリプトで雑なシミュレーションをする、ということをしていました。 もちろん、値を直接扱えないので、対数をとって計算していました。

おわりに

参加者の皆様、運営の皆様、お疲れ様でした! いろいろご迷惑おかけしましたが、出題することができて嬉しく思っています。 ありがとうございました!

(本稿はKLab Advent Calendar 2017 の3日目の記事になります)

昨今、電子工作やマイコンプログラミングへのハードルが急激に下がっているという印象があります。皆さんの身の周りでもArduinoやRaspberry Piに秋葉原で買ったセンサーを繋いで遊んでいる人がいるのではないでしょうか?

私の所属しているKLab株式会社にも「Make部」という部活があり、毎年Maker Faire Tokyoで各個人が作品を展示したり社内勉強会を開いたりして、業務と無関係に電子工作を楽しんでいたりします。

ふつうのLinuxマシンでもセンサー類を扱いたい

とはいえ、ArduinoもRaspberry Piも普段使っているLinuxマシンやmacOSマシンとは随分異なる環境です。ふつうのLinuxマシンにセンサーを接続して、気軽に扱えないものでしょうか?

Raspberry Piでセンサー類を簡単に扱えるのは、GPIOインターフェースが存在するためです。GPIOピンと各種センサー類やサーボモータなどを接続することで、Linux+電子工作の組み合わせが簡単に実現できるよ、というのがRaspberry Piの強みだと言えるでしょう。

Raspberry PiのGPIOピン

一方で、多くのLinuxマシンにはGPIOインターフェースが存在しません。たとえばUSB to I2C変換モジュールを使えばLinuxマシンでも電子工作的な遊びはできますが、追加の出費が必要ならRaspberry Piを買った方がマシだよ、となってしまいそうです。

本稿では、DigiTempを使ってLinuxマシンで比較的安価に温度センサーを扱う方法を紹介します。DigiTempはLinuxのシリアル通信インターフェース経由で1-Wire接続のセンサーを扱うOSSで、多くのLinuxディストリビューションで標準パッケージとして採用されています。

ソフトウェアのインストール

まずはソフトウェアのインストールをしましょう。大抵の環境でDigiTempはコマンド一発で入るはずです。

Debian系なら apt でインストールできます。

$ sudo apt install digitemp

RedHat系は yum でインストールできます。

$ sudo yum install digitemp

macOSでも遊べます。Homebrewからインストールしましょう。

$ brew install digitemp

後述するようにシリアル通信ドライバも必要です。こちらは利用するシリアル変換ICに応じて適切なドライバをインストールしてください。

ハードウェアの準備

当然ですが、ソフトウェアだけで外気温の測定はできません。DigiTempの利用には下記のような準備が必要です。

USB to シリアル変換モジュール

USBからシリアル通信(UART)への変換モジュールです。Arduinoで遊んだことがあれば必ず1個は持っているのではないでしょうか。変換ICとしてはFTDI社のFT232RLなどが有名ですが、他にもSilicon Labs社CP2102やProlific社 PL2303を採用した変換モジュールも容易に入手できます。

ちなみに私はCP2102ベースの変換モジュールを利用しています。これはeBayで1.15ドルでした。

CP2102 USB to シリアル変換モジュール

FTDI製ICを使っているモジュールであればドライバは標準でインストールされていることが多いかもしれません。それ以外の場合は手動でドライバをインストールする必要があるはずです。

温度センサ DS18B20

DS18B20はMaxim Integrated Products社製の温度センサです。秋月で買うと1個250円ですが、eBayなどを探せばもっと安いものも見つかります。

DS18B20

このセンサーは1-WireというMaxim独自のプロトコルで動作します。このプロトコルがUART経由で扱う上でのキモです。1-Wireはデータレートが低速かつ通信線1本で動作するので、UARTからでもドライブできるのです。他のプロトコルのセンサーであれば何らかのICが必須になるでしょう。

UARTとDS18B20の接続用ボード

UARTとDS18B20を直結しても動くことは動くらしいのですが、逆流防止などの用心のため、簡単な回路を工作してみました。

UART to DS18B20 接続用ボード

これはdword1511/onewire-over-uartで紹介されている下記の回路図を元に作成したものです。

回路図

材料は下記の通りです。

  • ユニバーサル基板
  • L型ピンソケット(1×6、メス)
  • 5.1kΩ 抵抗
  • スイッチングダイオード 1N4148
  • ポリウレタン銅線(配線用)

動かしてみる

これらを組み合わせると次のような見た目になります。思ったより場所を取る感じの仕上がりになってしまいました。

完成図

これをLinuxマシンのUSBに接続して、先ほどインストールしたDigiTempを起動すると温度が取れます。

コマンドの使い方として、まずは-wオプションを指定して1-Wireデバイスのスキャンを行う必要があります。-sオプションはシリアルポートの指定です。

$ /usr/bin/digitemp_DS9097 -s/dev/ttyUSB0 -w
DigiTemp v3.7.1 Copyright 1996-2015 by Brian C. Lane
GNU General Public License v2.0 - http://www.digitemp.com
Turning off all DS2409 Couplers
.
Devices on the Main LAN
28FF933161150389 : DS18B20 Temperature Sensor

これで接続されているセンサーの情報が$HOME/.digitemprcに記録され、次回以降の起動でこの情報を参照するようになります。

$ /usr/bin/digitemp_DS9097 -a -d 2 -n 5
DigiTemp v3.7.1 Copyright 1996-2015 by Brian C. Lane
GNU General Public License v2.0 - http://www.digitemp.com
Dec 02 21:21:27 Sensor 0 C: 21.50 F: 70.70
Dec 02 21:21:29 Sensor 0 C: 21.56 F: 70.81
Dec 02 21:21:31 Sensor 0 C: 21.50 F: 70.70
Dec 02 21:21:33 Sensor 0 C: 21.50 F: 70.70
Dec 02 21:21:35 Sensor 0 C: 21.44 F: 70.59

上記は2秒間隔でセンサーの値を5回取得する指定です。摂氏と華氏で温度が取れているのがわかります。

ちなみに、筆者はこれを家のLinuxルータに刺した上で取得した値をMackerelに書き出しています。

温度変化グラフ

上記のグラフが作りたいだけならRaspberry Piで温度センサーを扱った方が楽なのでは?と思われるかもしれません。理屈で言えばそうかもしれませんが、個人的にRaspberry Piは長期間電源を入れっぱなしにする気が起きないので、ふつうのLinuxマシンで運用できることに価値があるように感じています。同じ感覚の方が他にいらっしゃるかはわかりませんが…。

まとめ

  • DigiTempというLinux/macOS上で温度センサーDS18B20を扱うOSSを紹介しました
    • シリアル通信(UART)経由で1-Wireセンサーをドライブできます
    • 多くのLinuxディストリビューションで標準パッケージ採用されています
  • Raspberry Piで同じことをするより適用範囲が広かったり長期運用しやすかったりするかもしれません

@hnw

(本稿はKLab Advent Calendar 2017 の1日目の記事になります)

2017年のKLabのアドベントカレンダーです。最初はoho-sです。よろしくお願いします。

自分が作ったVRコンテンツをどんなのか説明したい!

VRコンテンツを作っていて、自分が作ったVRコンテンツをどんなものか説明したり共有したい時ってありませんか? ハイスペックPCやVR用HMDを持っていない人にも、雰囲気だけでも伝えたい。そんな時に便利なのが、いわゆる360°動画でのキャプチャです。 今回は、Facebookが公開している、360-Capture-SDKを使ってキャプチャしてみます。日本語での使い方の情報が探してもあまりなかったので、参考になれば幸いです。

Facebookの360-Capture-SDKを使ってみる

360-Capture-SDKの動作環境は、こちらを参考にしてください。 Windows(64bitのみ)の8以降で、NVIDIAもしくは、AMDのGPUが必要になります。各ドライバのバージョン指定があるので確認してください。 対応しているUnityのバージョンは、README.mdに記載がありませんが、今回Unity 5.5.3p3 (64-bit)で動きました。一方、Unity 2017.2.0p2 (64-bit)では、動画のキャプチャはできましたが、画面の表示がされないなどの不具合が見られました。

さて、では使ってみましょう。まず、キャプチャしたいUnityプロジェクトにSDKを組み込みます。 360-Capture-SDKが公開されているリポジトリは、こちらです。 このリポジトリをcloneしてきて、 Samples/Unity/Assets 以下のEncodePackageフォルダとPluginsフォルダをそのまま組み込みたいプロジェクトのAssets以下にコピーします。

次に、EncodePackage内の、EncoderObjectプレファブをシーンに置きます。

組み込み

そして、EncoderObjectのインスペクターからいくつかの録画用パラメータなどを修正などします。 負荷とクオリティを考えて、ピクセル数などを選びましょう。 EncoderObjectの位置がキャプチャの中心位置になるので、適切にPositionを設定します。少し離れた位置にすると、観客視点とかもできると思います。

最後にキャプチャをします。 プロジェクトを実行して、キャプチャしたいポイントでF2キー(デフォルトでは。インスペクターで変更可能)を押すとキャプチャ開始、F3キーで停止です。キャプチャした動画は、プロジェクトフォルダのGallery内に保存されます。

動画のメタデータの調整

ここまでの手順で作成した動画を、そのままYouTubeやFacebookに投稿しても360°動画再生の専用プレイヤーになりません。 動画に360°動画であることのメタデータを付けてやります。

そのためのツールが、こちらになります。

展開して実行すると下図のようなダイアログが出てくるので、「Open」からキャプチャした動画ファイルを選び、「Spherical」 のチェックボックスをオンにして「Inject metadata」します。以上で新しい動画ファイルができたと思います。

ダイアログ

アップロードしてみる

通常の手段でアップロードします。FacebookやYouTubeであれば、自動的に先ほどの手順でつけたメタデータに基づいて処理してくれて、360°動画として扱われるはずです。

サンプル動画ファイルリンク

まとめ

以上のように、比較的容易に360°動画でのキャプチャができてしまいました。 VRコンテンツのプロモーションなどに使えるのではないかと思います。 是非試してみてください。

最後に余談ですが、EncoderObjectのインスペクターを見ていると、どうもキャプチャーした動画のストリーミングができるようですが、試してみたところうまく動きませんでした。 この辺りも面白そうなので、今後調査を進めてみたいと思います。

KLab Advent Calendar 2017 の2日目は、haltさんです。よろしくお願いします。

↑このページのトップヘ