はじめに
こんにちは。2024/3/11〜2024/3/29の3週間、アカツキゲームスのインターンに参加させていただきました。今回はインターンで取り組んだ事・学んだことを紹介させていただきます!
自己紹介
東京理科大学修士2年の井出と申します。私は大学入学時からプログラミングをし始め、現在ではC++を使ったソフトウェア開発のアルバイト・pythonを使った画像処理分野の研究・Go言語を使った趣味での個人開発を行っています。
アカツキゲームスのインターンを志望した動機
私がインターンを志望した理由として、ゲーム業界でのサーバーサイドエンジニアがどういった業務をしているのかを肌で実感したかったという事が挙げられます。私が持っているモットーとして、「良いプロダクトは楽しく開発できなきゃ作れない」と考えています。その中でゲーム開発は楽しく開発するというスタンスが強いのではないかと思い、アカツキゲームスのインターンに応募しました!
取り組んだ内容
私が今回のインターンで取り組んだタスクは合計で3つでした。その中の1つをピックアップして紹介したいと思います。
Pngyu代替ツールの作成
アカツキゲームスでは、PngyuというGUIツールを使っていました
Pngyuとは?
Pngyuは、複数のPNG画像ファイルを一括で圧縮することができるユーザーフレンドリーなツールです。マウス操作だけで簡単に画像を圧縮できるため、デザイナーやゲーム開発者からの支持を受けています。
画像圧縮の必要性
ゲーム開発では、多数の画像が使用されます。タイトル画面、ガチャのお知らせバナー、ポップアップ通知など、これらの画像はゲームの魅力を伝える重要な役割を担っています。しかし、画像ファイルはテキストファイルと比べてデータサイズが大きく、そのまま使用するとゲームの読み込み速度を遅くしたり、パフォーマンスに影響を与える可能性があります。そこで画像の圧縮が重要となりますが、一枚一枚手動で処理するには時間がかかります。こうした背景から、Pngyuのような一括圧縮ツールが現場で頻繁に利用されていました。
画像圧縮の理論
画像圧縮はデジタル画像ファイルのデータ容量を削減するために用いられる技術です。ここでは、その原理について解説します。
例として、24ビットのフルカラー画像を考えてみましょう。この形式では、各ピクセルはRGB各色を8ビットで表現し、合計で3バイトのデータを使用します。これにより、約1677万色(正確には16,777,216色)を再現できます。 イメージとしては以下のような形です。
フルカラー画像のデータ容量を削減する方法の一つに、インデックスカラーへの変換があります。この方法では、使用する色の数を256色(1バイト)に限定し、各ピクセルに色のインデックスを割り当てることでデータ量を減少させます。各ピクセル情報とは別に、「カラーパレット」とよばれるデータがあり、色のインデックスごとにRGB各色の情報量を保持します。イメージとしては、以下のような形です。
このようにすることで、画像全体で1/3のデータ容量に収める事が出来ます。Pngyuではこれを内部的に行っています。
問題発生
しかし、使用していたPngyuが突然動作しなくなりました。公式のリリースノートを調べると、最後の更新は2013年11月4日であり、10年以上の歳月が経過しています。技術の進歩と共に、古いソフトウェアが互換性の問題で動かなくなるのは珍しくありません。
そこで
画像の圧縮は今後も行う必要があるため、Pngyuの代替となるツールを作成する事になりました。Pngyuでは圧縮エンジンにpngquantというライブラリを使用しており、macのターミナルでも使える圧縮ツールでもあります。幸いにもアカツキゲームスでは、会社で貸出されるPCはmacであったため、「pngquantを使って複数画像を一度に圧縮するシェルスクリプト」を作成すればよいため、これを作成しました。
pngquantのコマンド詳細
では、実際にどのようにコマンドを実行すべきなのか解説します。
pngquant 256 sample.png
上記のように実行すると、sample-fs8.png
が作成されます。
これだけの解説では寂しいので、pngquantのオプションについても一部解説します。
--outputオプション
--output <filename>
とすることで、出力先のファイル名を指定できます。
--qualityオプション
前提知識として、pngquantは画像を圧縮する際に、設定された「最大品質」を満たすために必要な最少の色数を使用します。このとき、画像の品質が「最小品質」を下回ってしまう場合、その画像は保存されず、代わりに元の24ビットカラーの画像が出力されます。ここで言う「品質」とは、「画像を圧縮する際にどれだけの色情報を保持し、元の画像にどれだけ近い見た目を維持できるか」という割合です。
今回の場合、「品質に関係なく、画像が圧縮される(ビットの深さが8ビットになる)」ことが最優先であったため、<min>
を0, <max>
を100で指定しました。
--speedオプション
簡単に言うと、実行速度を早くしたり遅くしたりするオプションです。実行速度が速いほど圧縮後の画像が荒くなり、逆に遅いほど品質が向上します。今回、実行速度はそこまで気にする必要がなく、「複数の画像を一度に圧縮できれば良い」ため、--speed 1
としました。
実際に作成したシェルスクリプト
以下が実際に作成したシェルスクリプトです。
#!/bin/sh -e IMGS_PATH="./input/*.png" OUT_DIR="/output" cd "$(dirname "$0")" # outputフォルダが作成されていなければ作成する if [ ! -e $OUT_DIR ]; then mkdir $OUT_DIR fi # input フォルダ内の画像を圧縮 for img in `find $IMGS_PATH` do #ファイル名のみを取得 BASE_NAME= `basename $img` # 出力先のパスを指定 OUT_IMG_PATH="$OUT_DIR/$BASE_NAME" echo "$BASE_NAME を圧縮中.." if [ -e $OUT_IMG_PATH 1]; then rm -f $OUT_IMG_PATH fi pngquant --output $OUT_IMG_PATH:--quality 0-100 --speed 1 256 $img echo "$OUT_IMG_PATH に圧縮した画像を保存しました\n" done
インターンを通して学んだこと
質問することの大切さ
インターンを始める前は「些細なことでも分からない事を質問をする」のが恥ずかしいと思っていました。しかし、現場独自のコードの書き方であったり、社内専用のデバッグシステムの使い方があるため、質問しなきゃ分からない事がとても多かったです。タスクをこなしていく中で「分からない事をそのままにしている」事の方がよっぽど良くない事に気づきました。
コードに対する責任感
エンジニアにとって「責任感のある仕事」ってなんだろう?と以前からずっと思っていましたが、その答えが出た気がしています。インターンのタスク中に「自分の書いたコード・書き直そうと思っているコード」それぞれのメリット・デメリットをまとめ、説明する機会がありました。 今まで「こうした方が良いのではないか?」という感覚的にしかコードを書いてこなかったため、自分の中だけで完結していました。しかし、今回メリットデメリットをまとめ、説明する中でエンジニアにとって「責任感のある仕事」とは、自分の書いたコード1つ1つに対し「なぜその書き方にしたのか」「どういう意図を持って書いたのか」を他人に説明できる事であると感じました。
コードレビューの大切さ
自分の実装した機能をコードレビューしてもらう機会を何度もしていただきました。その中でElixirのコードの書き方やテストコードの書き方であったり、(これは恥ずかしいですが)自分で気付かなかったようなスペルミスをレビューしてもらいました。コードレビューをする事でよりコードの保守性が向上すると実感しました。
感じたこと・感想
楽しかった!
本当にこれに尽きると思います。開発を進める中で自分がマスタデータやAPIの設計を行うタスクがあり、サーバーエンジニアの方以外にも、プランナーさんやクライアントさんと話し合う機会がありましたが、話した人全員「ゲームをよりよくしていこう!」という雰囲気が感じられました。また、そんな方たちと一緒に開発ができていると実感でき、とても楽しく感じられました!
つよつよエンジニアがたくさん!
今回のインターンでは、サーバーエンジニアの業務に潜ってタスクをしていました。自身のタスクをこなしつつチームメンバーと1on1面談を沢山やっている人や、レビューを依頼すると1,2時間後には完璧にコードレビューをまとめてくれる人、1人で多くのタスクを抱えながらてきぱき捌けている人など尊敬できる人が多く、とても刺激のあるインターンでした!
最後に
初日は「やり切れるのか」という不安もあり、緊張していましたが、タスクをこなしていく中で少しずつ自信が付き、3週間があっという間に経っていました。3週間を通して、楽しいだけじゃなく、自分が今まで知らなかった知識や自分の弱点を知れる、学びの多いインターンだったと感じています。メンターの方、インターンシップに参加する機会を提供してくださった人事の方など、すべての方に感謝しています。3週間ありがとうございました!