2014年5月22日木曜日

cocos2d-x CCSprite(テクスチャ)の軽量化

どうも、俺@仕事中です。

今日はcocos2d-xで頻繁利用するCCSprite(またはテクスチャ)の軽量化についてめも。
軽量化というのは、ファイルサイズ的な意味ではなくパフォーマンス面での軽量化という意味です。
ファイルサイズ的な意味での軽量化については最後に記します。

CCSpriteで画像生成するとけっこうなメモリを消費します。
けっこうなメモリとはどのくらいかと言うと、一般的なpng画像(24bitフルカラー)の場合、
1pxあたり4byte(赤8bit + 緑8bit + 青8bit + アルファ8bit)になります。
例えば200x200(px)のpng画像の場合、
200 x 200 x 4byte = 160000byte = 156.25KB
必要です。

なのですが、iPhoneや(ほとんどの?)Android端末で画像を処理する場合、
(2014.5.22修正 iPhoneやAndroidで実際にどのようにメモリ確保されるか不明)
利用するハードウェアによって、
画像(テクスチャ)のメモリは、2の累乗のサイズで確保されます。
どういうことかと言うと、
上の200x200サイズ画像の場合、256x256サイズとしてメモリ確保されるため、
消費メモリは
256 x 256 x 4byte = 262144byte = 256KB
になります。
なんと、これだけで約100KB無駄なメモリ領域が発生してしまいます。

500x600サイズ画像の場合は、
512 x 1024 x 4byte = 2097152byte = 2048KB
になります。
約900KB無駄なメモリ領域が。

画像を大量に使用するゲームアプリなどだと、かなり無駄なメモリが消費されてしまうことになります。


そこでこの問題の解決方法(1)として、スプライトシートを使いましょう。


スプライトシートは複数の画像をまとめて一つの画像として扱うため、
上記で述べたような無駄なメモリ領域というのを極力縮めてくれます。

次に解決方法(2)ですが、pngを出力する際に
透過を使わない → png24で出力
画像が荒くても構わない → png8で出力
という方法もあります。
png24は、24bitフルカラーで透過利用不可になります。
png8はGIFと同じ256色になります。

または、cocos2d-x側で、
    // 透過使わない
    CCTexture2D::setDefaultAlphaPixelFormat(kCCTexture2DPixelFormat_RGB565);
    // 減色させる(赤4bit + 緑4bit + 青4bit + アルファ4bit)
    CCTexture2D::setDefaultAlphaPixelFormat(kCCTexture2DPixelFormat_RGBA4444);
を呼び出しておく、という方法もあります。

このpng8で出力、またはkCCTexture2DPixelFormat_RGBA4444の設定は非常に効果的なのですが、画質が目に見えて荒くなるのが分かるのが残念です。
特にグラデーションは目も当てられません。

そこで、TexturePacker(基本有償)というツールを使いましょう。

有償なだけにとても高機能で、
TexturePacker上で画質を上述したRGBA4444に減色出来ます。
またすごいのが、画質が落ちた画像ファイルをディザリングという機能でキレイに加工してくれます。

例えば下の画像はRGBA8888の綺麗なままのpng画像。
※見やすいように拡大表示しています。

これをRGBA4444に画質を落とすと、
のようにグラデーション部分に荒い線が浮き出てしまいます。

これにディザリングをかけると、
のようになります。
荒いポツポツが目立ちますが、
拡大表示していることが原因で、実物サイズにすると
ほらキレイ。
目を細めてみると ほぼ元画像との違いなんて分かりません。

ちなみに、RGBA4444画質の元サイズはこちら。
うーん、、、
画像が小さいからあまり違い分からないですが、
やっぱりグラデーションが汚いです。そう思って下さい。

というわけでTexturePackerを使えば、
スプライトシートを生成できるだけでなく、画質の調整もできちゃうのでオススメです。



冒頭に書いた「ファイルサイズ的」な軽量化についてですが、
MacだとImageOptimがオススメです。

いろんなアルゴリズムを駆使して画像ファイルを圧縮し、ファイルサイズを小さくしてくれます。
ものによっては60%以上ファイルサイズが軽量化することもあります。
配布するアプリサイズが小さくなるので良いですね。
メモリへのロードも早くなるのかな?


あとは、CCSpriteBatchNodeを利用して、描画も軽量化させると見違えるほどアプリが軽くなります。

以上でぇぇぇぇぇす。

2014年5月13日火曜日

sshで "Received disconnect from xxx.xxx.xxx.xxx: 2: Too many authentication failures for" でログインできひん

どうも、俺@仕事中です。

sshでログインしようとして

$ ssh username@xxx.xxx.xxx.xxx
Received disconnect from xxx.xxx.xxx.xxx: 2: Too many authentication failures for username
が出てログイン出来ないとき。

$ ssh username@xxx.xxx.xxx.xxx -o PreferredAuthentications=password
とやればとりあえずログイン出来る、と思います。
※パスワードログインする場合

このエラーは、サーバ側のsshd_configにある
MaxAuthTries 6
の回数を超えてしまったために出るエラーです。
なので、サーバ側でこの値を増やしてsshd再起動すれば解決しますが、
無闇に増やすのはセキュリティ上多少心配です。

sshの公開鍵認証を設定していると、
数種類のサーバ向けに秘密鍵を用意する事が多いと思いますが、
そういう場合、sshが順番に鍵を使って認証していき(もちろんパスワード認証も)
その結果MaxAuthTriesを超えてしまう、
という事があるようです。
なので不要な秘密鍵を消すために、

$ ssh-add -D
を行ってから接続するのも別の解決策です。

どういう認証手順を踏んでるか確認するには、
$ ssh username@xxx.xxx.xxx.xxx -vvv
と 打てば詳細なログを出力できます。



以上でぇぇぇぇぇす。

2014年5月2日金曜日

Linuxでユーザをグループに追加する

どうも、俺@腹減ったです。

Linuxを作成したユーザを別のグループに追加したいとき。

$ id koexuka
uid=500(koexuka) gid=500(koexuka) groups=500(koexuka)
今はkoexukaユーザはgid=500のkoexukaグループに属している状態です。
追加してwheelグループに追加しちゃいましょう。

# gpasswd -a koexuka wheel
$ id koexuka
uid=500(koexuka) gid=500(koexuka) groups=500(koexuka),10(wheel)
見事wheelグループに追加されました。
では、やっぱwheelグループから削除したいとき、

# gpasswd -d koexuka wheel
$ id koexuka
uid=500(koexuka) gid=500(koexuka) groups=500(koexuka)
はい、見事にwheelグループから脱却できました。

ちなみにusermodコマンドでもグループ追加できます。
同じようにkoexukaユーザをwheelグループに追加したいときは、
# usermod -G wheel koexuka
$ id koexuka
uid=500(koexuka) gid=500(koexuka) groups=500(koexuka),10(wheel)
のように出来ます、が!

usermodコマンドでグループに追加すると、
すでに他のグループが設定されていた場合は危険です。
$ id koexuka
uid=500(koexuka) gid=500(koexuka) groups=500(koexuka),10(wheel)
// ↑↑グループはkoexukaとwheel

# usermod -G hogegroup koexuka
$ id koexuka
uid=500(koexuka) gid=500(koexuka) groups=500(koexuka),502(hogegroup)

// ↑↑設定されていたwheelが消える!!
上記のようにコマンドを叩くと、すでに設定されたグループが削除されてしまいます。
なので、
# usermod -G hogegroup, wheel koexuka
$ id koexuka
uid=500(koexuka) gid=500(koexuka) groups=500(koexuka),502(hogegroup),10(wheel)
のように、属するグループを,(カンマ)ですべて指定しなければいけません。

面倒なので、つまりgpasswdコマンドを使いましょう!
という結論。


以上でぇぇえぇぇぇす。