ページ 11

【解決済み】シューティングゲームの作成

Posted: 2023年6月27日(火) 22:47
by ppp
シューティングゲームを作っているのですが、遮蔽物(shield)が認識されずに、弾が消滅しません
弾はイベント動的生成プラグインとテンプレートイベントプラグインで生成。
shieldはマップにランダムで配置。画面は縦にループするようになっています。
分かっていること
・イベント名はshieldになっている
・シールド自体に同じ以下のコードを入力した場合、ちゃんとshield判定されている
↓弾のテンプレートイベントの内容
◆ループ
◆条件分岐:スクリプト:$gameMap.eventsXy(this.character(0).x, this.character(0).y)
◆スクリプト:let evtObj = $gameMap.eventsXy(this.character(0).x, this.character(0).y);
:     :for(let i = 0; i < evtObj.length; i++) {
:     : if($dataMap.events[evtObj._eventId] !== undefined){
:     : let event = $dataMap.events[evtObj._eventId];
:     : if(event.name !== undefined && event.name === 'shield'){
:     : let key = [this._mapId, this._eventId, "A"];
:     : $gameSelfSwitches.setValue(key, true);
:     : break;
:     : }
:     : }
:     :}

:分岐終了
◆条件分岐:セルフスイッチ AがON
◆セルフスイッチの操作:A = OFF
◆移動ルートの設定:このイベント (ウェイト)
:        :◇透明化ON
:        :◇ウェイト:10フレーム
:        :◇透明化OFF
:        :◇ウェイト:10フレーム
:        :◇透明化ON
:        :◇ウェイト:10フレーム
:        :◇透明化OFF
:        :◇ウェイト:10フレーム
:        :◇透明化ON
:        :◇ウェイト:10フレーム
:        :◇透明化OFF
:        :◇ウェイト:10フレーム
:        :◇透明化ON
:        :◇ウェイト:10フレーム
:        :◇透明化OFF
:        :◇ウェイト:10フレーム
:        :◇透明化ON
◆イベントの一時消去
◆ループの中断

:分岐終了
◆プラグインコマンド:TE_SET_SELF_VARIABLE 1 1 1
◆条件分岐:スクリプト:this.getSelfVariable(1) <= 60
◆条件分岐:スクリプト:this.character(0).x == this.character(-1).x && this.character(0).y == this.character(-1).y
◆条件分岐:プレイヤー無敵時間がOFF
◆条件分岐:階段移動後無敵時間がOFF
◆条件分岐:移動中がOFF
◆スイッチの操作:#0001 プレイヤー無敵時間 = ON
◆変数の操作:#0001 ホーミング中の敵のID = 弾を撃った敵のID
◆スクリプト:let atk = $gameVariables.value(16);
:     :let def = $gameActors.actor(1).param(3);
:     :let dmg = atk - def;
:     :dmg = dmg < 0 ? 0 : dmg;
:     :this.changeHp($gameActors.actor(1), -dmg, true);
◆SEの演奏:zipper (90, 100, 0)
◆画面のシェイク:5, 9, 20フレーム
◆コモンイベント:全滅するかしないか
◆イベントの一時消去
◆ループの中断

:分岐終了

:分岐終了

:分岐終了

:分岐終了

:それ以外のとき
◆イベントの一時消去
◆ループの中断

:分岐終了
◆ウェイト:1フレーム

:以上繰り返し

Re: シューティングゲームの作成

Posted: 2023年6月28日(水) 10:02
by Plasma Dark
イベントコマンドのスクリプトにあまり複雑なコードを書かないほうが良いかと思われます。
VSCodeなどのシンタックスハイライトの効くエディタでプラグインを書き、その中でプラグインコマンドを定義して使うことも検討してみてください。

イベントコマンドやコードを提示する場合、それの意図を付記していただけると、回答者に優しくなります。
現状だとイベントやコードの意図を書き込み内の他の情報から推測する他なく、意図通りに読み手に伝わらないおそれがあります。
また、イベントの動的生成やテンプレートイベントは少なからずイベント周りのスクリプトに影響を与えるので、利用されているバージョンも明記したほうが良いです。

さて、弾が shield という名前のイベントに重なったときにどんな挙動をさせたいかを、推測してみます。

現状を見る限り、

弾が shield に重なった場合に弾自身のセルフスイッチAをONにする。弾のセルフスイッチAがONなら弾が点滅して消滅。
消滅してない場合にセルフ変数1(弾が出現してからのフレーム数?)を1加算して、60以内ならプレイヤーとの衝突判定、60より大なら弾を消滅させる。

と読み取れますが、あっているでしょうか。

まず確認すべきことは、イベントのトリガーです。
意図としてはおそらく並列実行になっているべきなのだと思います。意図通り並列実行なら次の確認に行きます。

shieldにぶつかっても消えない、ということはおそらく前半のスクリプトに問題があるのでしょう。

先頭の条件分岐に書かれたスクリプトは現状、意味がありません。空配列は真と判定されるので、常に条件を満たします。
最終的には消してしまって良いと思いますが、まずは確認のため、こうしてみましょう。

コード: 全て選択

$gameMap.eventsXy(this.character(0).x, this.character(0).y).length > 0
弾とshieldが重なったときに、本当にこの条件を満たすかどうかを確認してみてください。
console.logでログを吐いても良いですし、エディタ上で分岐しているので、イベントコマンドのメッセージの表示やSEの再生を使っても良いと思います。
この条件式の結果が真にならない場合、弾イベントと重なるイベント一覧がそもそも取れていないことになるので厄介です。
this.character(0)がちゃんと弾イベントを返してくれているかどうかとか、そういうところを見ることになります。(おそらくここは問題ないはずですが……)
真になるのであれば、その後のスクリプトに問題があります。

自身のセルフスイッチの操作は必ずしもスクリプト内でやる必要はなさそうです。
重なっているイベントの中に shield という名前のイベントがあるかどうかを調べるコードはこのように書けます。

コード: 全て選択

$gameMap
  .eventsXy(this.character(0).x, this.character(0).y)
  .some(gameEvent => gameEvent.event() && gameEvent.event().name === 'shield')
(アロー関数式を使用しているためMV1.5系では動作しません。その場合は適宜function式に置き換えてください)

見やすさのために改行していますが、イベントコマンドの条件分岐に直接入力する場合は改行を消してください。
これが意図通り、shieldに重なったタイミングで真になるかどうかを確認して、真になるのであればそこでセルフスイッチを操作してあげれば解決しそうです。

コード: 全て選択

◆条件分岐:スクリプト:$gameMap.eventsXy(this.character(0).x, this.character(0).y).some(gameEvent => gameEvent.event() && gameEvent.event().name === 'shield')
  ◆セルフスイッチの操作:A = ON
  ◆
:分岐終了

Re: シューティングゲームの作成

Posted: 2023年6月28日(水) 10:10
by Plasma Dark
確認のための弾イベントをまとめるとこんな感じです。
セルフスイッチAがONかどうか確認する条件分岐以降は省略しています。
それより上部分(スクリプトで書かれていた部分)だけ差し替えて実行してみてください。

コード: 全て選択

◆条件分岐:スクリプト:$gameMap.eventsXy(this.character(0).x, this.character(0).y).length > 0
  ◆注釈:確認対象1: 弾と重なっているイベントが存在するかどうか
  ◆文章:なし, ウィンドウ, 下
  :  :このメッセージが表示されたら存在する。
  :  :SEの再生やconsole.logで確認しても良い。
  ◆条件分岐:スクリプト:$gameMap.eventsXy(this.character(0).x, this.character(0).y).some(gameEvent => gameEvent.event() && gameEvent.event().name === 'shield')
    ◆注釈:確認対象2: 重なっているイベントの中にshieldがあるか
    :  :あるならセルフスイッチAをONにする
    ◆セルフスイッチの操作:A = ON
    ◆
  :分岐終了
  ◆
:分岐終了
◆条件分岐:セルフスイッチ AがON
  ◆注釈:以下省略
  ◆
:分岐終了

Re: シューティングゲームの作成

Posted: 2023年6月28日(水) 11:00
by ppp
回答ありがとうございます!プログラムのコードの意図は回答者様のおっしゃるとおりです。
当たり判定はある(メッセージは表示される)のですが、弾が消滅しません。
ツクールのver.は1.6.2
TemplateEvent.jsはver.2.1.5
EventReSpawn.jsはver.1.12.2です

追記:遮蔽物をランダムに配置しているのですが(乱数でsetPositionを使う)
遮蔽物のランダム移動させないでみると、弾がちゃんと消滅します。初期では、遮蔽物は端によせて配置しています。

Re: 【解決済み】シューティングゲームの作成

Posted: 2023年6月28日(水) 12:38
by ppp
半歩移動プラグインをオフにすれば直りました!

Re: 【解決済み】シューティングゲームの作成

Posted: 2023年6月28日(水) 13:33
by Plasma Dark
当たり判定はある(メッセージは表示される)のですが、弾が消滅しません。
追記:遮蔽物をランダムに配置しているのですが(乱数でsetPositionを使う)
遮蔽物のランダム移動させないでみると、弾がちゃんと消滅します。
半歩移動プラグインをオフにすれば直りました!
この情報から考えるに、余計な条件分岐が原因ではないかと思われます。

コード: 全て選択

$gameMap.eventsXy(this.character(0).x, this.character(0).y).length > 0
この条件式を評価する時点ではshieldと重なっているが、次のフレームになって重なっている対象のイベント一覧を探すタイミングでは、もうshieldが重なっていないのでしょう。
半歩移動では重なり判定のチェックが厳しくなるため、半歩移動プラグインをオフにすると正常に弾が消えるのだと思われます。

コード: 全て選択

◆条件分岐:スクリプト:$gameMap.eventsXy(this.character(0).x, this.character(0).y).length > 0
この分岐を消してしまえば解決しそうです。

Re: 【解決済み】シューティングゲームの作成

Posted: 2023年8月06日(日) 07:54
by ppp
遅くなってすみません。おかげさまで完成しました!