NaGu-Ru開発もいよいよ大詰め(ほんとか?)に入ってきました。
しかし、「敵がアホ」、具体的には単発攻撃しかしないので、
妙によわっちいし面白くもないということで、連続攻撃をさせることにしました。
いわゆる「こんぼ」ってやつですかね。
(実は、今までのNaGu-Ruで「敵が強い」というのは
「攻撃間隔が短い」とかそんな単純なことだったりする.....) 「コンボ」の考え方は非常に簡単です。 攻撃の一つ一つをつなげていったものがコンボなんですから。 つまり、攻撃ひとつをしおえたら、次の攻撃を行う。 たった。これだけなんですよね。 たいてい、攻撃が終わる、というのはアニメーションが終わる、ってことなので アニメーションが終わったときに、つづけて攻撃するようにしていけばいいだけです。 さて、プログラムを組むことになりますが、 コンボの長さが固定ではおもしろくないし、制限が出てきますね。 そういうわけで、長短さまざまなコンボを実現するために、TListを使うことにしました。 これに好きな数だけコンボデータ配列をぶち込んでやるわけです。 で、敵キャラクタはアニメーション終了時にそのコンボデータを読み取ったものから順番に消していき、 コンボデータがなくなったらコンボ終了、というわけです。 ちょっとした擬似的なコードを書いてみます。 var ComoboDataList:TList; //コンボデータをセットする procedure SetCombo(data:array of TComboData); var i:Integer; comboData:PComboData; begin //引数dataの全データをリストに追加する for i:= Low(dat) to High(data) do begin New(comboData); //メモリを確保 comboData^:=data[i]; //データをゲット ComboDataList.Add(comboData); //データをリストに追加 end; end; //アニメーション終了時に呼び出される関数 procedure OnAnimationLoop; var comboData:PComboData; newdata:PComboData; begin if comboDataList.Count = 0 then Exit; //コンボデータがなくなったら何もしない comboData:=ComboDataList[0]; //先頭のコンボデータをゲット ComboDataList.Delete(0); //んでリストから削除 Dispose(combData); //メモリ開放 if comboDataList.Count = 0 then Exit; //コンボデータがなくなったら何もしない newData:=ComboDataList[0]; //次のコンボデータをゲット end;こんな感じになると思います。 ポインタとか、メモリの確保とかが絡んでいるのでわかりにくいかも しれませんが、やっていることは非常に単純です。アルゴリズムさえわかっていれば それなりに読めると思います。 それと、上記の「SetCombo」手続きで使われている、 「配列を関数に渡し、それをすべて読み込む方法」はこれ以外の場でも 多く流用できると思いますので、参考にしていただければ幸いです。 さて、実際に僕が作っているゲームでうまくいくかどうかを試してみたところ、 うまくいきました。そこで、調子に乗ってコンボデータを作っていろんなコンボを試していたら、 ある問題に遭遇しました。 どんな問題かというと、途中に攻撃以外のものをはさめないということです。 たとえば、NaGu-Ruの基本的なコンボとして、パンチX2、キックキックで敵を浮かして そこでジャンプして叩き落す、というのがあるんですが、このジャンプが問題なんです。 現在はアニメーション終了時に次のアニメーションをセットする、方法でコンボを実現していますが、 この方法だと、ジャンプは着地するまでアニメーションが続くために、着地後に 技を繰り出す、という変なものになってしまいます。つまり、ちょっとこったことをしようとすると アニメーション終了時に次のアニメーションをセットする方法では都合が悪いんです。 というか、悪かったんですよ。
というわけで、これを以下のように修正しました。 ちょっと文章で書くとわけわかんないので、コードを書いてみます。 //コンボの状態を管理する procedure TEnemy.CheckComboState; begin //コンボデータがなければだめ if ComboList.Count = 0 then Exit; //攻撃中なら次の動作に移らない if Attacking then Exit; //プレーヤーに攻撃が当たるかをチェックする if (NextIsAttacking)AND(not TryDstCheck) then begin //ミスカウントが0のときに、ミスった時間をとっておく if FMissCnt = 0 then FMissTime:=FrameTM; Inc(FMissCnt); Exit; end; //次のコンボデータを読み込む ComboList.DelData(0); if ComboList.Count = 0 then Exit; //ミスったときから1秒以上ならコンボ失敗なのでコンボデータをクリアする if (FMissCnt > 0)AND(FrameTM - FMissTime > 1000) then begin ComboList.ClearAll; end else begin //それ以外ならコンボを続ける doAction(ComboList.Data[0]); FMissCnt:=0; end; end;スパゲッティであるNaGu-Ruのコードの中でかなりきれいなほうです。 多分読めると思います...(たぶんね)。上の条件に加えて「コンボミス」を判定して よりそれっぽくしてます。これで、敵が普通にコンボをかましてくれるようになりました(^^;) もうこれで、思考ルーチンがへぼいなんていわせないぜ!!(<まだへぼいやん) さぁ、みんなもれっつれっとこんぼ!!
|
※敵がアホ 安いゲームにありがちな「強い=反応速度が速い」という方程式の元 ゲームが作られていたためにおこった現象。格闘ゲームでこれをやると、 かなり面白くないものになる。幸いNaGu-Ruは複数の敵と戦うので、 ある程度ごまかしが効いていたのだ。
※アニメーション
※擬似的なコード
※ポインタ
※アルゴリズム
※TList
※High,Low関数
※リスト
※うまくいくかどうか
※都合が悪い
※コンボデータ
※ジャンプ
※フラグ
※FrameTM
※NextIsAttacking
※クリア
※スパゲッティ
※思考ルーチン
|