« Flash Gun Shooting Alpha Version | メイン | Cars »

2006年06月09日

Flash Gun Shooting Alpha 2

Gunman Alpha 2
昨日から作業を再開。
シリンダーを弾を撃つごとに回るようにしてみた。
が、早く撃ったりすると処理が追いつかないのかシリンダーが回らなくなってしまう。
シリンダーのMCで弾1発減って72°回る動作アクション4フレームの内1〜3フレームがそのアニメーション、4フレーム目は3フレームと同じにしてActionScriptを以下のようにした。

例えば1発撃って残りが4発の場合は

if (_root.bullet == 4) {
gotoAndPlay("t4");
}else {
this.gotoAndPlay(_currentframe-1);
}

やはりHiroo氏の言うようにgotoAndPlayではうまく行かないんだろうか。
弾が減って回るアニメーションを5つのMCに分けてattachMovieで呼び出すってのはどうだろうか。
それとも回すのもActionScriptで制御した方がいいのかな。
逆にシリンダーが回り終わるまで弾を撃てなくすることで回避できないだろうか。
う〜ん、難しい。

追記。リロードの処理を間違えていた。
上のActionScriptでは弾を撃ちつくさないとちゃんとリロードが表示されないんだった。
現在修正中。

追記2。リロードの処理は修正したが、まだ根本的な解決には至っていない。

投稿者 Sousuke : 2006年06月09日 18:35

トラックバック

このエントリーのトラックバックURL:
http://www.sousuke.net/blog/mt-tb.cgi/651

コメント

「_currentframe-1」って?

cylinder_mcにシリンダーが回転するトゥイーンを作って、クリックごとにgotoAndPlayさせてるのだと思うけれど、以下のようにすると確実かな。

まず、swfのfpsが低いとシリンダーが回転しているように見えなくなるので、高速回転できるようにするためにfpsを上げます。
ゲームの場合は20位がイイと思います。マシンやグラフィックにも寄るけど、24以上はまず出ません(再生が遅くなる)。

・1フレーム目 ラベル「full」
全部の弾がある初期状態。stop()。

・次のラベル「bullet5」
弾が1発ない状態で72度回転するトゥイーン。最後のフレームでstop()。
以降、「bullet4」〜「bullet1」まで同様にトゥイーンを作成。

・最終ラベル 「bullet0」
弾が1発もない状態で、72度回転するだけのトゥイーン。同じく、最後のフレームstop()。

もしリロードもアニメーションさせるなら……
・「bullet0」の次に ラベル「reload」
弾がない状態から全弾装填のトゥイーン。最後のフレームでgotoAndStop("full")。

例えば各トゥイーンを5フレーム(0.25秒/20fps)で作成したとしたら、クリックしてから以後5フレーム間はクリックできないようにします。
「shot_flg」というフラグ用の変数を用意して、その値が「true」のときは撃てる、「false」のときは撃てないようにします。

敵を撃つスクリプトをどうしているか分からないので、仮に敵のMCを「enemy1_mc」とし、その1フレーム目にhit用の「hit_mc」があって、2フレーム目以降は攻撃("shot")や倒れる("hit")アニメ、ってことにしますが……。
また、サウンド面はattachSound()でもいいけれど、「sound_mc」を用意すると楽かな。

enemyNum = 10; //敵の数
frameNum = 5; //回転アニメのフレーム数
shot_flg = true; //フラグを撃てる状態に

for(i = 1;i 0){ //残弾があるとき
    sound_mc.gotoAndPlay("shot");
    this.gotoAndPlay("hit"); //敵が倒れるアニメへ
    score+=100; //スコア追加
   }else{
    sound_mc.gotoAndPlay("empty"); //カラの音
   }
   rollCylinder(); //シリンダー回転処理呼び出し
  }
 };
}

function rollCylinder(){ //シリンダー回転処理
 shot_flg = false; //フラグを撃てない状態に
 cylinder_mc.gotoAndPlay("bullet" + bullet) //残弾数に合わせ回転アニメ
 var count = 0; //カウント変数初期化
 this.onEnterFrame = function(){ //カウント処理定義
  count++; //カウント追加
  if(count>=frameNum){ //アニメのフレーム数に達したら
   shot_flg = true; //フラグを撃てる状態に
   delete this.onEnterFrame; //カウント処理削除
  }
 };
}

現物をシミュレートするような感じでしょうか。
シリンダーは残弾があるかどうか思考できるわけではないので、スクリプトでも(rollCylinder()部分)、撃った後にただ回転させるだけの内容にします。

リロードに関しても同様の作り方になります。
フラグの変数を用意して、リロード中は再びリロードアニメを再生させないよう、そのフラグをfalseにしておきます。
リロードアニメがないのでしたら、以下のようにするだけでオッケーです。

cylinder_mc.onPress = function(){
 if(shot_flg){ //trueの場合、if(shot_flg){と省略可
  this.gotoAndStop("stop");
  sound_mc.gotoAndPlay("reload");
 }
}:

とまあ、今思いついた一番簡単な方法で書いてみました。テストしてないので分からないけど……。
シリンダーが回転中でも撃てるようにするには、上記のカウンター処理関係部分をすべてなくして下さい。回転アニメは途中からはしょられますが、正しく動くはずです。

投稿者 Hiroo : 2006年06月09日 21:45

for文が、タグ扱いにされちゃった。書き直し。

for(i = 1;i<=enemyNum;i++){ //敵の数だけonPressを定義
 _root["enemy" + i + "_mc"].hit_mc.onPress = function(){
  if(shot_flg==true){ //フラグが撃てる状態のとき
   if(bullet > 0){ //残弾があるとき
    sound_mc.gotoAndPlay("shot");
    this.gotoAndPlay("hit"); //敵が倒れるアニメへ
    score+=100; //スコア追加
   }else{
    sound_mc.gotoAndPlay("empty"); //カラの音
   }
   rollCylinder(); //シリンダー回転処理呼び出し
  }
 };
}

投稿者 Hiroo : 2006年06月09日 21:53

訂正。

cylinder_mc.onPress = function(){
 if(shot_flg){
  this.gotoAndStop("full"); //ここ間違ってた
  sound_mc.gotoAndPlay("reload");
 }
}:

投稿者 Hiroo : 2006年06月09日 22:01

>Hiroo氏
おお、すごい! アドバイスありがとうございます。
現在のゲームのフレームレートは15fpsでした。

敵を撃つ部分のActionScriptは(hit判定のMCのリンケージ識別子はfire)
this.onMouseDown = function () {
if (_root.bullet > 0) {
se=new Sound();
se.attachSound("gunshot");
se.start( );
_root.attachMovie("fire","fire",18);
_root.fire._x = this._xmouse;
_root.fire._y = this._ymouse;
_root.attachMovie("flash","flash",19);
_root.flash._x = this._xmouse;
_root.flash._y = this._ymouse;
_root.bullet--;
} else {
se.stop("gunshot");
tn = new Sound ();
tn.attachSound ("empty");
tn.start();
}
}

敵のインスタンスのところに
onClipEvent (enterFrame) {
if ( this.hitTest(_root.fire) ) {
_root.fire.removeMovieClip();
this.gotoAndPlay("dead");
_root.attachMovie("deadman","deadman",11);
_root.deadman._x = this._x;
_root.deadman._y = this._y;
}
}

としていました。
Hiroo氏のアドバイスで改良します。

投稿者 Sousuke : 2006年06月09日 22:08

new Sound()とattachSound()はゲームスタート時のフレームに1度書いておけばいいと思うよ。
クリックしたらstart()。短い銃声とかは止める必要もないと思うので、他のサウンドに対するstop()もいらないんじゃないかな。

あとこのスクリプトだと、新たなdeadmanが古いdeadmanを上書きしてしまうよね。
それに各敵MCが常にhitTest()をチェックしているのも合理的ではないので、僕が書いたようにメインタイムラインにスクリプトをまとめてfor文で各敵MCを制御してみては。

スクリプトを現状に合わせて書き直してみます。
カーソルMCを「scope_mc」としてます。
cylinder_mcのラベルは「full」、「bullet5」〜「bullet1」、「empty」(カラの状態で回転)にし、リロードアニメはなしです。
カウント処理は割愛してます。

enemyNum = 16;
se = new Sound();
se.attachSound("gunshot");
re = new Sound();
re.attachSound("reload");
tn = new Sound();
tn.attachSound ("empty");

this.onMouseDown = function(){ //クリックした際の音とシリンダー処理定義
 if(scope_mc.hitTest(cylinder_mc)){ //リロード時
  bullet = 5;
  re.start();
  cylinder_mc.gotoAndStop("full");
 }else if(bullet > 0){ //リロード以外で残弾があるとき
  bullet--;
  se.start();
  cylinder_mc.gotoAndPlay("bullet" + bullet);
  enemyHitTest();
 }else{ //カラのとき
  tn.start();
  cylinder_mc.gotoAndPlay("empty");
 }
};

function enemyHitTest(){
 for(i=1; i<=enemyNum; i++){ //敵MCを一括定義
  var mcName = _root["enemy" + i + "_mc"]; //一時的に敵MC名を代入
  mcName.num = i; //各MCのnum変数にMC名に合わせた番号格納
  if(scope_mc.hitTest(mcName.hit_mc)){ //敵MCのhit_mcをクリックしたら
   score+=50;
   mcName.gotoAndPlay("dead");
   _root.attachMovie("deadman", "deadman", 10 + mcName.num);
   deadman._x = mcName._x;
   deadman._y = mcName._y;
  }
 }
};

こんな感じかな。

投稿者 Hiroo : 2006年06月09日 23:45

おっと、「deadman._y = mcName._y;」のあとに「break;」を入れて下さい。
あと一番最後の「;」はいりません。

投稿者 Hiroo : 2006年06月09日 23:50

訂正。
最後のはただのhitTest()なので、特にmcName.numはいらないですね。

_root.attachMovie("deadman", "deadman", 10 + i);
でいいです。

投稿者 Hiroo : 2006年06月09日 23:59

>Hiroo氏
Roger! 本日帰宅してから改良に取りかかります。
やはりなるべく_root上にまとめた方が合理的ですね。

投稿者 Sousuke : 2006年06月10日 06:25

先に敵出現関係からしようと思って、とりあえずcylinderの方は
this.onMouseDown = function () {
if (bullet > 0) {
se.start( );
attachMovie("fire","fire",18);
fire._x = this._xmouse;
fire._y = this._ymouse;
attachMovie("flash","flash",19);
flash._x = this._xmouse;
flash._y = this._ymouse;
bullet--;
cylinder.gotoAndPlay("t" + bullet);
enemyHitTest();
} else {
se.stop();
tn.start();
}
}

cylinder.onPress = function () {
flash.removeMovieClip();
fire.removeMovieClip();
se.stop( );
re.start();
bullet = 5;
cylinder.gotoAndPlay("t5");
}
にしました。
(crosshairはtitleラベルのところでattachMovieしている。fireはcrosshairのhit判定用MC。crosshairをattachMovieしたのは、deadmanより上に来てほしいから。)
enemyのMC個々にスクリプトがある時は普通に動作しますし、cylinderの挙動も正常です。

enemyのMC個々のActionScriptを消去した後、上記のScriptの下に
function enemyHitTest(){
 for(i=1; i<=enemyNum; i++){ //敵MCを一括定義
  var mcName = _root["enemy" + i + "_mc"]; //一時的に敵MC名を代入
  mcName.num = i; //各MCのnum変数にMC名に合わせた番号格納
  if(_root.fire.hitTest(mcName.hit_mc)){ //敵MCのhit_mcをクリックしたら
   score+=50;
   mcName.gotoAndPlay("dead");
   _root.attachMovie("deadman", "deadman", 10 + i);
   deadman._x = mcName._x;
   deadman._y = mcName._y;
break;
  }
 }
}
と記述してムービープレビューすると、
**エラー** シーン = シーン 1, レイヤー = スクリプト, フレーム = 7 :行 40:シンタックスエラー
 for(i=1; i<=enemyNum; i++){ //敵MCを一括定義

ActionScript エラー数 :1 報告済みエラー :1
と表示されてしまいます。
弾は撃てなくなり、Scoreは99999のままです。
多分俺の敵のMCの作り方が悪いとせいだと思います。
もうちょっと試行錯誤してみます。

投稿者 Sousuke : 2006年06月11日 18:14

追記。(MC等の名称は変更しています。)
cylinderの方も
this.onMouseDown = function(){ //クリックした際の音とシリンダー処理定義
 if(crosshair.hitTest(cylinder)){ //リロード時
  bullet = 5;
  re.start();
  cylinder.gotoAndStop("t5");
 }else if(bullet > 0){ //リロード以外で残弾があるとき
  bullet--;
  se.start();
  cylinder.gotoAndPlay("t" + bullet);
  enemyHitTest();
 }else{ //カラのとき
  tn.start();
  cylinder_mc.gotoAndPlay("t0");
 }
};
とすると以下のようなエラーが出ます。
**エラー** シーン = シーン 1, レイヤー = スクリプト, フレーム = 7 :行 13:演算子 '=' は、オペランドの前に来る必要があります。
this.onMouseDown = function(){ //クリックした際の音とシリンダー処理定義

**エラー** シーン = シーン 1, レイヤー = スクリプト, フレーム = 7 :行 14:シンタックスエラー
 if(crosshair.hitTest(cylinder)){ //リロード時

ActionScript エラー数 :2 報告済みエラー :2

投稿者 Sousuke : 2006年06月11日 18:19

スクリプトを書いたら「自動フォーマット」ボタンをクリック(またはショートカットキーで)するクセを付けるとイイよ。その時点で記述ミスがあるかどうか分かります。

で、コピペじゃなくて書き直してみて。

投稿者 Hiroo : 2006年06月11日 23:28

Roger!
で今全部書き直しました。
var mcName.num = _root["enemy"+i+"_mc"];
の辺りでシンタックスエラーが発生しているようで、試しにvarを取ってみるとエラーはなくなりました。
score、cylinder、弾、共にちゃんと動作します。
やっぱりずぼらしてコピペはいかんですね。
ただまだenemyにHitしないので、その辺りをもうちょっといじってみます。

投稿者 Sousuke : 2006年06月12日 06:22

あれ、おかしいな。
mcNameはそのステートメントでしか使わないローカル変数なので「var」があった方がいいのだけど。

というか、そこ違う。「num」いりません。
var mcName = _root["enemy"+i+"_mc];
です。

mcName.num = i;
もいりません。

投稿者 Hiroo : 2006年06月12日 07:24

あっ、num入れてました。寝ぼけてました。ご免なさい。
エラーがなくなりました。
hitTestはこんな感じにしています。
if (fire.hitTest(mcName.hit_mc)) {...}

「fire」はシリンダー処理定義内の
} else if (bullet>0) {
attachMovie("fire", "fire", 18);
fire._x = this._xmouse;
fire._y = this._ymouse;
attachMovie("flash", "flash", 19);
flash._x = this._xmouse;
flash._y = this._ymouse;
bullet--;
se.start();
cylinder.gotoAndPlay("t"+bullet);
enemyHitTest();
のところでattachMovieしてます。

crosshairのhit判定用のfireがenemy内のhit_mcとhit判定出来てないようです。
hitMC(hit_mcのムービークリップ名)をenemyのMC内に入れてそのフレームラベル名を「hit_mc」としています。
多分俺が単純なミスをしてるように思います。
作業の続きは夕方帰宅してから行います。
このBlogは携帯からも見ることが出来るので、外でもコメントの確認は出来ます。
http://www.sousuke.net/blog/mt4i.cgi

投稿者 Sousuke : 2006年06月12日 08:05

フレームラベルじゃなくてインスタンス名だった。
やはり寝起きでいきなりはダメですね。
帰宅したら修正します。

投稿者 Sousuke : 2006年06月12日 09:05

ごめん、うっかりしてたー。
「mcName」はインスタンス名ではなく変数なので、パス内に入れるときは「[]」で囲む必要があります。

_root[mcName].hit_mc

という書き方です。コレでいけるはず。

ちなみに「mcName」という変数を使わないときは、

_root["enemy"+i+"_mc"].hit_mc

という書き方になります。

投稿者 Hiroo : 2006年06月12日 10:44

下記のように修正しましたが、まだ敵にHitしないようです。
筋は間違いなく通ってると思うんですが。
function enemyHitTest() {
for (i=1; i<=enemyNum; i++) {
var mcName = _root["enemy"+i+"_mc"];
if (_root.fire.hitTest(_root[mcName].hit_mc)) {
score += 50;
mcName.gotoAndPlay("dead");
_root.attachMovie("deadman", "deadman", 10+i);
deadman._x = mcName._x;
deadman._y = mcName._y;
break;
}
}
}
_root上に17匹設置した敵のインスタンス名はenemy1_mc〜enemy17_mcにしています。
もしかしてenemyMCの作りに問題があるのかも。
enemyMCの構造はwait、up、shoot、deadのフレームラベルに分かれていて、waitのところのMath.random()でupへ、upの途中でMath.random()でshootへ移動するようになってます。
hitMC(enemyMC上のインスタンス名はhit_mc)はup〜shootの間に置いてます。

投稿者 Sousuke : 2006年06月12日 21:54

「mcName」のところは、最初の代入式以外全部「_root[mcName]」にしないとダメー。

_root[mcName].gotoAndPlay("dead");
_root.attachMovie("deadman", "deadman", 10+i);
deadman._x = _root[mcName]._x;
deadman._y = _root[mcName]._y;
break;

投稿者 Hiroo : 2006年06月13日 00:06

ということで
var mcName = "enemy"+i+"_mc";
の書き間違いでした。

ところで、「_root」は使わない方向で。
例えば、もし今後ポートフォリオとかで「flash game gallary」みたいなのをFlashで作って、これまでの作品をまとめようとした際に、子のswfにある「_root」と記述してある部分はすべて親のswfのルートを参照してしまいます。
それを避けるために、最初のフレームに

_global.dRoot = this;

と書いて、以降「_root」の代わりに「dRoot」と記述しましょう。

dRoot["enemy"+i+"_mc"].hit_mc

投稿者 Hiroo : 2006年06月13日 13:17

修正版をアップしました。
Hiroo氏のアドバイスで
var mcName = _root["enemy"+i+"_mc"];

var mcName = "enemy"+i+"_mc";
に変更することにより、敵にHitするようになりました。
今後も要素を追加、修正して行きます。

追記。dRootの件も了解しました。

投稿者 Sousuke : 2006年06月13日 13:25

ソースケ君に見せたflaファイル、setInterval()の使い方間違ってたね。
関数の呼び出しにわざわざ「"」でくくらなければならないのが、一体どういうことなのか不思議だったんだけど、「"」でくくるのはメソッドのときなのね。
関数呼び出しのときはターゲットもいらないし、くくらなくてもいいんだ。

オンラインリファレンス、間違ってるだろこれー。

Flash8用の「ActionScriptポケットリファレンス」っていつまでたっても出ないですね。

投稿者 Hiroo : 2006年06月17日 15:11

なんかちょこちょこオンラインリファレンス間違ってるみたいですね。
でもムービープレビューでは普通に動作しているように感じました。
本当にActionScriptポケットリファレンス出ないですねー。
馬場さんはやく。

投稿者 Sousuke : 2006年06月17日 16:16

Adobeのアンケートやってみた?
CS3の内容が分かるんだけど、どれにアップグレードするかちょっと迷うね。
FireworksとGoLiveはなくなると言ってたはずなんだけど、CS3にはまだ残ってました。
CS3 Design Suit Premium 12万か、Web Design Suit Premium 11万のどっちかだなあ。

投稿者 Hiroo : 2006年06月22日 22:33

>Hiroo氏
アンケートはメールのリンクからですか?
よく読まないで捨ててしまってるかも。
Adobeのアップグレードポリシーが旧Macromedia商品にも対応しているなら、あわてて買うことはないかもしれません。
早急にIntel Macがいるなら間違いなく買いでしょうけど。
FireworksとGoLiveをなくすなら、早いところなくしてすっきりさせてほしくもあります。

投稿者 Sousuke : 2006年06月22日 23:38

そう、メールできたやつ。
もれなく商品券がもらえるのでやってみました。

まだ組み合わせや価格は決まってないみたい。
アンケート結果を参考に決めるってことのようです。
だから上に書いた価格は未定です。

アンケート中に出てくる組み合わせだと旧Macromedia StudioからのCS3アップグレードは対応するっぽいです。
Flash、DW含め全面的にバージョンアップでした。

投稿者 Hiroo : 2006年06月23日 03:47

なるほど。CS3では今までより安めにアップグレード出来るかもしれないですね。
DWやFlashの文字がぐしゃぐしゃになったり消えてしまうバグを今度こそ修正してほしいですね。

投稿者 Sousuke : 2006年06月24日 12:05

Flash 9ではActionScript3.0が使えるようになるということなので、これはもしかするとポケットリファレンスは出ないかも。

http://journal.mycom.co.jp/articles/2006/06/20/flash/

2ページ目に書いてある「ディスプレイリスト」はイイなあ。
奥行きのあるゲーム作るときにキャラの動きに合わせて深度を調整するの面倒だったんだよね。勝手に生成される深度の数値も訳分からなかったし。

しかし2.0もまだ把握し切れてないのに……勉強するの大変だなあ。

投稿者 Hiroo : 2006年06月24日 17:06

千原 壮介様はじめまして。

つい先日、+Creator's net+というソフトウェア別検索エンジンを開設しました。

つきましては、Painter、その他関連性のあるカテゴリに登録してはいただけないでしょうか。

クリエイターを繋ぐ大きな輪になれば良いなと思っています。

相互リンク等も必須ではないので、手軽に登録できると思います。

ご検討願えたら幸いです。

URL:http://uradesign.com/creatornet/creatornet.htm

+Creator'snet+管理人:ぶっぽより

投稿者 ぶっぽ : 2006年06月24日 17:26

>Hiroo氏
まだAS1.0も把握してないのに、どんどん進化してますね。
ディスプレイリストはAS3.0が自動的に重なり順を決めるみたいです。
Spriteクラスはもしかして昔のゲームで使われたSpriteと同じような感じなんでしょうか。

>ぶっぽさん
コメント&お誘いありがとうございます。
ちょっと考えさせて下さい。

投稿者 Sousuke : 2006年06月24日 18:55

コメントしてください




保存しますか?