RPGの戦闘について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
red

RPGの戦闘について

#1

投稿記事 by red » 14年前

現在、ターン制の戦闘のRPGを作っているんですが、
2対1や2対2などの戦闘になったときの順番に攻撃するプログラムの作り方がわかりません。
どうすればいいのでしょうか?○対○のすべてのパターンについて分けて考えなければいけないのでしょうか?

red

Re: RPGの戦闘について

#2

投稿記事 by red » 14年前

書き忘れていましたが、
開発環境:VisualC++2010
開発言語:C言語
です。

アバター
h2so5
副管理人
記事: 2212
登録日時: 14年前
住所: 東京
連絡を取る:

Re: RPGの戦闘について

#3

投稿記事 by h2so5 » 14年前

敵や味方のキャラクタの情報をどのように管理しているかや、
攻撃をどのように実装しているかによると思います。

つまり、それだけの情報では答えられません。

red

Re: RPGの戦闘について

#4

投稿記事 by red » 14年前

すいません、情報が少なすぎました・・・。

まず、主人公のデータは構造体、敵のデータは構造体配列で管理しています。
画面の切り替えはWinMain関数の中のswitchの変数によってマップ画面や、戦闘画面の関数を呼び出しています。
そして、マップ画面でGetRandを使い何分の一の確率でswitchの変数に戦闘画面の関数を呼び出す値を代入しています。また、その際、さらにGetRandを使いその値を戦闘画面の関数の引数で渡し、その引数と同じ配列番号の敵を出現させるようにしています。
戦闘画面の関数では、まず、敵のデータを初期化し、whileループの中でswitchを使いコマンド入力→(素早さが早い順に)戦闘エフェクトとダメージ計算→コマンド入力というような感じにしたいと思っています。

ここでわからないのが(素早さが早い順に)戦闘エフェクトとダメージ計算という部分です。敵によって素早さが違うし、敵の出現数もばらばらにしたいので、いろいろなパターンが出てきてしまうのでどうすればいいのかと・・・。

アバター
h2so5
副管理人
記事: 2212
登録日時: 14年前
住所: 東京
連絡を取る:

Re: RPGの戦闘について

#5

投稿記事 by h2so5 » 14年前

データ構造が良くわからないのですが、こういった感じでしょうか?(ツクール風)

コード:

struct player{		//プレイヤーの単体データ
	// HP,MP,etc..
};

struct enemy{				//敵の単体データ
	// HP,MP,etc..
};

struct enemy_troop{			//敵グループのデータ
	struct enemy list[10];
};

//戦闘関数内

struct player player_list[10];         //プレイヤーの配列
struct enemy_troop troop;           //エンカウントした敵グループ


このような構造であれば、
戦闘関数内で敵のデータが入った配列を(この例だとtroop.list)
素早さで降順でソートして、先頭から順に戦闘をさせるという方法があります。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: RPGの戦闘について

#6

投稿記事 by softya(ソフト屋) » 14年前

>ここでわからないのが(素早さが早い順に)戦闘エフェクトとダメージ計算という部分です。敵によって素早さが違うし、敵の出現数もばらばらにしたいので、いろいろなパターンが出てきてしまうのでどうすればいいのかと・・・。

ここだけの部分を取り上げるとソート方法が分からないと言う印象を受けますが違うのでしょうか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

red

Re: RPGの戦闘について

#7

投稿記事 by red » 14年前

すいません、ソートという言葉を初めて聞きました・・・。

しかし、そのような方法は、敵の出現数が変化した場合も使えるんですか?

アバター
h2so5
副管理人
記事: 2212
登録日時: 14年前
住所: 東京
連絡を取る:

Re: RPGの戦闘について

#8

投稿記事 by h2so5 » 14年前

red さんが書きました: しかし、そのような方法は、敵の出現数が変化した場合も使えるんですか?
もちろん、使えますよ。
よほど特殊なデータ管理の方法をしていなければ。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: RPGの戦闘について

#9

投稿記事 by softya(ソフト屋) » 14年前

ソートとは、ある値(この場合素早さ)の順番に並べ替えることです。
可変個数のソートはもちろん可能ですよ。

ゲームや様々なプログラムを組む場合は、アルゴリズムを知っていると楽が出来たのに!って事がたくさん出てきます。

参考
「アルゴリズムとデータ構造編 トップページ」
http://www.geocities.jp/ky_webid/algorithm/index.html

今回の場合、素早さをソートキーにして味方と敵の区分・味方と敵の番号を構造体にまとめて、その構造体配列をソートすれば行動順番を決めるテーブルが出来ますよ。
参考にテーブルの構造と宣言。ソートは自分で考えてみてください。

コード:

struct tag_SortSentou {
 int subayasa; ← 素早さ値(装備などの補正済み)
 int mikataFlag; ← 敵味方の区分フラグ
 int bangou; ← 敵味方の管理番号
};

#define MIKATA_TEKI_MAX 40 ← 敵味方の予定される最大数
struct tag_SortSentou sortSentou[MIKATA_TEKI_MAX]; ← ここに値を入れてソートする。
int mikata_teki_nums; ← 味方と敵の今回の戦闘参加数。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

red

Re: RPGの戦闘について

#10

投稿記事 by red » 14年前

h2so5さん、softya(ソフト屋)さん、アドバイスありがとうございました。
もう一度じっくり考えてみたいと思います。

アバター
MoNoQLoREATOR
記事: 284
登録日時: 14年前
住所: 東京

Re: RPGの戦闘について

#11

投稿記事 by MoNoQLoREATOR » 14年前

まず方針として、
①各キャラクターにゲージを持たせ、ゲージの値を各々のすばやさで初期化しておきます。
②ゲージを1ずつ増やしていき、ゲージが一定数(今回の例なら100)を超えたら攻撃するようにします。
③全員が攻撃したら初期化します。
というようにします。
※同時の場合インデックス番号が早いほうが先になります。また、今回の例なら味方より敵の方が先になります。


~以下詳しい説明&重要な部分のソースコード~

敵の最大出現数を TEKI_MAX

とします。
それと、

struct KOUZOUTAI{
int being; //生きている場合1を、そうでない場合0を代入することとする
int subayasa; //すばやさを代入することとする
int gauge; //ゲージ(ゲージが一定数を超えると攻撃)
}party[PARTY_MAX], teki[TEKI_MAX];//変数宣言

を宣言しておきます。
あらかじめ

int party_kazu = パーティーの現在の人数;
for(int i=0;i<party_kazu;i++){
party.being = 1;
party.gauge = party.subayasa;
}

int teki_kazu = GetRand(TEKI_MAX-1)+1 //敵の数を決める
for(int i=0;i<teki_kazu;i++){
teki.being = 1;
teki.gauge = party.subayasa;
}

としておきます。

.attackの値の意味・・・ 0→未攻撃 1→攻撃中 2→攻撃済み

コード:

	//自動変数宣言 ※グローバルじゃないです
int hantei = 1;	// 1・・・全員攻撃済み 0・・・少なくとも一体は未攻撃
int trigger = 0;	//ゲージが溜まるのが同時の際に他のキャラに攻撃させないため


//最低1体が攻撃態勢になるまでゲージの処理をする
while(flagg==0){
	for(int i=0;i<teki_kazu;i++){
		//敵が生きている&ゲージが溜まる&敵が攻撃済みでない ならば
		if(teki[i].being==1 && teki[i].gauge+=1 >= 100 && teki[i].attack != 2){
			teki[i].attack = 1;	//敵の状態を攻撃態勢にする
			flagg = 1;		//whileループから脱出するようにする
		}
	}
	
	for(int i=0;i<party_kazu;i++){
		//味方が生きている&ゲージが溜まる&味方が攻撃済みでない ならば
		if(party[i].being==1 && party[i].gauge+=1 >= 100 && party[i].attack != 2){
			party[i].attack = 1;	//味方の状態を攻撃態勢にする
			flagg = 1;		//whileループから脱出するようにする
		}
	}
}

for(int i=0;i<teki_kazu;i++){
	if(teki[i].attack==1 && teki[i].being==1){
		TekiAttack();//味方の攻撃関数を呼び出す
		//処理が完了したら flagg = 0; としてwhileループに入るようにしてください
		//また、attack = 2; として、状態を攻撃済みにしてください
		
		trigger = 1;//トリガーを作動させる(同時の際に他に攻撃させないため)
		break;	//forループから脱出
	}
}
if(trigger==0){
	for(int i=0;i<party_kazu;i++){
		if(party[i].attack==1 && party[i].being==1){
			PartyAttack();//味方の攻撃関数を呼び出す
			//処理が完了したら flagg = 0; としてwhileループに入るようにしてください
			//また、attack = 2; として、状態を攻撃済みにしてください
			
			break;	//forループから脱出
		}
	}
}

	//↓全員攻撃し終わったらゲージをリセットする↓
for(int i=0;i<teki_kazu;i++){
	//敵の中に、生きていて攻撃していない者がいる ならば
	if(teki[i].attack!=1 && teki[i].being==1) hantei = 0;//リセットしない
}
for(int i=0;i<party_kazu;i++){
	//味方の中に、生きていて攻撃していない者がいる ならば
	if(party[i].attack!=1 && party[i].being==1) hantei = 0;//リセットしない
}
if(hantei==1) ResetTheGauge();	//ゲージをリセットする関数を呼ぶ(書くのめんどくさい)
	//↑全員攻撃し終わったらゲージをリセットする↑
これを無限ループすればできるはずです。
なお、攻撃関数を呼んだとき、仲間や敵が死んだらそのbeingを0にしてください。


実際にプログラムを実行したりとかはしていません。コンパイルもしていません。
だからコンパイルエラーが出るかもしれません。その場合は御自分で直してください。
また、正しく動かないかもしれません。その場合は臨機応変にがんばってみてください。

応援してます。
最後に編集したユーザー MoNoQLoREATOR on 2011年2月15日(火) 00:54 [ 編集 2 回目 ]

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

Re: RPGの戦闘について

#12

投稿記事 by softya(ソフト屋) » 14年前

>>MoNoQLoREATORさん。

少しテクニックに走っているので初心者さんには分かりづらいかも。
・beingを生きているフラグと加算値で兼用している点。
・attackフラグの数値の意味が不明確。2の値の意味は?
・party.attackの変化が1の代入しかコードにない。
あと、フラグを1にする部分と「TekiAttack(); //敵の攻撃関数を呼び出す」を分ける必要が無いのでは?

[追記]
念の為に書いておきますが、MoNoQLoREATORさんの回答が唯一の方法ではありません。
ソートもひとつの方法ですし、最大値を探して最大のものから一つづつ処理す方法もあります。
ツリー構造にして、ツリー構造を作るときに自動的に順番を決定することも出来ます。
アルゴリズムの組み合わせで色々方法があるとご理解下さい。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
MoNoQLoREATOR
記事: 284
登録日時: 14年前
住所: 東京

Re: RPGの戦闘について

#13

投稿記事 by MoNoQLoREATOR » 14年前

修正しました。


>>・party.attackの変化が1の代入しかコードにない。
ほんとうですね。書き忘れました。

フラグと攻撃関数呼び出しを分ける必要はないですね。
attackの値の2は「攻撃済み」を意味していました。
フラグと攻撃関数の呼び出しを分けないようにしたので、現在は1が「攻撃済み」を意味します。

アバター
MoNoQLoREATOR
記事: 284
登録日時: 14年前
住所: 東京

Re: RPGの戦闘について

#14

投稿記事 by MoNoQLoREATOR » 14年前

欠陥をみつけてしまったのでこっそり修正してきました。
攻撃エフェクトをアニメーションさせたいときは何度も攻撃関数を呼んだほうが良いのでそのやり方に対応させました。

閉鎖

“C言語何でも質問掲示板” へ戻る