「SWF4 rotation の不思議仕様・精度落ち対策」の編集履歴(バックアップ)一覧はこちら
「SWF4 rotation の不思議仕様・精度落ち対策」(2011/09/09 (金) 07:43:46) の最新版変更点
追加された行は緑色になります。
削除された行は赤色になります。
携帯待ち受けなどに使われるSWF4環境の rotation まわりには、わりと残念な仕様が多いようで、私が確認した現象とその対策をメモしておきます。
-【現象1】アナログ時計の針を回転させたら、どんどん縮んでいく。
-【現象2】細かな位置・角度変更を続けると動きがガタつく、位置がズレる、縮んで消えるなどする。
結局は「スプライトは座標の記録や計算の精度が低く、誤差が累積しやすいので出来るだけ慎重に動かす」という事なのですが…。
***【現象1】アナログ時計の針を回転させたら、どんどん縮んでいく
#divclass(marginleft16){
発生環境:Flash4
----
ありそうな話ですが、これは以下にオフィシャルなアナウンスがありました。
[[Adobe Macromedia - Director TechNote // FlashのムービークリップをsetFlashPropertyで回転させたら縮小してしまう>>http://www.adobe.com/jp/support/director/ts/documents/dr0221.html]]
どうも仕様のようです。説明によると、要点としては
-小数点で角度を設定すると縮小が起こる
-整数で角度を設定しても、実際の座標計算では小数点レベルの誤差を生じる(ただし、45度の倍数だけは正確)
だそうです。
【対策】
アナウンス通りに、こうしましょう。
-原則として、角度は整数値で設定
-角度を変更したら、scaleX, scaleY を 100 に設定
アナウンスにも記述されていますが、rotation に設定した値が、正確に反映される保証がありません。不具合あるような時は rotation の値を読み込んで処理を分岐するようなことはせず、自前で設定を変数に保存しておき、設定したつもりの値を基準にしてコードを書くべきです。
【個人的推察】
どのレベルの精度問題かはわかりかねますが、もともとのリソースの水平状態からサンプリングして画面に出力…ではないのかな?という気がします。今の角度と次の角度との差分をとって、現在の画素に対して回転をかけていくような設計なら、計算を繰り返すたびになんらかの精度落ちが誤差として累積していく可能性が高いと言えます。なんかそのテのエラーっぽく見えます。
}
***【現象2】細かな位置・角度変更を続けるとスプライトの動きがガタつく、位置がズレる、縮んで消えるなどする(※環境依存)
#divclass(marginleft16){
発生環境:iモードシミュレーターII、W63CA(au機)
未発生環境:ParaFla!プレビュー、W41SH(au機)
----
【現象1】と似たような感じですが、発生が環境依存で少し複雑です。小さなスプライトに対し、細かく位置・角度変更を繰り返し続けると、動きがガタつく、位置がどんどんズレていく、縮んで消える、という現象が発生しました。時計の針が逆回転までしてしまうのです。
スプライトの特徴としては、「ドットサイズが非常に小さく、基準点もゼロとかではなく、スプライト中に配置している画像のサイズはさらに小さい」。
|スプライトの大きさ|3x28|小さくて細長い|
|スプライトの基準点|1x27|基準点がスプライトの外側。端の方。|
|イメージの配置/サイズ|0,0 / 3x17|スプライトサイズからすると中途半端な大きさ|
起こったコードは【現象1】の対策済です。
-スプライトの位置や角度は整数値を設定
-スプライトの位置や角度は設定した値を記録し、変更の必要がある(新たな設定値が1以上違う)場合のみ書き換える
-スプライトの位置や角度を変更した場合には、scaleX, scaleY を再設定する
デバッグ出力しても、スプライト自体のプロパティ状態は良好です。スプライトのプロパティは正しいのに表示が乱れていることになります。
【推察1】
スプライトのプロパティが正しく設定できていて、【現象1】という前例も踏まえます。変形計算を行うたびスプライト内イメージの「位置情報」にも誤差が累積している可能性が高いと思います。変形の基準点も端っことかではなくスプライトの外側ですし。内部のイメージを描画するのにも、スプライトの端から座標のオフセットを計算し、その部分にも誤差が累積する環境があるのかもしれません。
【検証1・ならばそもそもオフセットがなければ良い】
イメージの座標計算に誤差が乗るなら、スプライト座標と±0、つまりピッタリサイズのスプライトにすればどうかな、というのを試してみました。
-スプライトのサイズを変更し、イメージぴったりのサイズに変更する。
|スプライトの大きさ|3x17|→ イメージのサイズに合わせた|
|スプライトの基準点|1x27||
|イメージの配置/サイズ|0,0 / 3x17||
完璧ではありませんが、それなりに効果がありました。最初の状態だと rotation とは逆方向に回転するなど相当酷かったのですが、指定した範囲にある程度落ち着いてくれます。それでも50~100回程度も再計算すればある程度の誤差が出ました。一定範囲の角度でアニメーションさせているはずが、最低角と最高角で位置が毎回微妙にズレていきます。完全にズレる前に自己復元して正常な範囲に戻るのですが、そのうちまた多少のズレを生じ始めます。結局、バグ状態に変わりはありませんでした。
しかし、とりあえずの方針として、わずかな誤差が相対的に大きくなってくる小さなイメージの描画には、とにかくジャストサイズのスプライトを使う方が無難だと思いました。スプライトの組み方には多少の制限となりますが、【現象1】の対策だけでそこそこフォローできます。
【検証2・完全に成功した対策】
-固定画面スプライトをそのまま描画しないで、定期的に duplicateClip()&removeClip() する。
最終手段です。もし、【現象2・検証1の対策】でも微妙にずれることが確認されたら、強引な手段ですが、スプライトの削除と生成をはさんでクリアすれば良いと思います。
スプライト内イメージの位置情報は AS からは操作できない部分です。誤差が累積しても修正できません。
そこでオリジナルの健全な状態のスプライトを別に安置しておきます。で、見せるスプライトはduplicateClip()によるコピーとします。で、時々破棄して再生成してやるのです。もちろん携帯での頻繁な再生成はそれなりに処理負担&電池消耗があると思いますので、現象が出たらパフォーマンスを多少犠牲にしつつ、程度を見ながら後付けで対処していくのがセオリーのような気がします。
}
----
----
携帯待ち受けなどに使われるSWF4環境の rotation まわりには、わりと残念な仕様が多いようで、私が確認した現象とその対策をメモしておきます。
-【現象1】アナログ時計の針を回転させたら、どんどん縮んでいく。
-【現象2】細かな位置・角度変更を続けると動きがガタつく、位置がズレる、縮んで消えるなどする。
結局は「スプライトは座標の記録や計算の精度が低く、誤差が累積しやすいので出来るだけ慎重に動かす」という事なのですが…。
***【現象1】アナログ時計の針を回転させたら、どんどん縮んでいく
#divclass(marginleft16){
発生環境:Flash4
----
ありそうな話ですが、これは以下にオフィシャルなアナウンスがありました。
[[Adobe Macromedia - Director TechNote // FlashのムービークリップをsetFlashPropertyで回転させたら縮小してしまう>>http://www.adobe.com/jp/support/director/ts/documents/dr0221.html]]
どうも仕様のようです。説明によると、要点としては
-小数点で角度を設定すると縮小が起こる
-整数で角度を設定しても、実際の座標計算では小数点レベルの誤差を生じる(ただし、45度の倍数だけは正確)
だそうです。
【対策】
アナウンス通りに、こうしましょう。
-原則として、角度は整数値で設定
-角度を変更したら、scaleX, scaleY を 100 に設定
アナウンスにも記述されていますが、rotation に設定した値が、正確に反映される保証がありません。不具合あるような時は rotation の値を読み込んで処理を分岐するようなことはせず、自前で設定を変数に保存しておき、設定したつもりの値を基準にしてコードを書くべきです。
【個人的推察】
どのレベルの精度問題かはわかりかねますが、もともとのリソースの水平状態からサンプリングして画面に出力…ではないのかな?という気がします。今の角度と次の角度との差分をとって、現在の画素に対して回転をかけていくような設計なら、計算を繰り返すたびになんらかの精度落ちが誤差として累積していく可能性が高いと言えます。なんかそのテのエラーっぽく見えます。
}
***【現象2】細かな位置・角度変更を続けるとスプライトの動きがガタつく、位置がズレる、縮んで消えるなどする(※環境依存)
#divclass(marginleft16){
発生環境:iモードシミュレーターII、W63CA(au機)
未発生環境:ParaFla!プレビュー、W41SH(au機)
----
【現象1】と似たような感じですが、発生が環境依存で少し複雑です。小さなスプライトに対し、細かく位置・角度変更を繰り返し続けると、動きがガタつく、位置がどんどんズレていく、縮んで消える、という現象が発生しました。時計の針が逆回転までしてしまうのです。
スプライトの特徴としては、「ドットサイズが非常に小さく、基準点もゼロとかではなく、スプライト中に配置している画像のサイズはさらに小さい」。
|スプライトの大きさ|3x28|小さくて細長い|
|スプライトの基準点|1x27|基準点がスプライトの外側。端の方。|
|イメージの配置/サイズ|0,0 / 3x17|スプライトサイズからすると中途半端な大きさ|
起こったコードは【現象1】の対策済です。
-スプライトの位置や角度は整数値を設定
-スプライトの位置や角度は設定した値を記録し、変更の必要がある(新たな設定値が1以上違う)場合のみ書き換える
-スプライトの位置や角度を変更した場合には、scaleX, scaleY を再設定する
デバッグ出力しても、スプライト自体のプロパティ状態は良好です。スプライトのプロパティは正しいのに表示が乱れていることになります。
【推察1】
スプライトのプロパティが正しく設定できていて、【現象1】という前例も踏まえます。変形計算を行うたびスプライト内イメージの「位置情報」にも誤差が累積している可能性が高いと思います。変形の基準点も端っことかではなくスプライトの外側ですし。内部のイメージを描画するのにも、スプライトの端から座標のオフセットを計算し、その部分にも誤差が累積する環境があるのかもしれません。
【検証1・ならばそもそもオフセットがなければ良い】
イメージの座標計算に誤差が乗るなら、スプライト座標と±0、つまりピッタリサイズのスプライトにすればどうかな、というのを試してみました。
-スプライトのサイズを変更し、イメージぴったりのサイズに変更する。
|スプライトの大きさ|3x17|→ イメージのサイズに合わせた|
|スプライトの基準点|1x27||
|イメージの配置/サイズ|0,0 / 3x17||
完璧ではありませんが、それなりに効果がありました。最初の状態だと rotation とは逆方向に回転するなど相当酷かったのですが、設定した範囲にある程度落ち着いてくれます。それでも50~100回程度も再計算すればある程度の誤差が出ました。rotationには一定の範囲を与えてアニメーションさせているはずですが、最低角と最高角で打つ位置が毎回微妙にズレていきます。完全にズレる前に自己復元して正常な範囲に戻るのですが、そのうちまた多少のズレを生じ始めます。結局、バグ状態に変わりはありませんでした。
しかし、とりあえずの方針として、わずかな誤差が相対的に大きくなってくる小さなイメージの描画には、とにかくジャストサイズのスプライトを使う方が無難だと思いました。スプライトの組み方には多少の制限となりますが、【現象1】の対策だけでそこそこフォローできます。
【検証2・完全に成功した対策】
-固定画面スプライトをそのまま描画しないで、定期的に duplicateClip()&removeClip() する。
最終手段です。もし、【現象2・検証1の対策】でも微妙にずれることが確認されたら、強引な手段ですが、スプライトの削除と生成をはさんでクリアすれば良いと思います。
スプライト内イメージの位置情報は AS からは操作できない部分です。誤差が累積しても修正できません。
そこでオリジナルの健全な状態のスプライトを別に安置しておきます。で、見せるスプライトはduplicateClip()によるコピーとします。で、時々破棄して再生成してやるのです。もちろん携帯での頻繁な再生成はそれなりに処理負担&電池消耗があると思いますので、現象が出たらパフォーマンスを多少犠牲にしつつ、程度を見ながら後付けで対処していくのがセオリーのような気がします。
}
----
----
表示オプション
横に並べて表示:
変化行の前後のみ表示: