2011年8月3日水曜日

[Glaeja] The Case of the Cottingley

…というわけで、『Galeja』の[イメージ]レイヤーおよび[スプライト]レイヤーのチュートリアルです。


・はじめに

チュートリアルの前に、Android における画素の取り扱いとその単位について、簡単にまとめておきます。

画像の大きさを扱う単位で、最も基本的なものは「画素単位(ピクセル、単位は px.)」で、これは Android でも同じです。この単位は言うまでもありませんが、表示デバイス(LCD、EL等)の1画素を単位とするもので、いわゆる「ドット」というものです。この単位を用いると、画像の大きさを「何画素分」という形で表現することになります。

世の中には、様々な大きさの表示デバイスがあり、またその画素数も色々あります。同じ大きさのデバイスでも、その画素数が異なるものがあり、それは画素の大きさが異なることによるわけです。
この「画素の大きさ」をマイクロメートル等の実サイズで表しても、いまいちピンときませんw そこで、「デバイス上の1インチ内に収まる画素数」という「ピクセル密度(dots per inch、単位は dpi.)」という単位を用いることが多いです。
同じ1インチの線を引くのに、160 dpi. のデバイスでは160画素、240 dpi. のデバイスでは240画素が必要となります。

これは逆に考えると、「160 px.」の長さを持つ線は、160 dpi. のデバイス上では1インチで表示され、240 dpi. のデバイス上では、2/3インチで表示される、ということになります。このことは、“同じ画像は、どんなデバイス上でも同じように表示したい”という立場からするとあまり都合よくありません。

そこで、「密度非依存ピクセル(density independent pixels、単位は dp.)」という単位が導入されました。これは、「デバイス上で 1/160インチとなる大きさ」が 1 dp. となる仮想的な単位です。「160 dp.」の長さを持つ線は、160 dpi. のデバイスだろうが240 dpi. のデバイスだろうが、全て1インチで表示されます。

この「dp.」という単位は、「画面の見た目を揃える」という点では使い勝手のよい単位なんですが、やはり欠点はあります。それは「デバイスサイズによっては画像が拡大縮小されるのでジャギーになる」という点です。
例えば、「160 px. ×160 px.」の画像ファイルがあり、これをデバイス上で1インチ角となるよう表示する場合、160 dpi. のデバイスなら「1dp. = 1 px.」なのでドット・バイ・ドットで表示されます。しかし、240 dpi. のデバイスでは、「1dp. = 1.5 px.(1インチ = 160 dp. = 240 px.)」なので、画像を1.5倍拡大しなければならず、ジャギーが発生して美しくありません。

特に Android のウィジェット(AppWidget)は、その配置サイズが「72 dp., 146 dp., 220 dp., 294 dp.」と dp. 単位で規定されているので、異なるデバイスサイズの端末で同じ(ピクセル数の)画像ファイルを表示させると、大きさを揃えるために拡大・縮小させざるを得ません。
ですので、ウィジェットに画像ファイルをキレイに(ドット・バイ・ドットで)表示させたい場合には、デバイスのピクセル密度に応じてピクセル数を変えた画像ファイルを用意しなければならない、ということになります。

拙作『DigitalClockDesigner』『Battery Designer』および『Glaeja』では、ウィジェットサイズが1マス[横 80 dp.×縦 100 dp.]で、日本国内の多くの端末が[240 dpi.]のピクセル密度なので、大体[横 120 px.×縦150 px.]を基本に画像ファイルを作っておけばイイんじゃないでしょうか。


・[イメージ ]レイヤーと[スプライト ]レイヤーの表示位置の違い

イメージ]レイヤーでは“ウィジェット内の指定した位置に、画像ファイルの左上がくるように表示”され、[スプライト]レイヤーでは“画像ファイルの中心が、ウィジェット内の指定した位置にくるよう表示”されます(下図参照)。



・アナログ時計を作ってみよう

やっとチュートリアルですw 以前の[ハンド]レイヤーでも作りましたが、[スプライト]レイヤーの回転を利用してここでもアナログ時計を作ってみます。

1.文字盤画像を用意し、[イメージ]レイヤーで表示させます。

ここでは、240 dpi. のデバイスを持つ端末に、2×2のウィジェットを表示させるという想定で画像を作りました。

アンカーポイントを調整し、ウィジェットの真ん中に表示されるようします。











2.[スプライト]レイヤーを新規追加し、用意した長針画像ファイルを設定します。
用意する画像ファイルは、画像の中心が針の回転中心となるよう、右のようなサイズで作る必要があります。

針が正しい位置に表示されるよう、中心位置(水平)・(垂直)を設定します。
このとき、中心位置は固定なので、[現在値となる項目]をゼロにした上で、[開始位置]を調整することで、表示位置を調整します。

時計分針として機能させるため、[角度]を
・[開始角度]: 0
 ・[終了角度]: 360
 ・[現在値となる項目]: $m$
 ・[最大値となる項目]: 60
に設定します。


3.上記[スプライト]レイヤーを複製して追加し、画像ファイルを短針用のものに差し替えます。

そして、時計時針として機能させるため、[角度]を
・[開始角度]: 0
 ・[終了角度]: 360
 ・[現在値となる項目]: $i$
 ・[最大値となる項目]: 720
に設定します。

情報偽装ダイアログで時刻を色々イジり、針がズレてないか確認してください。。







4.お好みで[シャドウ]とかつけたら完成です。

使った画像ファイルをZIPにまとめてココに置いておきます。

















・ドロイド君のバッテリー残量ゲージを作ってみよう

時計ばっか作っててもツマンナイので、バッテリー残量計も作ってみましょう(これも作り飽きましたがw)。

1.ゲージ部分となる画像ファイルを用意し、[イメージ]レイヤーで配置します。ここでは4×1を使いました。

画像ファイルの数字は、各桁(00、10、…、90、99)の真ん中が等間隔になるようカーニングが調整してあります。







2.ドロイド君の画像ファイルを用意し、これを[スプライト]レイヤーで表示します。

中心位置(水平)]の[開始位置][終了位置]を、[現在値となる項目]がゼロおよび100のときに、ドロイド君が該当する数値の真上にくるよう調整します。

中心位置(垂直)]を調整し、ドロイド君が数値の上に乗るようにします。










3.[中心位置(水平)]の[現在値となる項目]を”#P#”にして、バッテリー残量%に連動するようにします。偽装ダイアログでバッテリー残量を変えながら、表示位置を確認してください。


これで完成、、、ではツマンナイのでもうちょっとイジってみましょう。




4.歩いているドロイド君の画像を作り、下のようにファイル名をつけます。









5.[スプライト]レイヤーの[画像ファイル]を、
  • ファイル名のマッチ]: ファイル名の最も似たものを表示
  • パターン文字列]: droid_#PPP#@1/2/@
と設定します。

このパターン文字列は、「"droid_"の後ろに、バッテリー残量%を3桁の数値で表し、その後ろ1文字目から2文字を削除したものを追加」という意味で、
  • バッテリー残量 2% ⇒ droid_002 ⇒ droid_2
  • バッテリー残量 12% ⇒ droid_012 ⇒ droid_2
  • バッテリー残量 25% ⇒ droid_025 ⇒ droid_5
という風に補完されます。

これでドロイド君がバッテリー残量%に応じて歩くことができました。

コマ割りが悪いんで、ギクシャクですがw























6.これで完成、と思ったんですが、これだと放電中はドロイド君がバックステッポwになってしまいますね…
というわけで、ドロイド君の画像ファイルに逆向きのものを追加して、以下のようなファイル名をつけます。











バッテリー残量が増える方向へ向かうドロイド君には“_charging_”を、減る方向へ向かうドロイド君には”_discharging_”をつけておくわけです。また、満充電時用に”_full_0”をつけたファイルも用意します。

7.そして[スプライト]レイヤーの[画像ファイル]を、

・[ファイル名のマッチ]: ファイル名の最も似たものを表示
・[パターン文字列]: droid_#S#_#PPP#@1/2/\d@

と設定します。

これで左のように充放電状態に応じて歩く向きを変えることができました。

用いた画像ファイルとスキンをココに置いておきます。










とりあえずこんなとこで。

9 件のコメント:

  1. ドロイド君バッテリバー参考にさせてもらってます!
    そこで不明な点が出てきたんですが、
    #S#による表記が満充電時に「full」とならず「100」になります。
    なのでfull_0の画像も反映されません。
    100かfullかは端末依存ですかね?
    改善方法があれば教えてください。

    返信削除
    返信
    1. #S#単独の表示ではどうなるのですか?
      テキストレイヤーに「#S#」とだけ記述した状態で端末を充電器に繋ぎ、
      端末が満充電になると、なんと表示されますか?
      「100」ですか?「full」もしくは「満充電」ですか?それとも何も表示されませんか?

      「100」なら、満充電時の画像ファイル名を「droid_100_0.png」に改名すれば良いかと思います。
      また何も表示されないのなら、同様に「droid__0.png」にすれば良いかと思います。
      そこらへんは臨機応変にお願いします。

      「100かfullか」が端末依存かどうかは私には分かりません。
      もしかしたら「充電池を満充電にすると寿命が縮まる」ということで、
      満充電ギリギリのところで充電回路を切るようなことが行なわれてるのかも知れません。
      そうした場合、残量は(ほぼ)100%でも満充電とはならないかも知れませんね。
      よろしければ後学のため端末名をお教え願えませんか?

      削除
  2. すいません勘違いしてました!
    「100」は「#S#」ではなく「#P#」の表記ですね。
    「full」とならず「100」になるではなく、「full」とならず「discharging」「charging」になります。

    「#S# #P#%」が「full 100%」ではなく「(dis)charging 100%」になります。
    なので、バッテリーバーの画像も右向きか左向きしか表示されず、満充電時に個別の画像が表示されません。

    端末はドコモGalaxy S2です。ICSです。

    返信削除
    返信
    1. この部分は、現在のバッテリー状態を取得して、
      そのstatusがBatteryManager.BATTERY_STATUS_FULLだったら
      言語が英語なら"full"、日本語なら"満充電"と表示するだけです。

      > ドコモGalaxy S2

      100%になってもこのステータスを返さないってのは
      ちょっとお行儀の悪い端末ですねw


      で、現状打開の方法ですが、、、

      (1)諦める

      (2)「#S#」に頼らないで「#P#」が100なら"full"と表示させるような@@を書く

      のどちらかですね。
      (2)は、「#S#」の代わりに、
      「#P#の結果と100を比較して、同じなら"full"、
       そうでないなら#S#を表示」させるような@...@を書いてやればいいかと思います。

      削除
  3. この記事のドイロイド君バッテリーについてなんですが、数字の部分はどうやればいいんでしょうか?
    特に鏡文字のやり方がわかりません
    ミラーを使っても反映されなくて困っています…

    返信削除
    返信
    1. よく読めば書いてありますが、あの数字は「イメージ」レイヤーに表示させた画像ファイルです。画像編集ソフトで反射も含めて作成したものです。

      削除
  4. 申し訳ないです。なんとか3まではできたのですが5からができません・・・

    こちらのZIPからDLし名前も確認したのですが、なぜかdroid_#PPP#@1/2/@を入力すると先のバッテリーの数字の方が表示されてしまいます。
    図としては同じものが二段重ねになっている様子です。
    ファイル情報化から確認しましたが自分じゃどうも解決できません。
    なにが原因かわかりますか?

    返信削除
    返信
    1. 原因以前にどういう現象が起こっているのかがわかりません。

      削除
    2. あ、、、
      えーっと、あのDLできるスキンは作例の6・7で使う画像しか入ってません。
      5で使う画像(droid_0.pngとか)は含まれていません。

      削除