VOYAGE GROUP エンジニアブログ

voyagegroup_techのブログ
VOYAGE GROUPエンジニアブログです。

2011年06月

ソーシャルゲームな画像合成のススメ ~ GDとImagickの比較とともに


ECナビの子会社unigameでソーシャルゲームの開発をしている谷西(@tnnsst35)といいます。
新卒入社3年目のまだまだひよっこですが、お付き合いいただければと思います。

今回僕がお話しするのは「画像合成」についてです。

* 画像合成って?

ソーシャルゲームでは、キャラクターの表情、洋服、持ち物など、組み合わせ方によっては何パターンも存在するような画像を扱う必要があります。
そんな数え切れないパターンの画像をひとつひとつデザイナーに作ってもらうのは気の遠くなる話です。
そこで登場するのが、「画像合成」です。

画像合成は文字どおり、画像Aと画像Bを合成して、新しく画像Cを生み出すということです。

unigameで開発しているほぼ全てのソーシャルゲームで画像合成は登場しています。
unigameではPHPのGDライブラリを用いて画像合成をしています。

* GDで画像合成

例として
キャラクター(img/chara.gif) に 青い洋服(img/wears/blue.gif) を着せた画像を img/compose/blue_chara.gif として保存する方法をGDでやってみましょう。

<?php
    $baseImg = imageCreateFromGif('img/chara.gif');       //img/chara.gifを読み込む
    $wearImg = imageCreateFromGif('img/wears/blue.gif');  //img/wears/blue.gifを読み込む

    $size = getImageSize('img/wears/blue.gif');           //img/wears/blue.gifのサイズを取得する
    $width  = $size[0];
    $height = $size[1];

    imageCopy($baseImg, $wearImg, 16, 32, 0, 0, $width, $height);  //画像を合成する

    imageDestroy($wearImg);                                        //メモリを開放する

    $newFile = 'img/compose/blue_chara.gif';
    imageGif($baseImg, $newFile);             //img/compose/blue_chara.gifとして書き出す
    chmod($newFile, 0775);                    //権限を775に変更する

    imageDestroy($baseImg);                   //メモリを開放する
?>
 
どうでしょうか?

ソースコードをみてみると、実に簡単でわかりやすい処理なのかがわかると思います。
imageCreateFromGifで画像を読み込み、imageCopyに読み込んだ画像と合成する座標を引数で渡し、imageGifで書き出す。
たったこれだけで出来てしまいます。
また、複数の画像を合成したい場合は、imageCopyを繰り返せば実現できます。

実際の運用では一度保存した画像は再度合成しないように file_exists でファイルがなければ合成するようにします。


<?php
    $newFile = 'img/compose/blue_chara.gif';
    if (!file_exists($newFile)) {
        //画像合成の処理
    }
?>

* Imagickで画像合成

unigameではGDを用いていますが、他にもいくつか方法はあるようです。
今回は PECL::Imagick を用いた方法も試してみました。


<?PHP
    $baseImg = new Imagick('img/chara.gif');         //img/chara.gifを読み込む
    $wearImg = new Imagick('img/wears/blue.gif');    //img/wears/blue.gifを読み込む

    $baseImg->compositeImage($wearImg, $wearImg->getImageCompose(), 16, 32);  //画像を合成する

    $wearImg->destroy();                      //メモリを開放する

    $newFile = 'img/compose/blue_chara.gif';
    $baseImg->writeImage($newFile);           //img/compose/blue_chara.gifとして書き出す
    chmod($newFile, 0775);                    //権限を775に変更する

    $wearImg->destroy();                      //メモリを開放する
?>

コードをみるとわかりますが、やってることはGDとほとんど変わりません。
一見するとどちらでやっても同じ結果を生み出すので、どちらも採用しても良い感じがしますが、
実は速度に差があるのです。

* GDとImagickの比較

画像合成する処理を 10000回繰り返し行い、かかった時間を測定するテストを行いました。


<?PHP
    //GDのテスト
    $startTime = time();

    for ($i = 0;$i < 10000;$i++) {
        $baseImg = imageCreateFromGif('img/chara.gif');       //img/chara.gifを読み込む
        $wearImg = imageCreateFromGif('img/wears/blue.gif');  //img/wears/blue.gifを読み込む

        $size = getImageSize('img/wears/blue.gif');           //img/wears/blue.gifのサイズを取得する
        $width  = $size[0];
        $height = $size[1];

        imageCopy($baseImg, $wearImg, 16, 32, 0, 0, $width, $height);  //画像を合成する

        imageDestroy($wearImg);     //メモリを開放する
        imageDestroy($baseImg);     //メモリを開放する
    }

    $endTime = time();

    echo 'GD : ' . ($endTime - $startTime);

    //imagickのテスト

    $startTime = time();

    for ($i = 0;$i < 10000;$i++) {
        $baseImg = new Imagick('img/chara.gif');         //img/chara.gifを読み込む
        $wearImg = new Imagick('img/wears/blue.gif');    //img/wears/blue.gifを読み込む

        $baseImg->compositeImage($wearImg, $wearImg->getImageCompose(), 16, 32);  //画像を合成する

        $wearImg->destroy();                      //メモリを開放する
        $wearImg->destroy();                      //メモリを開放する
    }

    $endTime = time();

    echo ', imagick : ' . ($endTime - $startTime);
?>

テスト1回目 GD : 4, imagick : 10 
テスト2回目 GD : 4, imagick : 11 
テスト3回目 GD : 5, imagick : 10
テスト4回目 GD : 4, imagick : 9
テスト5回目 GD : 4, imagick : 11

テスト100回してみましたが、GDの方がimagickに比べて2倍の速度があることがわかりました。
画質に関してはフィーチャーフォンでみる分には、ほとんど違いがありませんでした。

* まとめ

ソーシャルゲームでは、どれだけ早くレスポンスを返せるのかということが、ストレスなくゲームを楽しんでもらうための重要な指標のひとつになります。
PHP×ソーシャルゲーム×画像合成にはGDをオススメしたいと思います。

※ 今回のベンチマークで使用した環境はSakura InternetのVPS512プランです。
  環境によっては必ずしも同じ結果にはならない事もありますので、ご了承ください。 

「PHPでTDD&CIワークショップ」に参加してきました

初めまして。中村(@tomomihoge)と申します。
5月よりECナビの中の人になりました。

今回は、先日グリーさんで開催されました勉強会、「PHPでTDD&CIワークショップ」に参加しましたので、そちらについてお話しようと思います。

[概要]

勉強会の大まかな流れは以下の通り。

  1. テスト駆動開発(以下TDD)、継続的統合(以下CI)に関して概念の説明や、周辺の話題に関して座学。
  2. TDD 組と CI 組に分かれて実践形式で演習(ワークショップ)。
  3. 懇親会
なお、私の知識レベルは
  • TDD, CI について概念は抑えてる
  • どんなツールがあるかも知っている(代表的なものくらいは・・多分)
  • テストは書いたり書かなかったり(少なくともテスト・ファーストは実践してない)
  • CI は経験ゼロ
と言ったところです。

こんな状況なので CI ワークショップを選択しました。
実際どんなものか見てみたかったのと、先駆者から実運用する際のアイデアを吸収したかったので。

1. 2. については他の方のレポートを参照していただくとして、私は 3. についてお話しようと思います。

[CI ワークショップ]

ワークショップのスタイルですが、事前に環境をある程度用意して、実践すると言ったものでした。
これは時間圧縮に有効だなと思いました。
一方、事前の環境がバラッバラなので VM 用意してそこからスタート、みたいなのもアリだと思いました。

参加者は15名ほどでしたでしょうか。
全体では50名ほどで、TDD を選択された方が多かったです。

ワークショップの内容はまさに↓こちらの資料の通りです。
PHPでTDD&CIワークショップ、Jenkins + PHP の各種プラグインパート資料

かいつまむとこんな感じ。
  1. 環境作る
  2. サンプルジョブ作って実際に動かして大まかな流れ確認
  3. 各種プラグインとの連携
特に 3. に入ってから実践的な内容を多く聞かせていただきました。
現実(メンテコストの高い既存コード)とどう向き合っていくか、
その中で Jenkins をどう活用しているか、興味深かったです。
  • 閾値を調整して、現在を出発点にする。現状より悪くしない、新しいコードは綺麗に書く。
  • カバレッジは100%が理想だけど、少しずつ増えていけばそれでいい。完璧を目指すより向上を実践する。
とかく「1から始まるプロジェクトなら使えるけど、途中から導入するのは無理ゲー」
と逃げがちな自分には、自省することしきりでした。

[その他]

合間に参加者の開発環境について聞いてみました。
Eclipse が数名、Emacs が 2名、Vim が残り全部でした。
この割合は現職の割合とも類似してます。

また Windows ノートで参加してたのは 3 名程度だったでしょうか。
残りの方達は全て Mac で、Web 系ってこういう感じなんだなーと。
(前職では Windows 一色でした。)

[懇親会]

ワークショップは22:00を超えたあたりで終わったのですが
その後、質疑応答やらなんやらで22:30になっても席を立つ人はまばら。
CI話でご飯三杯いける状態で、懇親会と言う名のアディショナルタイムでした。
私にはこっちの方が気楽でいいですね。

非常に有意義な勉強会でした。
今回 DB のテスト(DB と言うか DAO 層部分)をどうやっているのか聞きそびれてしまったので、次回はそちらも盛り込んでいただけたらなぁ(チラッ
次の機会も是非参加したいです。

会場を提供していただいたグリーさん、CIワークショップ講師の @cactusman さん、@yamashiro さん、ありがとうございました。

※ にしても、記念すべき一回目の投稿がコード1行もなしってお前・・・。次回はもう少しテクニカルな何かを書きます。

「プロジェクトが失敗する要因 見積り編」という勉強会を行いました。

こんにちは、CTOの小賀(@makoga)です。

ECナビでは「テーマを決めてお話しよう勉強会」とか「テーマを決めてほげほげ勉強会」と呼ばれるエンジニアが自分でテーマを決めて発表する勉強会を行っています。

    第1回 メール配信システム
    第2回 バージョン管理とデプロイ
    第3回 プレゼンテーションにおける提示資料作成技術

第3回の@bash0C7からご指名を受け、第4回目は僕が発表しました。テーマは「プロジェクトが失敗する要因」です。タイトルがつりっぽいところもあり30名以上が参加しました。エンジニア以外の人からもなかなか好評だったので、その後同じ内容でもう1回行ったところ、こちらは半数以上がエンジニア以外となり全体で30名ほどが参加しました。どちらの回でも質問がたくさん出て、僕も理解が深まり、やはり情報は発信するところに集まることを実感しました。

一応そのときの資料をslideshareにアップしてみましたが、説明しないと???な感じに仕上がっておりますw

資料について少し補足します。今回はまず用語の認識をあわせるところから始めました。「プロジェクト」についてはプランニング・オニオンをベースに説明し、「プロジェクトの成功・失敗」についてはCHAOSレポートから引用した文章を元にそこから自社の特性に合わせ説明しました。ようやく認識があったところで今回は特に見積もりに特化するよと宣言し、覚えてほしいこと3つ「不確実性コーン」「規模と期間」「正確さと労力」について説明しました。ここを文章だけでうまく説明するのは難しいので興味のある方は『アジャイルな見積りと計画づくり ~価値あるソフトウェアを育てる概念と技法~』を読んでみてください。とても良い本です。

次回は不確実性に備えるバッファあたりの話をしようと思います。

ECナビ インターンシップ募集開始 ~ミチをソウゾウせよ~

こんにちは、 システム本部の吉村と申します。
ECナビでは仲間と共にゼロから'もの創り'を実践するインターンを毎年夏に開催しており、今回で6回目となります。
開催期間は、2011/8/15(月)から2011/9/9(金)までです。

詳細は、もの創り実践プログラム「Treasure」|ECナビ インターンシップ ~ミチをソウゾウせよ~ をご覧下さい。

ECナビ エンジニアブログの執筆者たちも、 インターンのサポートを行ないます。
またインターン期間中は、CEO,CTOからの話や現役エンジニアへの質問コーナーを企画しています。
圧倒的に成長したいあなたのエントリーをお待ちしております。

昨年のインターンの様子は、過去エントリーをご覧下さい。 
記事検索
QRコード
QRコード