サイトトップ

Director Flash 書籍 業務内容 プロフィール

Optimizing Performance of ActionScript 3.0

Chapter 01 文法の基本から

□01-03 数値は小数か整数かマイナスを含むのかを区別する

01-01「変数と関数にはデータ型を指定する」に述べたとおり、データ型は正しく定めることが大切です。とくに数値には、Numberとintおよびuintの3つのデータ型があります。データの中身をよく考えて、できるだけ厳格に決めましょう。一般に、小数値を含むNumber型よりも、整数型(intまたはuint)の方が処理は最適化されます。数値のデータ型を定めるには、まず初期値から始めて、その後の演算や代入の処理を考えたうえで、値の範囲に問題がないかどうか確かめます。

    【数値のデータ型を定めるには】
  1. 初期値を決める
  2. 演算や代入の処理を考える
  3. 値の範囲を確かめる

01-03-01 初期値を決める
まず、初期値が基本となります。プロパティやメソッドの戻り値を代入するときは、リファレンスでそのデータ型を確かめましょう。たとえば、MovieClipインスタンスの座標(DisplayObject.xDisplayObject.y)や幅・高さ(DisplayObject.widthDisplayObject.height)はNumber型です。それに対して、ステージの幅と高さ(Stage.stageWidthStage.stageHeight)はint型とされます。また、配列の長さ(Array.length)はuint型です。

Tips 01-03-001■データ型はコードヒントでも確かめられる
プロパティやメソッドの戻り値は、リファレンス以外にコードヒントでもデータ型が確かめられます(図01-03-001)。

図01-03-001■コードヒントにデータ型が示される

Stage.stageWidthプロパティのデータ型はintであることがわかる。

初期値を設定しなければ、指定したデータ型のデフォルト値として扱われます(表01-03-001)。Number型はNaN、整数型(intとuint)は0が初期値です。とくにNaNは、どのような演算を行っても結果はNaNにしかなりません。Number型はできるだけ初期値を与えるか、速やかに最初の値が代入されるようにしておくと安心です。

表01-03-001■数値のデータ型とデフォルト値および仕様
データ型 デフォルト値 説明
int 0 -2,147,483,648(=-231)以上2,147,483,647(=231-1)以下の整数値。32ビット符号付き整数と呼ばれます。
uint 0 0以上4,294,967,295(=232- 1)以下の整数値。32ビット符号なし整数と呼ばれます。
Number NaN 整数および小数値。64ビット浮動小数点数と呼ばれます。

[*筆者用参考]「スクリプトによるアニメーション」Tips 02-015「数値のデータ型


01-03-02 演算や代入の処理を考える
初期値を決めたら、その後の演算や代入の処理を考えます。初期値が整数であっても、割り算や小数を伴う計算があるときは、整数型は使えません。Number型を指定する必要があります。

たとえば、以下のフレームアクション(スクリプト01-03-001)をMovieClipシンボルに書くと、インスタンスはイーズアウトつまり減速しながらマウスポインタの水平方向の動きに追随します。しかし、減速するときの動きが滑らかになりません。問題は、変数(nMoveX)をint型で指定していることです(第3行目)。

変数に代入する右辺は、マウスポインタのx座標(DisplayObject.mouseX)値を減速率の値で割り算しています。ところが、変数がint型のために小数点以下の端数が切捨てられてしまいます。そのため、とくに減速したとき、1ピクセル単位の動きになって、滑らかにならないのです(図01-03-002)。

スクリプト01-03-001【×】小数値を整数型変数に入れると切捨てられる
    // フレームアクション: 動かすMovieClipシンボル
  1. addEventListener(Event.ENTER_FRAME, xMove);
  2. function xMove (eventObject:Event):void {
  3.   var nMoveX:int = mouseX / 5;
  4.   x += nMoveX;
  5. }

図01-03-002■イーズアウトの減速が滑らかに動かない

int型は小数を丸めるので、減速が1ピクセル単位の動きになってしまう。

滑らかに減速させるためには、値を小数で扱わないといけません。つまり、変数(nMoveX)はNumber型で指定する必要があるのです(スクリプト01-03-002第3行目)。

スクリプト01-03-002【○】小数値を入れる変数にはNumber型で指定する
    // フレームアクション: 動かすMovieClipシンボル
  1. addEventListener(Event.ENTER_FRAME, xMove);
  2. function xMove (eventObject:Event):void {
  3.   var nMoveX:Number = mouseX / 5;
  4.   x += nMoveX;
  5. }

Tips 01-03-002■数値型同士の暗黙の型変換
数値型の値を別の数値型の変数に代入すると、とくにエラーも起こらず、暗黙的に型変換されます。整数型の数値をNumber型の変数に入れることは、もちろん問題ありません。さらに、前掲スクリプト01-03-001で見たとおり、整数型の変数にNumber型の数値を納めることもできます。ただし、小数点以下の端数が切捨てられます。なお、次項01-03-03「値の範囲を確かめる」で説明するように、データ型の範囲を超えた数値が入ると、予期しない値になることは注意が必要です。

整数の初期値に整数の加減算を行う場合には、整数型を指定すると処理が最適化されます。ループ処理で用いるカウンタ変数は、この条件に当てはまることが多いでしょう。もちろん、型指定をしないのは論外です。処理が遅くなります。

スクリプト01-03-003【×】変数に型指定をしないのは論外
  1. for (var i = 0; i < 10; i++) {
  2.   // 処理内容
  3. }

カウンタ変数をNumber型で指定した場合、処理は正しく行われます。しかし、変数値がつねに整数であるなら、最適化のためには望ましくありません。

スクリプト01-03-004【△】値が必ず整数と決まっている変数にNumber型は望ましくない
  1. for (var i:Number = 0; i < 10; i++) {
  2.   // 処理内容
  3. }

カウンタの値が整数なら、変数を整数型で指定します。しかも、数値が負にならない場合は、uint型を指定するとより最適化がはかられます。

スクリプト01-03-005【○】値が0以上の整数となるカウンタ変数にはuint型を指定する
  1. for (var i:uint = 0; i < 10; i++) {
  2.   // 処理内容
  3. }

[*筆者用参考]

Comparison of counter variable's data type in for loop - wonderfl build flash online


Tips 01-03-003■できるだけ厳格なデータ型を定める
小数値を扱うNumber型より、整数型の方がデータの制約は厳しくなります。しかし、その分Flash Playerの内部的に、最適化の余地が大きいといえます。

もっとも、処理の速さは、環境つまりオペレーティングシステムやFlash Playerのバージョン、ブラウザなどによって変わります。環境によっては差が出なかったり、結果が逆転することもありえます。

たとえば、Flash Player 9では、uint型の処理がNumber型よりも遅いことがありました(Grant Skinner「Quick As A Flash: Optimization Strategies for AS3 and Flash」「player 9」<http://www.gskinner.com/talks/quick/#8>参照)。しかし、Flash Player 10で改善されています。ですから、データ型はできるだけ厳格に指定する、ということを基本に考えてよいでしょう。


01-03-03 値の範囲を確かめる
前掲表01-03-001「数値のデータ型とデフォルト値および仕様」のとおり、とくに整数型は値の範囲が決まっています(Number型は、単純に最大値と最小値だけで説明できません。[ヘルプ]の[ActionScript 3.0の学習]<http://help.adobe.com/ja_JP/as3/learn/>/[ActionScript言語とシンタックス]/[データ型]/[データ型の記述]参照「Numberデータ型」をご参照ください)。

まず、int型の最大値と最小値は、定数int.MAX_VALUE(2147483647)とint.MIN_VALUE(-2147483648)の値です。整数の加減算で扱う分には、多くの場合十分な大きさといえます。しかし、16進数のカラー値や累乗の計算をすると、うっかり範囲を超えがちです。RGBカラー値ならint型に収まります。

スクリプト01-03-006【○】RGBカラー値はint型の整数の範囲内に納まる
  1. var n:int = 0xFFFFFF;
  2. trace(n);   // 出力: 16777215

しかし、アルファを含むARGBカラー値はint型の範囲では扱えません。範囲を超えてもとくにエラーは起こらず、予期しない数値になります。そもそもカラーなら、マイナスの値をとりませんので、uint型にすべきでしょう。なお、RGBカラー値の計算については、後述Column「2進数や16進数の計算あるいはRGBカラーの演算」をご参照ください。

スクリプト01-03-007【×】ARGBカラー値はint型の整数の範囲を超えることがある
  1. var n:int = 0xFFFFFFFF;
  2. trace(n);   // 出力: -1

スクリプト01-03-008【○】uint型ならARGBカラー値の整数が範囲内に納まる
  1. var n:uint = 0xFFFFFFFF;
  2. trace(n);   // 出力: 4294967295

uint型は正の整数で、定数uint.MIN_VALUEの0からuint.MAX_VALUE(4294967295)までの値をとります。この最大値はARGBカラーの0xFFFFFFFFに等しいです。したがって、この数値に1足しただけで、定められた範囲を超えます。そのような場合には、変数をNumber型で指定しなければなりません。

スクリプト01-03-009【×】ARGBカラーの最大値はuint型の最大値に等しい
  1. var n:uint = 0xFFFFFFFF + 1;
  2. trace(n);   // 出力: 0

スクリプト01-03-010【○】uint型の範囲を超える数値には整数でもNumber型を指定する
  1. var n:Number = 0xFFFFFFFF + 1;
  2. trace(n);   // 出力: 4294967296

値の範囲が予めはっきりとわからないときには、最適化で劣っても予期せぬ数値になることを避けるため、Number型で指定すべき場合もあるでしょう。

[*筆者用参考] 馬鹿全「(AS3)ビット演算を倒す


作成者: 野中文雄
更新日: 2011年1月23日 スクリプトに連番と行番号を追加。
更新日: 2011年1月15日 例のタイトルを具体化。
更新日: 2010年12月28日 スクリプト冒頭に記述場所とインスタンスについてのコメントを追加。
作成日: 2010年12月24日


Copyright © 2001-2011 Fumio Nonaka.  All rights reserved.