Entries

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
この記事に対してトラックバックを送信する(FC2ブログユーザー)
http://penntyann.blog94.fc2.com/tb.php/1245-bf9ea3ee

-件のトラックバック

-件のコメント

コメントの投稿

投稿フォーム
投稿した内容は管理者にだけ閲覧出来ます

NO.1484 【Parafla!】ハエっぽい動きを作る【1アクション縛り】

 変わり種企画登場。

 Flash(ActionScript 以下AS)で特定の動きを作ってみよう的な企画。一発ネタ?
 使用ソフトは無料国産Flash作成ソフトでお馴染み「Parafla!」。3年前の今頃を境に何一つ更新されなくなったんだけどどうしたんだろう。ParaPoly楽しみにしてるのに…。
 それはさておき、原則的に使うソフトはこれだけ。ParaDrawとかペイントとかお絵かきツールは一切無し。「絵どうすんだよ」ってのは後程説明。
 もう一つ、イベントリストの動作は「フレームアクション」1つのみ。つまり、

に全動作を記述する。ファイルリストも原則空っぽで。音声を使う場合は仕方無いので例外扱い。因みにこんな感じで作っていくとこうなるw
 
 本題に入ろう。先ずは動かす対象となるハエを用意するが、画像を使えない状態でどうするかと言うと、ASの描画機能を使う。詳しくはお絵かき教室でも読んでもらうとして(専門外の人や読むのめんどくさい人は「プログラミングで絵が描けるんだ」って事だけ理解すればおk)、之を踏まえて、
lineStyle(2,0x000000,100);
beginFill(0xffffff,100);
curveTo(8,-8,8,0);
curveTo(8,8,0,0);
curveTo(-8,-8,-8,0);
curveTo(-8,8,0,0);
endFill();
lineStyle(6,0x000000,100);
moveTo(0,-2);
lineTo(0,2);
endFill();
こんな風に記述してプレビューしてやると、

凄い位置にハエが描けた。之じゃ良く分からんし、この後動かすのに不便極まりないので、スプライトの中に書き込んでしまおう。とは言っても、ファイルリストにスプライトを作り、それをイベントリストに表示して…ってのはタブーなので、之もASで書いてしまう。
_root.createEmptyMovieClip("hae", 256); //新しいスプライトを作る(名前は"hae", 深度は256);

hae._x = 120; //スプライト「hae」の表示位置を決める
hae._y = 120;

_root.hae.
lineStyle(2,0x000000,100); //さっきの全動作をスプライト「hae」の中に記述
hae.beginFill(0xffffff,100);
hae.curveTo(8,-8,8,0);
hae.curveTo(8,8,0,0);
hae.curveTo(-8,-8,-8,0);
hae.curveTo(-8,8,0,0);
hae.endFill();
hae.lineStyle(6,0x000000,100);
hae.moveTo(0,-2);
hae.lineTo(0,2);
hae.endFill();
赤字を追加、緑時はコメントなので無くてもおk。之でプレビューすると、

こんなん出来たね。めっちゃテキトーだけどちゃんとハエになってる。

 ところで、上のスクリプト見て「hae.」って全部書くのめんどくさくね?と思うだろうけど、実はこのめんどくさいのを簡略化出来る。
_root.createEmptyMovieClip("hae", 256);

hae._x = 120;
hae._y = 120;

hae.lineStyle(2,0x000000,100);
hae.beginFill(0xffffff,100);
hae.curveTo(8,-8,8,0);
hae.curveTo(8,8,0,0);
hae.curveTo(-8,-8,-8,0);
hae.curveTo(-8,8,0,0);
hae.endFill();
hae.lineStyle(6,0x000000,100);
hae.moveTo(0,-2);
hae.lineTo(0,2);
hae.endFill();
_root.createEmptyMovieClip("hae", 256);
with(hae){ //{}に囲まれたスクリプトの頭に全て「hae.」が付く;
    _x = 120;
    _y = 120;

    lineStyle(2,0x000000,100);
    beginFill(0xffffff,100);
    curveTo(8,-8,8,0);
    curveTo(8,8,0,0);
    curveTo(-8,-8,-8,0);
    _root.hae.curveTo(-8,8,0,0);
    endFill();
    lineStyle(6,0x000000,100);
    moveTo(0,-2);
    lineTo(0,2);
    endFill();
}
青字を消して、赤字を追加。プレビューしても見た目は変わらないけど、記述がスッキリした。因みに、{}の中の行頭に空白を入れてるけど、無くても問題無い。但し記述が複雑になる程読みにくくなるのでオススメ出来ない。記事中では全角スペース4つにしてるけど本当はtabキー(滅多に使われないよねこのキーw)を使う。
 序でに、配置位置をランダムにしよう。
_root.createEmptyMovieClip("hae", 256);
with(hae){
    _x = 120;
    _y = 120;

    lineStyle(2,0x000000,100);
    beginFill(0xffffff,100);
    curveTo(8,-8,8,0);
    curveTo(8,8,0,0);
    curveTo(-8,-8,-8,0);
    _root.hae.curveTo(-8,8,0,0);
    endFill();
    lineStyle(6,0x000000,100);
    moveTo(0,-2);
    lineTo(0,2);
    endFill();
}
_root.createEmptyMovieClip("hae", 256);
with(hae){
    _x = random(240);
    _y = random(240);

    lineStyle(2,0x000000,100);
    beginFill(0xffffff,100);
    curveTo(8,-8,8,0);
    curveTo(8,8,0,0);
    curveTo(-8,-8,-8,0);
    _root.hae.curveTo(-8,8,0,0);
    endFill();
    lineStyle(6,0x000000,100);
    moveTo(0,-2);
    lineTo(0,2);
    endFill();
}

プレビューする度にハエの出現位置が変わる。今度は之を動かしていこう。

 フレーム毎に同じ動作をしてやりたい場合、フレームアクション内では「onEnterframe = function(){};」と書き、{}内に記述する。
 この先一つ注意しないといけないのは、AS内では360で1周する「度数法」と2πで1周する「弧度法」が混在する事。特に「Math.なんちゃら」の中では高校諸氏を悩ませる弧度法を当たり前のように使うので、気を付けないと頓珍漢な動きをしてくれる(之のせいで3時間吹っ飛んだw)。その為、度数法と弧度法の変換用に何処でもいいので(最初の方が望ましい)
変数 = Math.PI / 180;
と書いておくとよい。変数名は何でもいいが短ければ短いほど楽なので此処では「p」にする。必要に応じてコイツを掛けたり割ったりすればいい。

 まず、どの様な動きをさせてやればいいかイメージを考えよう。

とりあえずこんな感じで。この動きをASで再現する。一気に書いちゃおう。(都合によりハエの縦横が変わってるけど大きな問題ではないのでそのままで)
xm = random(240); //目的地をランダムに設定
ym = random(240);
p = Math.PI / 180;
//度数法と弧度法の変換用

_root.createEmptyMovieClip("hae", 256);

with(hae){
    _x = random(240);
    _y = random(240);

    lineStyle(2,0,100);
    beginFill(0xffffff,100);
    curveTo(-8,8,0,8);
    curveTo(8,8,0,0);
    curveTo(-8,-8,0,-8);
    curveTo(8,-8,0,0);
    endFill();
    lineStyle(6,0,100);
    moveTo(-2,0);
    lineTo(2,0);
    endFill();
}

onEnterFrame = function(){ //{}内を毎フレーム実行
    t = Math.atan2(ym - hae._y,xm - hae._x); //自分の位置と目的地との角度差を計算
    with(hae){
        t = Math.atan2(ym - hae._y,xm - hae._x); //自分の位置と目的地との角度差を計        _x += Math.cos(t); //それぞれ横、縦方向への移動距離を計算
        _y += Math.sin(t);
        _rotation = t / p; //ハエの向き。之は度数法なので変換してやる
    }
    if(Math.abs(xm - hae._x) <= 1 || Math.abs(ym - hae._y) <= 1){
         //縦横どちらかハエの位置と目的地との差が±1以内に近づいたら
        xm = random(240); //目的地を再設定
        ym = random(240);
    }
};
此処で重要になるのは先ずkaku = Math.atan2(ym - hae._y,xm - hae._x);という行。縦と横方向の長さから角度を出している。いわゆるアークタンジェントという奴だ。

例えば、上の様な三角形があり、θは何度?って時に使う(因みに此場合約63.4度)。今回の場合、その値は縦横それぞれ目的地の位置-ハエの位置で計算する。之で出た値を縦横それぞれの移動量の計算とハエの向きの計算に使う。
 もう一つ重要なのはif(Math.abs(xm - _root.hae._x) <= 1 || Math.abs(ym - _root.hae._y) <= 1){という行。移動していくと目的地に着く。そしたら新しい目的地を設定してやらねばならない。だから、ハエの位置が目的地の位置±1以内に近づいたら新しい目的地を設定してやるという処理をする。
 一先ず之をプレビューしてみると、

超遅いね。もっとビュンビュン動き回ってくれないと。と思って、
xm = random(240);
ym = random(240);
p = Math.PI / 180;

_root.createEmptyMovieClip("hae", 256);

with(hae){
    _x = random(240);
    _y = random(240);

    lineStyle(2,0,100);
    beginFill(0xffffff,100);
    curveTo(-8,8,0,8);
    curveTo(8,8,0,0);
    curveTo(-8,-8,0,-8);
    curveTo(8,-8,0,0);
    endFill();
    lineStyle(6,0,100);
    moveTo(-2,0);
    lineTo(2,0);
    endFill();
}
onEnterFrame = function(){
    with(hae){
        t = Math.atan2(ym - hae._y,xm - hae._x);
        _x += Math.cos(t) * 10;
        _y += Math.sin(t) * 10;
        _rotation = t / p;
    }
    if(Math.abs(xm - hae._x) <= 1 || Math.abs(ym - hae._y) <= 1){
        xm = random(240);
        ym = random(240);
    }
};
こんな風に書いちゃうと、時々
        \みなぎってきた/

こんな動きをしてくれちゃってどうしようも無くなるw要するに「行き過ぎちゃって戻る」を延々繰り返してる訳で、之を防ぐには、移動距離を増やすのではなく、フレーム毎の処理回数を増やせば良い。
xm = random(240);
ym = random(240);
p = Math.PI / 180;

_root.createEmptyMovieClip("hae", 256);

with(hae){
    _x = random(240);
    _y = random(240);

    lineStyle(2,0,100);
    beginFill(0xffffff,100);
    curveTo(-8,8,0,8);
    curveTo(8,8,0,0);
    curveTo(-8,-8,0,-8);
    curveTo(8,-8,0,0);
    endFill();
    lineStyle(6,0,100);
    moveTo(-2,0);
    lineTo(2,0);
    endFill();
}
onEnterFrame = function(){
    for(i = 0; i <= 10; i++){ //10回繰り返す
        with(hae){
            t = Math.atan2(ym - hae._y,xm - hae._x);
            _x += Math.cos(t);
            _y += Math.sin(t);
            _rotation = t / p;
        }
        if(Math.abs(xm - hae._x) <= 1 || Math.abs(ym - hae._y) <= 1){
            xm = random(240);
            ym = random(240);
        }
    }
};
さっきの代わりにこう書き加えてやると、

ブルブル震える事無く動き回ってくれる。かなりハエっぽくなってきたね。之で完成でもいいんだけど、まだ何か違和感があるね。動きが直線的過ぎる。もっと丸みを帯びた軌道で動いて欲しい。そこで、こう書き換える。
xm = random(240);
ym = random(240);
p = Math.PI / 180;

_root.createEmptyMovieClip("hae", 256);

with(hae){
    _x = random(240);
    _y = random(240);

    lineStyle(2,0,100);
    beginFill(0xffffff,100);
    curveTo(-8,8,0,8);
    curveTo(8,8,0,0);
    curveTo(-8,-8,0,-8);
    curveTo(8,-8,0,0);
    endFill();
    lineStyle(6,0,100);
    moveTo(-2,0);
    lineTo(2,0);
    endFill();
}
onEnterFrame = function(){
    for(i = 0; i <= 20; i++){//序でに20倍速に
        with(hae){
            t += 360 / (Math.sqrt(Math.pow(xm - hae._x,2) + Math.pow(ym - hae._y,2)) / Math.cos(Math.PI / 2 - Math.atan2(ym - hae._y,xm - hae._x) + t) * Math.PI) * p;//円軌道を描く為の式
            _x += Math.cos(t);
            _y += Math.sin(t);
            _rotation = t / p;
        }
        if(Math.abs(xm - hae._x) <= 1 && Math.abs(ym - hae._y) <= 1){
            xm = random(240);
            ym = random(240);
        }
    }
};
何やらトンデモナイ式が出てきたけど、之はハエに目的地に向けた円軌道を描いて貰う為の式。もう少し説明すると、

先ず2点と、その内1点を通ってx軸と平行な直線との角度がθ°の直線がある時、2点を通って且つ直線が接線となる円の半径を求めている。その計算式は上記になるが、とりあえず分からなくていい。って言うか式作った俺も分からんw合ってんのか之w360をこの円周で割って、最終的にはハエが1進む間に何ラジアン曲がればいいかを計算している。そしたらこの式をASで使う形に書き替えて、終了。
 最初からこの動きに漕ぎ着く迄なんと8時間を要したw式は全部自力だし計算は合わないし計算誤差で微妙に目的地着いてくれないしで大パニック。手元に散らばるメモの山。

結果的にはこんな動きをしてくれるが欠点があって、画面外に軌道を取って来る事が多い。もう一つ、目的地が自分の真後ろに近付く程描く円が大きくなって暫く帰ってこなくなる事があるw上のFlashが真っ白になっている時は放浪中。お茶でも飲みながらゆっくり待つか更新をどうぞ。
 さっきの直線的な動きのほうが未だマシと言う人も居るかも知れないので、お好きな方をどうぞ。
 後は創意次第で色々自由が効く。円が大きくなったら横に方向転換するとか、複数体をいっぺんに動かすとか。ハエをリアルにするとか。

 とりあえず何が言いたいかと言うと、幾何学的なプログラミングは数学と根性だ!あれ、当初の目的と違うw
この記事に対してトラックバックを送信する(FC2ブログユーザー)
http://penntyann.blog94.fc2.com/tb.php/1245-bf9ea3ee

0件のトラックバック

0件のコメント

コメントの投稿

投稿フォーム
投稿した内容は管理者にだけ閲覧出来ます

Appendix

プロフィール

ペンちゃん

Author:ペンちゃん
 記事は時々加筆・訂正されるかも。
 その日の内に書き上がらなかった記事は
投稿日時59分59秒にしてある。
身長 172cm 体重 53kg 年齢 23歳
性別 男 生息地 秦野 弱点 両腰
 人嫌いの癖に何故かサービス業で頑張る
常識に囚われない社会人。
 自分でもよく分からない性格と発想を持つ。
基本のんびり屋。基本天然。PC歴が年齢-3年。
 太鼓の達人三段(10年やってる腕前とは思えん)。
スコアネームは旧筐体が「 いわた」(頭が1文字空いてる)。
現在は「ぺんちゃん」。
 ネットの影でこっそり流行った「太鼓のタスジン」の
製作者。また何か企んでいるが行動に移す気が無い。
 東方Projectはゲームのオマケ付き音楽CDだと
思っているとか。


月別アーカイブ


InterPot 自分の土地

Akinnen 22-10

Zokeholm 15-5

Rostan 3-12

ブロとも申請フォーム

この人とブロともになる

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。