- ベストアンサー
アクションスクリプトでのブロック崩しの作り方
フラッシュを始めたての初心者です。よろしくお願いします。 「http://hakuhin.hp.infoseek.co.jp/main/as.html」さんのホームページのブロック崩しの作り方にそってブロック崩しを作ったのですが、少し手を加えて「3回玉が当たらないと消えないブロック」と「消えると玉が2つに増えるブロック」を作りたいのですが、あれこれ考えては見ましたが知識がないものでさっぱり解りません。 ご存知の方がおられましたら、お教えください。 どうかよろしくお願いします。
- みんなの回答 (2)
- 専門家の回答
質問者が選んだベストアンサー
#1です。 耐久力の異なるブロックの件は解決しましたでしょうか? よくある失敗の原因としては、 ・実は普通のブロックが配置されていた ・耐久力を表す変数の名前や初期値が間違っている といったところです。 色違いのブロックのシンボルを作るなどして硬いブロックが配置されていることが視覚的にも分かるように作ると、確認もラクです。 #1の作例を作るにあたり、ご提示のサイトで配布されているサンプル” block_07_01_fla05_as1.fla ”を使用させていただきました。 このサンプルでは、attachMovie でブロックを動的に配置しているようです。 同様に attachMovie で配置している場合は、硬いブロックのシンボルにもリンケージを設定し、attachMovie の1番目のパラメータにこのシンボルのリンケージ名を指定してみてください。 リンケージの設定等に誤りがなければ、32 個とも全て硬いブロックが配置されます。 ----------------------------------------------------------- 打ち返す玉が2個に増えるパワーアップについて、考え方のヒントだけご紹介します。 プログラミングは物事を細かく考えることから始まります。 アイデアを形にするためにも、漠然と”2個になる”で終わらず、もっと細かくパワーアップの仕様を決めましょう。 まず、2個目の玉はどこから出てくるのでしょうか。 壊したブロックからだとすると、2個目の玉が出現する際の動き方も決めなければなりません。普通の玉(持ち玉)のように斜めに射出されるのか、それとも、単純に直線的に落下してくるのか? また、壊したブロックの場所から出てくる場合は、バーまで届く間に他のブロックに当たる可能性があります。その際に持ち玉と同様に反射するとなると、残っているブロックの配置によってはバーのところまでなかなか落ちてこなくなることもありえます。 壊したブロックから出るとなると、このようにいろいろと考えることが多くなるので、簡単なところで、持ち玉と同様にバーから出してしまうのも1つの方法です。 それから、一番の問題は増えた玉を落とした時の扱いです。 私の知っているゲームですと、増えた玉を落としてもミスにならずパワーアップの効果が消えるだけですが、持ち玉を落とすと増えた玉が無事でもミス(パワーアップの効果も消える)になっていました。 この発想だと残数制のシステムにも簡単に組み込めますから、最初のうちはオススメです。 こうではなく、持ち玉を落としても増えた玉が無事ならミスにならない、という考え方もできます。 ********************************************** 仮に、玉が2個になる時の仕様を次のように決めたとします。 ・2個目の玉はバーから出る。出方は持ち玉と同じ。 ・2個目の玉を落とすと、この玉が消えるだけでミスにはならない。 ・持ち玉を落とした場合は、2個目の玉が無事でもミスになる。 ・2個目の玉が既に存在している時は、2個になるブロックを壊しても何も起こらない。 仕様が決まったら、この仕様を実現するにあたってどんなことが必要なのか、2個になる時やなった後にどのような変化が起こるのかを考えてみましょう。 細かく考えていくと、スクリプトの方向性も見えてきます。 ********************************************** 2個目の玉も、移動・ブロックにダメージを与える・ブロックやバーに当たって反射するといった性質は持ち玉と同じです。 ですから、この処理は持ち玉と同じ発想で作れそうです。 しかし、2個目の玉は最初は存在しておらず、玉が2個になるブロックを壊した時に初めて画面に登場し、持ち玉と同じ性能を発揮するのです。 これは要するに、移動等の処理を行う時に条件を付けて”2個目の玉が画面に出ている時にだけ”行うようにすればいいわけです。 2個目の玉が存在しているかどうかの判断は、「画面に出ている」を「表示されている」と言い換えると、画面に表示する・しないを決める _visible プロパティを見て判断できそうですね。 カラクリのタネとしては、まず、2個目の玉に持ち玉と同様の移動・ブロックとの判定等を書き、最初は _visible プロパティを false にしてステージのどこかに隠しておきます。 onClipEvent(enterFrame) に書かれている移動等の処理は全体を _visible プロパティを見る if 文の中にいれ、_visible プロパティが true の時にだけ行うようにします。 移動等の処理は持ち玉のものをコピーしてもいいのですが、持ち玉のスクリプト(特に、ブロックおよびバーとの当たり判定の部分)は専用のスクリプトになっているため、インスタンスの名前のなど細かい点を変更する必要があります。 それから、2個目の玉を落としてもミスではありませんから、下端に来た時の処理も変更します。 ********************************************** 2個目の玉は、どんな時に現れて、どうしたら消えるのでしょうか。 現れるのは”2個になるブロックを壊した時”ですから、2個目の玉を出させる処理はブロックが壊れた時、それも、壊れたブロックの種類が玉を2個にするものだったと判明する部分に入れます。 異なる種類のブロックの作り方や判別方法は、#1の1アップブロックの考え方をご参考になさってください。 ブロックを壊せるのは、持ち玉と増えた2個目の玉の両方です。 従って、「壊したブロックが玉を2個にするブロックだった時、2個目の玉を出現させる」処理は、持ち玉および2個目の玉の両方に必要です。 ところで、ステージに隠してある2個目の玉は1つしかありません。 ですから、ただ出現させるだけでなく条件を付けて、”2個目の玉が表示されていなければ出現させる”ようにしましょう。 既に2個目の玉が表示されている時は条件が不成立になり、2個にするブロックがいくつあっても2個目の玉は同時には1つしか登場しなくなります。 2個目の玉が消える時は、 ・持ち玉を受け損なった時(ミス) ・2個目の玉を受け損なった時(ミスにならない) です。 つまり、持ち玉が下端に来た時はミス・ゲームオーバーの判定・ミスからの復帰の処理とともに2個目の玉を消す処理が必要ですが、2個目の玉の場合は単純に自分自身が消える処理だけでいいというわけです。 ********************************************** 2個目の玉を出現させるには、要するに2個目の玉のインスタンスの _visible プロパティを true にすればいいのですが、問題はその位置です。 適当な位置に隠しておいたものをただ表示しては、何の脈絡もない場所に唐突に2個目の玉が出現してしまいます。 そこで、2個目の玉を出現させる時に、初期位置と移動量を設定するようにします。 2個目の玉をバーの中央から出現させるには、玉の位置をバーの位置をもとに決めるようにします。 式にしますと 玉の初期 _x = バーの _x 玉の初期 _y = バーの _y - 10 となります。これで、バーがどの位置にあっても2個目の玉はバーの中央から打ち出されるようになります。 (ただし、2個目の玉が出た瞬間にバーが動くと、打ち出される位置がズレて見えることがあります) 2個目の玉も持ち玉と同様に斜めに打ち出されるように、初期位置を決めるとともに移動量を表す dx と dy の初期値の設定もお忘れなく。 ********************************************** ActionScript では、変数やムービークリップなどのインスタンスには全て、持ち主がいると考えます。 変数などを利用する時は、誰の持ち物なのか、その持ち主を正確に指定しなければなりません。 持ち主の指定のことを”ターゲットパス”といいます。 今回は2個目の玉がブロックの状況を見たり、持ち玉が2個目の玉に指示を出したりと、他のムービークリップが持っている情報を利用するところが多く出てきます。 これまではターゲットパスをあまり気にしなくても何とかなりましたが、今回はターゲットパスの誤りにも注意してください。 例えば、各ブロックが消えたかどうかを管理している” flg ”という配列変数があります。 この配列変数の持ち主は ball というインスタンスで、その ball の持ち主は _root です。 flg はブロックの有無の情報を持っていますから、ブロックを消すことができる2個目の玉も見せてもらう必要があります。 ターゲットパスは自分自身の持ち物であれば省略できるので、サンプルでは flg[ i ] = 1 というように flg の前にターゲットパスを何も付けずに参照していました。 しかし、2個目の玉から見ると、この配列変数は他のムービークリップの持ち物です。見せてもらうには、その持ち主である持ち玉のインスタンスを指定しなければなりません。 具体的には _root.ball.flg[ i ] = 1; というように書きます。 ターゲットパスには様々な書き方があります。 _root から書くと不都合が出る場合もあるので、いろいろと研究してみてください。 ----------------------------------------------------------- 最後になりましたが。 このサンプルは Flash 5 向けに作られたもので、現在のバージョンの Flash から見ると相当古い書き方です。 特に、多用している eval 関数は Flash Player 6 からは制限が付き、式の左辺に書くとエラーになるように変更されました。 Flash Player 5 でパブリッシュすれば問題ありませんが、このサンプルを Flash Player 6 以降でパブリッシュするとエラーになる箇所が多々あります。 Flash Player 6 以降では、eval 関数の代わりに配列アクセス演算子[ ] を使って文字列を変数などのターゲットパスに変換する書き方が一般的です。 また、新しいバージョンになってできること・新しい書き方も増えました。 考え方は今でも通用するものでも、このスクリプトの書き方は今時の Flash に合っていません。 #1のスクリプトもサンプルに合わせて eval 関数を使って書きましたが、この書き方は既に古いものである点をご了承の上で、ご参考になさってください。
その他の回答 (1)
- DPE
- ベストアンサー率85% (666/776)
各ブロックがそれぞれ耐久力を管理するパラメータを持ち、玉が当たった時にはそのブロック自身の耐久力を減らしていくことで、ブロックごとに違う硬さを表現できます。 次のように考えます。 ブロック全てに、耐久力を管理する変数を用意します。 この変数には予め、耐久力を表す数値を入れておきます。3回で壊れるブロックなら 3 、普通のブロックは1回で壊れるということですから 1 を入れます。 各ブロックが持っている変数は、インスタンスのターゲットパス.変数名 で中身を見ることができます。 玉が当たるたびに、玉が当たったブロックが持っている耐久力を減らしていきます。 ブロックが消える(壊れる)とは、耐久力がなくなる=耐久力が 0 になると考えることができます。 逆に、玉が当たった時に耐久力を減らしてなお耐久力が 0 にならなかったブロックは消えないということです。 そこで、サンプルでは「玉が当たったブロックは無条件で消滅」させていたのですが、ブロックを消滅させる時に条件を付けて「耐久力が 0 以下になった場合のみ消滅」に変更します。 このように変更すると、耐久力が高いブロックは耐久力が 0 になるまで何回か玉を当てないと消せなくなります。 これで、硬さの異なるブロックは完成です。 耐久力を管理する変数の名前をどのブロックでも統一しておくと、for ループでまとめて処理できます。 ********************************** 作り方の一例です。 硬いブロックのシンボルを作成します。色違い程度でよければ、「ライブラリ」パネルでシンボルを複製して色を塗り替えると簡単に作れます。 attachMovie を使って動的にブロックを配置する場合は、リンケージも設定してください。 シンボルの編集画面を開き、レイヤーを1つ追加します。 フレーム1にキーフレームを作り、次のようなスクリプトを書きます。 (↓以下のスクリプトは、各行頭に全角のスペースが入っています。コピーする際は、全てタブか半角のスペースに置き換えてください。このまま使うとシンタックスエラーになります) //ブロックの耐久力を保持 hp = 3; これで、このシンボルから作られたブロックのインスタンスは必ず” hp ”という名前の変数と同じ初期値を持つようになります。 硬いブロックだけを特別扱いすると何かと面倒なので、1回で壊れる普通のブロックにも同じ名前の変数を作り、耐久力のパラメータを持たせることにします。 普通のブロックのシンボルの編集画面を開き、レイヤーを追加してフレーム1に次のようなスクリプトを記述してください。 //ブロックの耐久力を保持 hp = 1; 普通のブロックも硬いブロックと同様に、全て” hp ”という名前の変数を持つようになります。 今回は扱いやすいところで、シンボルに直接記述して耐久力を決めています。 シンボル単位で耐久力が決まりますから、硬いブロックの耐久力はどれも 3 、普通のブロックは一律 1 です。 シンボルにではなくインスタンスごとに耐久力を設定すると、見た目は同じでも耐久力の違うブロックを作ることもできます。 次に、玉が当たりブロックが消える時の処理を、「耐久力を減らし、0 以下になったら消滅」するように変更します。 変更する箇所は、玉とブロックの当たり判定を取り、当たった時に行われる処理の一部です。サンプルでは玉のインスタンスに記述されています。 変更点のみ記載しますので、他の部分はご提示のサイトの解説を参考に作成してください。 /*****************************************************/ // 32個のブロックをfor文で処理する for ( i = 0 ; i < 32 ; i++ ) { // ブロックはすでに消えているので次のループへ if( flg[ i ] == 1 ) continue; // ボールとブロック block i 番目 が当たったとき if ( _root.ball.hitTest( eval( "_root.block" + i ) ) ) { /*----- この部分を変更 -----*/ //ブロックの耐久力を減らす eval( "_root.block" + i ).hp--; //0以下になったものは消滅 if( eval( "_root.block" + i ).hp <= 0 ) { // 消えた事をあらわすフラグ flg[ i ] = 1; // ブロックを非表示に eval( "_root.block" + i )._visible = false; } /*----- 変更ここまで -----*/ /*以下、ブロックに当たった時のボールの反射処理を書く*/ } } /*****************************************************/ 普通のブロックの代わりに硬いブロックを配置するなどして、動作を確認してみてください。 ちなみにブロックのシンボルは、ブロックの絵にダイナミックテキストのテキストフィールドを重ねて変数 hp の値を表示するように作ると、各ブロックの耐久力の変化が一目で分かるようになります。見た目は悪くなりますが、動作の確認には便利です。 ------------------------------------------------------------- かつて市販されたブロック崩しのゲームに、バーで打ち返す玉が文字通り2個になるというパワーアップがありました。 攻撃が純粋に2倍になるものの打ち返す頻度も2倍で忙しくなり、実はかえってミスしやすくなるのでは?と思わせるところが、このパワーアップのツボです。 これはこれで面白いのですが、今のサンプルに組み込むとなると難しいテーマです。 「玉が2つに増える」とは2個の玉を打ち返せるようになるのではなく、壊した時に玉のスペアがもらえる、いわゆる1アップのようなブロックのことではないでしょうか。 サンプルでは、玉を1回受け損なっただけで即刻ゲームオーバーになっていました。 玉のスペアがもらえるとすると、”スペアの玉がある限りゲームオーバーにならない”ということになります。 つまり、玉のスペアがもらえるブロックを作るなら、ゲームオーバーの判定の仕組みも変更しなければなりません。 次のように考えます。 変数を1つ作り、玉の残数を管理します。 玉が下端に来たらすぐにゲームオーバーにせず、まずは玉の残数を減らします。 減らした結果、残数が 0 以下になったらゲームオーバーです。これは、ブロックの耐久力を減らしていって 0 以下になったら消滅するのと同じ発想です。 1アップのブロックを壊した時は逆に、玉の残数を持っているこの変数の値を増やせばいいわけです。 ところで、スペアの玉があるということは、玉を落としても”今のブロックの配置のままやり直せる”ということでもありますよね。 ゲームオーバーになって最初からやり直すリプレイとは違い、”ミスするまでに壊したブロックは復活しない”点に注目してください。 これは基本的に、玉を落とした時に「ブロックは配置し直さないが、玉とバーを初期配置に戻す」ことで実現できます。 市販のゲームなどではミスの時やミスからの復帰の際に演出・効果音などが入るところですが、今回はそこまで考えません。 ********************************** 普通のブロックと硬いブロックの違いは、耐久力の数値の違いだけでした。 スペアの玉がもらえるブロックも玉を当てると壊れる点は同じなので耐久力のパラメータを設けますが、これとは別に、壊しても何も起こらない先の2つとは違い、”壊すと何かが起きる”という性質を持っています。 この違いを見分けられるようにするために、各ブロックに耐久力の他にもう1つ、種類のパラメータを持たせることにしましょう。 耐久力のパラメータ=変数 hp と同じ要領で、各シンボルのフレーム1に同じ名前の変数を設定します。 この変数の値を、壊しても何も起こらないブロック= 0 、壊すと何かが起きるブロック= 1 というように決めておきます。 すると、ブロックが消滅する際にこの変数の値を見ることで、壊れるだけで何も起こらないのか、それとも何かが起きるのかを判別できるようになります。 壊すと玉のスペアがもらえるブロックの効果は、壊した時に玉の残数が加算される、というものです。 つまり、消滅するブロックが持っているこの変数に 1 が入っていた場合=消滅するブロックが1アップのブロックだった時に、玉の残数を加算すればいいわけです。 ********************************** 作り方の一例です。 1アップのブロックのシンボルを作成します。 このシンボルのタイムラインのフレーム1に、耐久力を管理する変数 hp を作るスクリプトを記述します。記述方法は、普通 / 硬いブロックのシンボルの時と同じです。 このスクリプトに続けて、ブロックの種類を表す変数を設定します。 ここでは仮にこの変数の名前を block_type とし、値は、何も起こらないブロック= 0 、何か起こるブロック= 1 と決めます。 合わせますと、1アップのブロックのシンボルのフレーム1に書くスクリプトは次のようになります。耐久力は適度な値に決めてください。 /*****************************************************/ //ブロックの耐久力を保持 hp = 5; //ブロックのタイプを保持 //0:壊しても何も起こらない //1:玉の残数が1up block_type = 1; /*****************************************************/ 普通および硬いブロックのシンボルのフレーム1のスクリプトにも同様に、ブロックの種類を表す変数 block_type を追加してください。 これらは壊しても何も起こらないブロックなので、block_type = 0; にします。 なお、このように種類などを数値で管理する変数の場合は特に、後から見て「この数字はどういう意味だったかな?」とならないように、コメントを入れてメモを残しておくといいでしょう。 スクリプトの変更点は次の3箇所です。 1) 玉の残数を管理する変数を作る 2) 玉が下端に来た時の処理: ・玉の残数を減らし、0 以下になった時だけゲームオーバー ・玉が残っている場合は玉とバーを初期状態に戻す 3) ブロックが消える時、1アップのブロック( block_type の値が 1 )だった場合は玉の残数を加算 スクリプトの変更例です。 1) 玉の onClipEvent(load) の中に次のスクリプトを追加 //玉の残数 _root.balls = 3; 2) 玉が下端に来た時の処理を、次のように変更 // 下端に来たとき(ミス&ゲームオーバー判定) if ( _y > 250 + 5 ) { //玉の残数を減らす _root.balls--; //残数が0以下になったらゲームオーバー if( _root.balls <= 0 ) { // ブロックを破棄 for( i = 0 ; i < 32 ; i++ ) { eval("_root.block"+i).removeMovieClip ( ); } //ゲームオーバー画面を表示 _root.gotoAndStop("2"); } else { //残数がある時は玉とバーを初期状態に戻す //玉の位置と移動量をリセット _x = 100; _y = 220; dx = 1; dy = -3; //バーの位置をリセット _root.bar._x = 100; _root.bar._y = 230; } } 3) ブロックを消滅させる部分(ブロックを非表示にする処理の次)に、次のスクリプトを追加 //1upブロックだった時は玉の残数を増やす if( eval( "_root.block" + i ).block_type == 1 ) { _root.balls++; } ↑ _root.balls++; の次に if 文で条件を付けると、1アップのブロックをたくさん壊してもスペアの玉はある一定の数までしか持てないといった制限を加えることもできます。 ブロックの配置に1アップのブロックを加えて、プレビューしてみてください。 ミス(玉を下端に落とす)しても、玉の残数が 0 にならない限りゲームオーバーにはなりません。 ステージにダイナミックテキストのテキストフィールドを作って変数 balls の値を表示すると、玉の残数の変化も同時に確認できます。 今回の作例ではミスから復帰する時に演出や間がなく、玉とバーが初期状態に強制的に戻されていきなりゲームが再開してしまいます。 普通の人ならまず面くらうでしょうし、呆けているうちに復帰したそばからまたミスになった・・・なんてこともありえますから、「なんてつまらないゲームなんだ!」と怒る人も出てくるかもしれません。 Flash や ActionScript に慣れてきたら、このあたりも改良してみてください。 ------------------------------------------------------------- 市販されているブロック崩しは、絶対に壊せないブロック・壊すとアイテムが落ちてくるブロック(アイテムをバーで受け止めるとパワーアップ)・玉を当ててボスキャラを撃破する・ステージごとにユニーク / 崩すのが難しいブロックの配置・・・など、プレイヤーを飽きさせない様々な工夫が凝らされています。 ブロック崩し自体は単純なルールですが、単純だからこそ、遊びとしてもスクリプトの教材としても逸材なのです。 市販品のレベルまで作り込む必要はないにしても、不満な点は改良して面白い作品にしていってください。
補足
大変解りやすい丁寧な回答ありがとうございます。 早速やってみましたがブロック耐久力は書かれてた通りにしたつもりですがどこかがおかしいようで一回で消えてしまいます。もう少しがんばってみますがだめだったらまた質問させてください。 あと「玉が二つに増えるのは最初に書かれてた打ち返す玉が二つになるということなんですがやっぱり無理ですかね? はじめからある玉のシンボルを複製した玉を、「消すと二つに増える用のブロック」の下に隠しておいてそのブロックが消えたら動き出すというのはできないでしょうか? すいませんが良い案があればおねがいします。
お礼
返信がおそくなりすいません。 いろいろ丁寧にありがとうございます。 まだ試せてないのですが教わった通りに頑張ってみます。 またつまずいた時にはよろしくお願いします。