DisplayObject.rotationプロパティは、インスタンスの角度を±180度の範囲の値で示します。そして、この範囲を超える数値を与えても、範囲内の角度に換算されて設定されます。このプロパティ値のように、決まった範囲内で値を循環させる計算について考えます。お題としては、やはりわかりやすいので角度を採上げます[*1]。
|
[*1] 3次元空間におけるxyz各軸ごとにの角度を示すプロパティDisplayObject.rotationX/DisplayObject.rotationY/DisplayObject.rotationZも、値の範囲は±180とされます。しかし、DisplayObject.rotationプロパティとは異なり、範囲外の数値も設定できてしまいます。予期しない結果を招かないためには、予め設定値を決まった範囲に収めておくのが安心です。
|
01 角度を0から360度の範囲に換算する
まずは、任意の角度を0以上360未満の範囲に換算してみます。数値を0以上にかぎれば、剰余演算子%を使って簡単に計算できます。
数値 % 360
数値がマイナスのときは、剰余に360を加えなければなりません。そうすると、逆に正の場合に値が360以上になってしまいます。それだけでなく、負でも余りが0(たとえば-360)のとき360とされます。この問題を避けるには、改めて360の剰余をとればよいでしょう(表001)。計算の対象となる数値が変数nAngleに収められているとすれば、つぎのとおりです。
|
(nAngle % 360 + 360) % 360
|
表001■剰余の式と計算結果
| 式 |
数値 |
|
-360
|
-90
|
0
|
90
|
360
|
|
数値 % 360
|
0
|
-90
|
0
|
90
|
0
|
|
数値 % 360 + 360
|
360
|
270
|
360
|
450
|
360
|
|
(数値 % 360 + 360) % 360
|
0
|
270
|
0
|
90
|
0
|
正負に拘らずひとつの式で答えを導けることは、パズルの解き方としては優れています。しかし、正数であれば剰余は1回求めれば済むことを考えると、計算には無駄があります。正負を分けた方が、扱いは速められるでしょう。
|
nAngle %= 360;
if (nAngle < 0) {
nAngle += 360;
}
|
360の剰余がマイナスのときのみ360を加えることとしました。これで、要らぬ計算が省けます。
02 角度を±180度の範囲に換算する
つぎは、角度を±180の範囲に換算します。値の幅は360ですので、その剰余をとるという考え方は変わりません。違ってくるのは、下限値が0でなく-180になることです。そこで、一旦180加えて、下限値を0にします。そして、前項と同じように換算した角度を求めたうえで、最後に改めて180を差引きます。これで、±180の範囲を循環する角度が導けます。
前項のスクリプトでは360の剰余をとった後、角度がマイナスのとき360を加えました。そのうえで180差引くなら、合算で180加えればよいことになります。したがって、つぎのスクリプトは、剰余後の正負を分けて計算しています。
|
nAngle += 180;
nAngle %= 360;
if (nAngle < 0) {
nAngle += 180;
} else {
nAngle -= 180;
}
|
頭から数値の正負それぞれについての式を立て、条件演算子?:により振分けると、もう少し最適化できます[*2]。つぎのスクリプトはラジアン値の±πなどにも応用しやすいように、定数をconst宣言しました。
const FULL:Number = 360;
const HALF:Number = FULL / 2;
| nAngle |
= (nAngle < 0)
? (nAngle - HALF) % FULL + HALF
: (nAngle + HALF) % FULL - HALF; |
|
循環する数値の計算の仕方は、ほかにもいろいろあるでしょう[*3]。
|
[*2] ただし、このスクリプトは180を-180に、-180は180に変換します。これらふたつは同じ角度とみるべきです。その前に掲げたスクリプトは、どちらの角度も-180とし、180という値を返すことはありません。角度の一意性という点からは、こちらの方が優れています。なお、DisplayObject.rotationプロパティには、ふたつの数値がそのまま設定されますので、角度の一意性について同じ問題があります。
[*3] 本文に紹介したスクリプトも含め、いくつかの計算方法をwonderflで比べてみました。
Restricting range of circulating value - wonderfl build flash online
なお、「radian角度をπ範囲に丸める方法まとめ」も参考になるでしょう。
|
作成者: 野中文雄
作成日: 2011年5月29日