以前書きました、「ステージをランダム画像で埋め尽くすFLASHを作ってみる」の続編です。
ステージいっぱいにランダムで画像がペタペタ貼られるPetaクラスを元に、それらが四方八方へ飛散する動きを加えてみたいと思います。
前回のおさらい
軽くおさらいしましょう。
おおまかな流れとしてはこんな感じでした。
- スプライトを一個作る(wrapper)
- イベントリスナーで毎フレームsetMovieを呼び出すようにする
- setMovieがカウントしながらpasteを呼び出し、画像を適当にペタペタ
- カウント数が上限に達したらイベントリスナーを解除しておしまい
これの4番を「カウント数が上限に達したらイベントリスナーを解除して飛散」に作り替えます。
どうやって、どこに飛ばすか
まず、どうやって飛ばすか(移動させるか)ですが、これはもう使い慣れているTweener一択です。ちなみに、一択(いったく)は造語です。辞書には載ってません。テレビのクイズ番組による造語だとか。
そしてどこに飛ばすか。このときにまず思いついたのが、「ステージの外に領域を作ってそこのどこかの座標に飛ばす」でした。図にするとこういうイメージです。

この黄色いエリア内の座標をランダムで算出してあげようと。
次に思ったのがこれ。

「ステージより一回り大きい矩形の線上にあるどこかの座標に飛ばす」です。
そして次にこれ。

「ステージを囲むような円の線上にあるどこかの座標に飛ばす」
なんでこうやって色々考えたかというと、「できるだけシンプルな仕組みにしたい」と思ったから。どうせほっといたって自動的にぐちゃぐちゃになるのが目に見えているので、「やらなければいけないこと」を「できるだけ自分に優しくする」というのが大切だと思うわけです。
たとえば、一番目のと三番目では単純に書かなければいけないコードの行数が違うはず。コードが多かったり、条件分岐が多かったりすると、それはもう、ハマル率が上がるわけです。
「地雷があると分かっているのであれば、敢えてそっちには行かない。」これが肝要。
そういえば、昔付き合っていた女性は当時マインスイーパーが大好きでした。僕はほとんどやらずに隣で見ていたんですけどね。なぜかって?だって、なんで自らわざわざ地雷踏みに行くんですか?
・・・、いや、本当は数字が苦手なだけなんです。(暗算できない)
円周上の座標ってどうやって求めるのだろう
ということで、円周上の座標に飛ばしてあげるのが一番シンプルっぽかったのですが、どういう式を書けばいいのか。そんなんもん知る由もなく。インターネット先生に聞くことにします。
三角関数ってなんだっけ
もうね、こういう場面に遭遇するたびに、なんでちゃんと数学を学ばなかったのかと思うわけです。(倫社と現国は得意だったんだけどね)
とにかく僕には到底理解できないので、公式だけ有り難く頂戴します。半径rの円周上の座標はx,yはこうなるらしいです。
x = r × cosθ
y = r × sinθ
要は半径とcosθもしくはsinθとやらを与えてあげれば、座標が帰ってくるっちゅーわけです。もうあとはactionscriptのリファレンス通りにやればいいじゃないですか。
sin () メソッド
public static function sin(angleRadians:Number):Number
ラジアン単位で指定された角度のサイン (正弦) を計算して返します。ラジアンを計算するには、Math クラスの概要を参照してください。
sinを出すにはラジアンとやらが必要と。なんですか。ラジアン。
1ラジアンは半径と弧の長さが等しくなる角度(約57.3度)とかいう単位らしい。
もうね、ホントごめんなさい。単位です。角度の単位として認識します。
よーするに、ランダムで決めたラジアン(角度)を与えて座標を求めるっちゅーわけです。
で、僕が欲しいのは「360度の内のどこかのラジアン」なので、リファレンスの表記を参考にコードを考えます。
ラジアン値を計算するには、次の式を使用します。
radians = degrees * Math.PI/180ラジアンで角度を計算するには、次の式を使用します。
degrees = radians * 180/Math.PI
つまりこういうことですな。
ラジアン = ランダムな角度(0~360) × π(パイ) ÷ 180
さて、組んでみるか
蘊蓄はこのくらいにして(ぉぃぉぃ)、実際に組んでみます。というか、ほとんど理解してませんけれども、組み方は分かりました。だからおk。先に進むのです。
//ランダムでラジアンを決める var rad:Number = Math.random() * 360 * Math.PI / 180; //X座標 = 半径(ステージの中心) × cosθ var posX:Number = (sW / 2 + 600) * Math.cos(rad); //Y座標 = 半径(ステージの中心) × sinθ var posY:Number = (sH / 2 + 600) * Math.sin(rad);
四方八方に飛散する部分のファンクションはこうなりました。
private function scatter():void
{
var sW:int = mainStage.stageWidth;
var sH:int = mainStage.stageHeight;
for (var i:int = 0; i < photoArray.length; i++) {
//飛んでく座標決定 x=半径cosθ y=半径sinθ
//ラジアン値を計算するには、次の式を使用します。 radians = degrees * Math.PI/180
var rad:Number = Math.random() * 360 * Math.PI / 180;
var posX:Number = (sW / 2 + 600) * Math.cos(rad);
var posY:Number = (sH / 2 + 600) * Math.sin(rad);
//飛ばす画像番号
var targetNum:int = photoArray.length - i;
//飛ばす
Tweener.addTween( photoArray[targetNum],
{
x:posX,
y:posY,
time:0.5,
transition:"linear",
delay:Math.random() / 2 + 0.5
} );
}
}
何とか完成
そんなわけでなんとか完成しました。完成版のムービーはこちら
全部のコードは以下の通りです。
package
{
import flash.display.*;
import flash.events.*;
import flash.utils.getDefinitionByName;
import caurina.transitions.Tweener;
public class Peta extends MovieClip
{
public function Peta() {}
private const roopMax:int = 250; //写真配置枚数
private const scatWidth:int = 1000; //散布範囲X
private const scatHeight:int = 700; //散布範囲Y
private var roopCnt:int = 0; //写真カウンター
private var photoBmpArray:Array = new Array(); //写真配列
private var photoArray:Array = new Array(); //写真MC配列
private var target:MovieClip; //ベースMC
private var wrapper:Sprite; //真ん中に置く用ラッパー
private var mainStage:Stage;
public function init(t:MovieClip):void
{
target = t;
mainStage = target.stage;
wrapper = new Sprite();
target.addChild(wrapper);
//ステージサイズ監視
mainStage.addEventListener(Event.RESIZE, stageChange);
stageChange(null);
//散布
target.addEventListener(Event.ENTER_FRAME, setMovie);
}
private function stageChange(e:Event):void
{
wrapper.x = mainStage.stageWidth / 2;
wrapper.y = mainStage.stageHeight / 2;
}
private function setMovie(e:Event):void
{
if (roopCnt < roopMax) {
paste();
paste();
paste();
} else {
//リスナー削除
target.removeEventListener(Event.ENTER_FRAME, setMovie);
scatter(); //飛散
}
}
private function paste():void
{
roopCnt++;
//ランダム値生成
var ranP:int = Math.floor(Math.random() * 20);
var ranX:int = Math.random() * 1000;
var ranY:int = Math.random() * 700;
var ranR:int = Math.random() * 360;
//写真定義
var name_str:String = "Photo" + ranP;
var myClass:Class = Class(getDefinitionByName(name_str));
var bmp:Bitmap = new Bitmap(new myClass(0, 0));
//スプライトセット
var container:Sprite = new Sprite();
container.x = ranX - scatWidth / 2;
container.y = ranY - scatHeight / 2;
container.rotation = ranR;
container.addChild(bmp);
//配列に格納
photoArray[roopCnt] = container;
wrapper.addChild(container);
}
private function scatter():void
{
var sW:int = mainStage.stageWidth;
var sH:int = mainStage.stageHeight;
for (var i:int = 0; i < photoArray.length; i++) {
//飛んでく座標決定 x=半径cosθ y=半径sinθ
//ラジアン値を計算するには、次の式を使用します。 radians = degrees * Math.PI/180
var rad:Number = Math.random() * 360 * Math.PI / 180;
var posX:Number = (sW / 2 + 600) * Math.cos(rad);
var posY:Number = (sH / 2 + 600) * Math.sin(rad);
//飛ばす画像番号
var targetNum:int = photoArray.length - i;
//飛ばす
Tweener.addTween( photoArray[targetNum],
{
x:posX,
y:posY,
time:0.5,
transition:"linear",
delay:Math.random() / 2 + 0.5
} );
}
}
}
}

THE BACK HORN、GRAPEVINEを聞いていたと言うだけあって、そのテイストが感じられる曲調。3ピースでも音にしっかりとした厚みがあって、バランスが良いと思った。
その名の通り、切なくて冷たい雨が降る。TK(男性Vo)のハイトーンは好みが分かれるところだが、345(女性Vo)とのツインボーカルが生み出す緊迫感はとても狂おしく、破滅的で情緒に溢れている。
でもね、曲はめっちゃカッコイイス。そういう細かいところを気にするアホウは僕くらいなもんで、良いアルバムに仕上がってますよ。
いやはや、凄いの見てもーた。基本はスクリーモなんですが、エモが来たと思ったらいきなりエレクトロニカなん?4つ打ちなん?っていう最高の一品です。
1曲目の「insurance?」からいきなり「It's Only Natural」と似たテイストのノリノリナンバーで、一気に持ってかれてしまいました。全体的に気持ちよく聴けるアルバムに仕上がっています。
埼玉産インディーズバンドLooking For。同郷なら応援しないわけにはいかない。とにかくメロディック・メロディックなのであります。まさしく僕好み。ありがとうございます。
初めて聴いた感想はズバリ「つまらん」。
で、封印しようかと思いつつ、他に聴くものもないし・・・などとループ再生していたところ・・・4,5回目くらいから良くなってきました。
僕のファーストインプレッションは、
「んー、フライングキッズ?いや、オリジナルラヴ?」
でした。
前作 rapture が割とアップテンポで勢いのある印象だったので、アップテンポ好きな僕には少し物足りないというか、お子ちゃまな僕の好きな路線とはちょっと違うかなぁという感想。
女性Vo.なんですが、彼女の声と曲の世界観が絶妙です。彼女の声を聴いていると、切なくなるような、苦しくなるような、かと思えば一気に解放されるような、フワフワ浮かんでいるような。
クラムボンが好きな人とかすんなり聴けるんじゃないかと思います。
正統派J-popとでもいうべき非常に聴きやすい作品。メロディーも心地よく耳に残る感じ。無意識のうちに結構気に入っていたらしく、このまえ気付いたら4曲目のサビをひたすら口ずさんでました。
コメントする