Flashのシンボル変換時のルーチン作業をサポートするコマンド

最近はUnityを使う時間も多くなりましたが、なんだかんだで一番使う時間が多い開発ツールはFlashという状況です。

1年程前に作ったFlash IDEのコマンドが何気に便利で、もうコレなしじゃ無理!っていうくらい使いこんでいるので紹介してみようと思います。

どういうコマンドかというと、下記画像のようにシンボル「top」内にあるシンボル「top_head」、さらにその中にある「top_head_base」というようなシンボルの階層に沿ってシンボル名を付けていく作業、つまり「親シンボル名_○○」という名前を付ける作業をサポートするコマンドとなっています。

【使い方】
下記画像はシンボル「top_head」の編集画面です。
この画面でシンボルに変換したいオブジェクトを選択します。

ここからシンボルに変換するには普段なら「F8」キーを押して「シンボルに変換」を実行するところですが、今回は代わりに紹介するコマンドを実行します。
『シンボルに変換_「親シンボル名_○○」』という名前のコマンドです。
(キーボードショートカットも登録しておくと便利です。)

シンボル名を記入するダイアログが出るので、今回は「base」と記入してOKを押します。

次にシンボルの基準点を決めるダイアログが出ます。

7:左上 8:中上 9:右上
4:左中 5:中中 6:右中
1:左下 2:中下 3:右下

と表示される予定だったのが、収まり切れずに省略されています(笑)
実際は1~9まで対応しています。
テンキーの位置で見ると分かりやすいです。

数字を記入後、OKを押します。

すると下記のようにシンボル「top_head_base」が出来ました。(赤線箇所)
親シンボルがフォルダに入っている場合でも親と同じフォルダ内に作成されます。
ついでにインスタンス名にも今回命名した「base」が設定されています。(青線箇所)
便利ですね~。もう手放せないですね~。

コマンド(jsfl)のダウンロードは以下からお願いします。

シンボルに変換_「親シンボル名_○○」.jsfl

※動作確認はWindowsでのみ行っています。
※jsflの設置方法が分からない方は「flash jsfl」等で検索してみてください。

Flash・Unity・openFrameworksの計算速度比較

普段使うツールで計算速度が速いのはどれっていうのは、頭の中でなんとなく序列ができていますが、実際の数値でどれくらい差があるんだろうと思い、各ツールに似たような計算をさせて計算時間を計ってみました。

試してみたのは下記のツールです。
 ・openFrameworks(C++)
 ・Unity(C#)
 ・Unity(JavaScript)
 ・Flash(ActionScript3)
 ・Webブラウザ(JavaScript)

実行したコードは後述しますが、主には配列へのアクセスと関数の実行を1億回行ったという内容です。
一番差が出る部分と思う描画関係のコードは一切なく、あくまで配列と関数の速度ですので「へ~」くらいに思いながら参考にしていただければと思います。

実行環境は全て同じPCで統一しています。

[実行環境]
 ・OS: Windows 8.1
 ・プロセッサ: Core i7-4500U

結果は以下のようになりました。

計算時間
(ミリ秒)
ツール 言語 内容
158 openFrameworks C++ v0.8.3 exe
244 Unity C# v4.3.5 PCスタンドアローン
497 Unity JavaScript v4.3.5 PCスタンドアローン
845 Flash ActionScript3 FlashPlayer13.0 スタンドアローン
2096 Webブラウザ JavaScript Chrome v36.0

Unityって、「C#」と「JavaScript」で速度が違ったんですね。初めて知りました。

後、テストしてみて一番驚いたのはWebブラウザでのJavaScript実行の速さです。
ツールごとの順番では一番遅くなっていますが、Webブラウザ用JavaScriptだけは配列の初期設定時にlengthの指定をしていません。
FlashのActionScript3でVectorのlength指定を省略すると計算時間が5000ミリ秒になってしまったこと考えると、Webブラウザ用JavaScriptは思っていたよりかなり早かったです。
かといってWebブラウザ用JavaScriptで配列の初期設定時にlengthの指定をすると8000ミリ秒かかってしまい逆に遅くってしまったので、ケースバイケースということでお願いします。(なにが)

以下、ツール別の内容です。

openFrameworks

ofApp.h

#pragma once
#include "ofMain.h"
#define MAX_NUM 100000000

class ofApp : public ofBaseApp{

	private:
		int time1;
		int time2;
		int arr[MAX_NUM];
		int testFunc(int i);

	public:
		void setup();
		void draw();
		void keyReleased(int key);
};

ofApp.cpp

#include "ofApp.h"

void ofApp::setup(){
	time1 = 0;
	time2 = 0;
}
void ofApp::draw(){
	if(time2 != 0){
		ofDrawBitmapString(ofToString(time2), 20, 20);
	}
}
void ofApp::keyReleased(int key){
	time1 = ofGetElapsedTimeMillis();

	for(int i = 0; i < MAX_NUM; i++) {
		arr[i] = testFunc(i);
		arr[i] = arr[i] + 1;
	}
	time2 =  ofGetElapsedTimeMillis() - time1;

}
int ofApp::testFunc(int i){
	return i;
}
計算時間
(ミリ秒)
ツール ver 言語 内容
158 openFrameworks 0.8.3 C++ exe
162 openFrameworks 0.8.3 C++ Visual Studio Express 2012
ローカルWindowsデバッガー(Releaseモード)
2721 openFrameworks 0.8.3 C++ Visual Studio Express 2012
ローカルWindowsデバッガー(Debugモード)

計算時間は毎回同じ数値が出る訳ではなく、158の場合もあれば260の場合もあったりで結構誤差があるので、ざっくりで見てもらえればと思います。

Unity

C#の場合

using UnityEngine;
using System.Collections;

public class IndexC : MonoBehaviour {
	private int time1 = 0;
	private int time2 = 0;
	private const int maxNum = 100000000;
	private int[] arr = new int[maxNum];

	void Update () {
		if (Input.GetKeyUp(KeyCode.Space)){
			time1 = (int) (Time.realtimeSinceStartup*1000);

			for (int i = 0; i < maxNum; i++){
				arr[i] = testFunc(i);
				arr[i] = arr[i] + 1;
			}
			time2 = (int)(Time.realtimeSinceStartup * 1000) - time1;
		}
	}

	void OnGUI(){
		if (time2 != 0){
			GUI.Label(new Rect(0, 0, 100, 30), time2.ToString());
		}
	}

	int testFunc(int i){
		return i;
	}
}

JavaScriptの場合

#pragma strict

private var time1:int = 0;
private var time2:int = 0;
private var maxNum:int = 100000000;
private var arr:int[] = new int[maxNum];

function Update() {
    if (Input.GetKeyUp(KeyCode.Space)){
		time1 = Time.realtimeSinceStartup*1000;
		for (var i:int = 0; i < maxNum; i++){
			arr[i] = testFunc(i);
			arr[i] = arr[i] + 1;
		}
		time2 = Time.realtimeSinceStartup*1000 - time1;
    }
}

function OnGUI() {
	if (time2 != 0){
		GUI.Label(new Rect(0, 0, 100, 30), time2.ToString());
	}
}

function testFunc(i:int):int {
	return i;
}
計算時間
(ミリ秒)
ツール ver 言語 内容
244 Unity 4.3.5 C# PCスタンドアローン
260 Unity 4.3.5 C# WebPlayer
htmlをFireFox v31.0で再生
497 Unity 4.3.5 JavaScript PCスタンドアローン
531 Unity 4.3.5 JavaScript WebPlayer
htmlをFireFox v31.0で表示
1311 Unity 4.3.5 C# Gameパネル
1468 Unity 4.3.5 JavaScript Gameパネル

Flash

package myproject{
	import flash.display.MovieClip
	import flash.events.MouseEvent;
	import flash.text.TextField;

	public class Index extends MovieClip {
		public var maxNum:int = 100000000;
		public var arr:Vector. = new Vector.(maxNum, true);

		public function Index() {
			stage.addEventListener(MouseEvent.CLICK,clickHandler);
		}

		private function clickHandler(e:MouseEvent):void
		{
			var time1:Number = new Date().time;

			for (var i:int = 0; i < maxNum; i++) {
				arr[i] = testFunc(i);
				arr[i] = arr[i] + 1;
			}
			var time2:Number = new Date().time-time1;
			var tf:TextField = new TextField();
			addChild(tf);
			tf.text = String(time2);
		}

		public function testFunc(i:int):int
		{
			return i;
		}
	}
}
計算時間
(ミリ秒)
ツール ver 言語 内容
845 Flash CC2014 AS3 FlashPlayer13.0 スタンドアローン
1044 AIR 14.0 AS3 AIRランタイム デスクトップ版
4350 Flash CC2014 AS3 FlashPlayer14.0
htmlをFireFox v31.0で表示
4063 Flash CC2014 AS3 プレビュー
5060 AIR 14.0 AS3 FlashDevelop 4.6.2
AIR 14.0 テスト再生
リリースモード
27292 AIR 14.0 AS3 FlashDevelop 4.6.2
AIR 14.0 テスト再生
デバッグモード

FlashDevelopのAIR テスト再生(デバッグモード)の圧倒的な遅さが気になったのですが、原因がよく分かっていません。

Webブラウザ

<html>
<head>
<script language="Javascript" type="text/javascript">
	var maxNum = 100000000;
	var arr = [];

	function clickHandler(){
		var time1 = new Date();
		for (var i = 0; i < maxNum; i++) {
			arr[i] = testFunc(i);
			arr[i] = arr[i] + 1;
		}
		var time2 = new Date()-time1;
		document.getElementById("timePane").innerHTML=time2;
	}
	function testFunc(i){
		return i;
	}
</script>
</head>
<body>
    <a href="javascript:clickHandler();">button</a>
    <div id="timePane"></div>
</body>
</html>
計算時間
(ミリ秒)
ツール 言語 内容
2096 Webブラウザ JavaScript Chrome v36.0
2184 Webブラウザ JavaScript IE v11.0
4576 Webブラウザ JavaScript FireFox v31.0

IEが以外と早いです。

※どのブラウザでもループの回数は1億回で試すとタイムオーバーか何かで処理が止まってしまっていたので、タイムオーバーにならない5千万回で出た計算時間を2倍にしています。

制作事例: リラミックス

ポッカサッポロフード&ビバレッジさんの新商品「GREEN SHOWER」の発売に合わせて公開されたWebコンテンツ「Relamix - リラミックス」のFlash制作を5iveの下村さんにお誘いいただき、今回は下村さんと僕の2人体制でFlashパートをお手伝いさせていただきました。

動物の鳴き声などを組み合わせてリラックス環境音が作れるコンテンツです。

昼と夜でも環境音が違ったりします。

作った環境音をダウンロードすることも可能です。

サイトは↓こちらからどうぞ!

Web Site: http://www.relamix.jp/

2つの円運動の組み合せで出来る動き

2つの円運動を組み合わせるとどんな動きが出来るのかというのが気になって、シミュレーション用のFlashを作成しました。
wonderflにアップした分がこちらです。

2つの円運動 - wonderfl build flash online

中心で青いラインが回転していて、青いラインの先を中心点とした緑のラインが回転しています。
緑のラインの先の奇跡が赤いラインです。

[スライダーの解説]
 ・blue speed: 青いラインが1秒間で何周するか
 ・green speed: 緑のラインが1秒間で何周するか
 ・blue distance: 青いラインの長さ
 ・green distance: 緑のラインの長さ

このスライダーをいじくっていると、青と緑それぞれの回転スピードの比率によって出来る形に決まりがあるんだなーということが分かってきました。

以下に回転スピードの比率ごとに分けてみました。

【約1 : 1】
正確な1:1では、うずまき型にならずに同じサイズの円をずっとなぞっているだけでしたので、
うずまき型にするには 1 : 0.99 のように少し比率をずらすのがポイントでした。

【約1 : 1.5】

【約1 : 2】
円の中に、あわよくば別の円が入ろうとしている感じですね。

【約1 : 3】
円の中に2つの円が入ろうとしている感じですね。

【約1 : 4】
今度は3つ。

【約1 : 5】

【約1 : 6】

【約1 : 10】

【約1 : 30】

えんもたけなわですが今日はここまでです。

AIR Native Extension(ANE)の速度を試す

今回はANEを試してみました。

ANEとは、AIRからデバイスのネイティブコードと連携できる仕組みのことで、今回のテストではAIRから複雑な計算処理だけをネイティブコードに任せて、AIRを爆速で動かしてみます。

今回のテスト内容は↓この記事をかなり参考にさせていただきました。ありがとうございます。

Air Native Extension(ANE) 実行速度実験2 + 画像処理 » Every day is Carnival

テスト内容は、

(1) 動画を毎フレームごとに
(2) 1200×800px のBitmapDataにdrawして
(3) 緑色以外の部分だけグレースケールに変換する

というものです。

(3) の部分だけをネイティブコードにお任せします。
元の動画はこちらを使いました。

ネイティブコード(C++)で計算してみた動画です。環境はWindows7です。

FPSは 30 出ています。
これ以上BitmapDataのサイズが大きくなると、フレームレートが落ちてくるのですが、2010年に買ったノートPC(Core i7)なので、最新のデスクトップPCだともう少し大きなBitmapDataも処理できるはずです。

C++での画像変換処理のコードはこんな感じです。(参考blog記事に少し手を加えただけです。)

FREObject grayScale(
    FREContext ctx,
    void* funcData,
    uint32_t argc,
    FREObject argv[]
) {

	FREByteArray ba;
	int32_t w, h;

	FREAcquireByteArray(argv[0], &ba);
	FREGetObjectAsInt32(argv[1], &w);
	FREGetObjectAsInt32(argv[2], &h);

	uint32_t *p, *data = (uint32_t*)(ba.bytes);
	int r, g, b;

	p = data;

	for(int y = 0; y < h; ++y) {
	    for(int x = 0; x < w; ++x) {
	        r = *p >> 8 & 0xff;
	        g = *p >> 16 & 0xff;
	        b = *p >> 24 & 0xff;
			if(r>g || b>g){
				r = g = b = (r+g+b)/3;
			}
	        *p = b << 24 | g << 16 | r << 8 | 0xff;
	        p++;
	    }
	}

	FREReleaseByteArray(argv[0]);
	return FREObject();
}

そして、比較用にAS3だけで同じ画像変換処理を行ったものはこちらです。

FPSは 2 しか出ていません。
AS3には暴力的な計算処理みたいです。
AS3での画像変換処理のコードはこんな感じです。

private function grayScale(bmpData:BitmapData):void{
	bmpData.lock();
	var color:uint;
	var r:uint;
	var b:uint;
	var g:uint;
	for(var i:int = 0; i < bmpData.height; i++){
		for(var j:int = 0; j < bmpData.width; j++){
			color = bmpData.getPixel(j, i);
			r = color & 0xFF;
			g = (color>>8) & 0xFF;
			b = (color >> 16) & 0xFF;
			if(r>g || b>g){
				r = g = b = (r+g+b)/3;
			}
			bmpData.setPixel(j,i, (b<<16)|(g<<8)|r);
		}
	}
	bmpData.unlock();
}

ネイティブコードの方がかなり早いことが実感できました!
次は、openFreamworksのライブラリ等とも連携してみたいなー!

1 2 3 4

ABOUT

GAMES

サッカーピープル
スライムパズルストーリー

倉庫番ライクパズルと
冒険のゲームです
※制作中

止まるなコロッコ2
止まるなコロッコ2

止まるなコロッコの
続編です
iOS版 / Android版

止まるなコロッコ
止まるなコロッコ

石ころのコロッコが転がるように
セッティングする脱出ゲームです
iOS版 / Android版

コロッコトロッコ
コロッコトロッコ

石ころのコロッコを転がしながら
サラリーマンを会社へ運ぶゲームです
iPhone版 / Android版

TAGS

SNS

FEEDS