アクションゲームでプレイヤーの後を自動的についてくるキャラクター

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

アクションゲームでプレイヤーの後を自動的についてくるキャラクター

#1

投稿記事 by Wirelessりちみ » 14年前

現在、マリオブラザーズのような画面の横スクロールアクションゲームを作っています。
主人公が増殖してプレイヤーの後をついてくるというようなものなのですが、(カービィのヘルパーのような)
自動的にプレイヤーの後をついてくるキャラクターの処理がうまくいきません。
まずはプレイヤーと同じような地形との判定処理を作って、
それの前に、そのキャラクターの移動判断処理を書いています。

自分で作ってみた移動判断処理をまず箇条書きで書きますと、
(地面での処理)
・地面にいるときにプレイヤーから一定距離 左に離れたらプレイヤーに近づいて右に歩く
・地面にいるときにプレイヤーから一定距離 右に離れたらプレイヤーに近づいて左に歩く
・右に歩いているときに自分の1マス右に障害物があったらジャンプする
・左に歩いているときに自分の1マス左に障害物があったらジャンプする
・右に歩いているときに自分の1マス右の列の一番下のマスが穴だったらジャンプする
・左に歩いているときに自分の1マス左の列の一番下のマスが穴だったらジャンプする
・プレイヤーの近く一定距離まで来たら移動をやめる
(空中での処理)
・1回のジャンプで必ず1マス分はプレイヤーの方向に動かす(踏み外しは除く)
・踏み外した場合は着地まで動かない(穴の場合はジャンプしているはずなので確実に着地する)
・空中で自分の下に地面がなかったらあるところまでプレイヤーの方向に動く
・ジャンプして1マス以上動いてから自分の下に地面があったら移動をやめる

というものなのですが、
簡単なマップならこれでうまくついてきてくれるのですが、これだと分かれ道等はプレイヤーの方向を無視してしまいますし、
縦に進むマップなんて作れなくなってしまいます。
うまくついてきてくれる他の処理や、何か他に良い方法はないのでしょうか?

プレイヤーについてくるキャラのコードです
Zousyoku.cpp

コード:

#include "DxLib.h"
#include "Keyboard.h"
#include "Player.h"
#include "Map.h"
#include "Zousyoku.h"

extern int CameraX;	//現在座標から表示座標への変換用
int Enter;			//Enterが1になると一人増えて0に戻る
Zousyoku_t Zousyoku[99];	//最大99人まで増殖

//マップ地形参照マクロ
#define MAP_CHIP(y,x) (MapData.Map[(y)*(MapData.Width)+(x)])


// 初期化をする
void Zousyoku_Initialize(){
	
	Enter=0;

	for (int i = 0; i < 99; ++i) //99人分の初期化
	{
		LoadDivGraph( "Image/Chara/Player1.png" , 16 , 4 , 4 , 32 , 32 , Zousyoku[i].DivImage );//画像の分割読み込み
		Zousyoku[i].Flag = 0;	//存在フラグ0
		Zousyoku[i].Image = Zousyoku[i].DivImage[4];	//プレイヤーの最初の画像
		Zousyoku[i].X     = 0;	//初期X
		Zousyoku[i].Y     = 0;	//初期Y
		Zousyoku[i].Walk=0;		//歩いていない
		Zousyoku[i].Muki=1;		//向きが右
		Zousyoku[i].WalkCount=0;//歩きカウント0
		Zousyoku[i].Speed=0;	//スピード0
		Zousyoku[i].Accel=0.5;	//加速度0.5
		Zousyoku[i].Jump=0;		//ジャンプしていない
		Zousyoku[i].JumpPower=0;	//ジャンプ力0
		Zousyoku[i].JumpAccel=0.5;	//重力0.5

		//CPUの判断で増える入力カウント(プレイヤーでいうボタン入力)
		Zousyoku[i].RIGHTcount=0;
		Zousyoku[i].LEFTcount=0;
		Zousyoku[i].Acount=0;
		Zousyoku[i].Bcount=0;

		Zousyoku[i].Count20=0;		//きっちり1マス歩かせるときに使う20フレームカウント
		Zousyoku[i].JumpMuki=0;		//0:左に向かってジャンプしている 1:右に向かってジャンプしている
		Zousyoku[i].Humihazusi=0;	//現在のジャンプ状態はは自発ジャンプなのか踏み外しなのか
	}

}




// 増殖キャラの動きを計算する
void Zousyoku_Move(Player_t *Player){

	//Enterが1になると一人増えて0になる
	if(Enter==1){
		for(int i = 0; i < 99; i++)
		{
			if(Zousyoku[i].Flag == 0)
			{
				//1人の存在フラグを1に
				Zousyoku[i].Flag = 1;
				//初期位置設定
				Zousyoku[i].X = Player->X;
				Zousyoku[i].Y = Player->Y;
				//プレイヤーとの距離が全員一定にならないようにランダム値を出す
				Zousyoku[i].Random = GetRand( 128 );

				break;
			}
			Enter = 0;
		}
	}

	for(int i = 0; i < 99; i++)
	{
		//現在座標から表示座標への変換
		Zousyoku[i].ViewX = Zousyoku[i].X-CameraX;

		//存在フラグが1のキャラ全員の処理
		if(Zousyoku[i].Flag==1){

			//↓自分の現在の位置と地形からどう動くか判断///////////////////////////////////////////////

			 //(地面)プレイヤーから一定距離(ランダム値+32)左に離れたらプレイヤーに近づいて右に歩く
			if(Zousyoku[i].Jump==0 && Player->X-(Zousyoku[i].Random+32) > Zousyoku[i].X){
				Zousyoku[i].RIGHTcount++;
				//自分の1マス右に障害物があったらジャンプする
				if(MAP_CHIP((Zousyoku[i].Y)/32,(Zousyoku[i].X+32)/32)!=0 &&
					MAP_CHIP((Zousyoku[i].Y+31)/32,(Zousyoku[i].X+32)/32)!=0){
						Zousyoku[i].Acount = 1;
						Zousyoku[i].JumpMuki = 1;
				}
				//自分の1マス右の列の一番下のマスが穴だったらジャンプする
				if(MAP_CHIP((383)/32,(Zousyoku[i].X+32)/32)==0 &&
					MAP_CHIP((383)/32,(Zousyoku[i].X+63)/32)==0){
						Zousyoku[i].Acount = 1;
						Zousyoku[i].JumpMuki = 1;
				}
			}//(地面)プレイヤーから一定距離(ランダム値+32)右に離れたらプレイヤーに近づいて左に歩く
			if(Zousyoku[i].Jump==0 && Player->X+(Zousyoku[i].Random+32) < Zousyoku[i].X){
				Zousyoku[i].LEFTcount++;
				//自分の1マス左に障害物があったらジャンプする
				if(MAP_CHIP((Zousyoku[i].Y)/32,(Zousyoku[i].X-1)/32)!=0 &&
					MAP_CHIP((Zousyoku[i].Y+31)/32,(Zousyoku[i].X-1)/32)!=0){
						Zousyoku[i].Acount = 1;
						Zousyoku[i].JumpMuki = 0;
				}
				//自分の1マス左の列の一番下のマスが穴だったらジャンプする
				if(MAP_CHIP((383)/32,(Zousyoku[i].X-32)/32)==0 &&
					MAP_CHIP((383)/32,(Zousyoku[i].X-1)/32)==0){
						Zousyoku[i].Acount = 1;
						Zousyoku[i].JumpMuki = 0;
				}
			}
			//(地面)プレイヤーの近くまで来たら移動をやめる
			if(Zousyoku[i].Jump==0 && (Player->X-(Zousyoku[i].Random+32) <= Zousyoku[i].X && Player->X+(Zousyoku[i].Random+32) >= Zousyoku[i].X)){
				Zousyoku[i].RIGHTcount = 0;
				Zousyoku[i].LEFTcount = 0;
			}
			//(空中)1回のジャンプで必ず1マス分(20フレーム)は右(プレイヤーの方向)に動かす(踏み外しは除く)
			if(Zousyoku[i].Jump==1 && Zousyoku[i].JumpMuki==1 && Zousyoku[i].Humihazusi==0 && Player->X > Zousyoku[i].X){
				Zousyoku[i].Count20++;
				if(Zousyoku[i].Count20 <= 20)
					Zousyoku[i].RIGHTcount++;
			}
			//(空中)1回のジャンプで必ず1マス分(20フレーム)は左(プレイヤーの方向)に動かす(踏み外しは除く)
			if(Zousyoku[i].Jump==1 && Zousyoku[i].JumpMuki==0 && Zousyoku[i].Humihazusi==0 && Player->X < Zousyoku[i].X){
				Zousyoku[i].Count20++;
				if(Zousyoku[i].Count20 <= 20)
					Zousyoku[i].LEFTcount++;
			}
			//(空中)踏み外した場合は着地まで動かない(穴の場合はジャンプしているはずなので確実に着地する)
			if(Zousyoku[i].Jump==1 && Zousyoku[i].Humihazusi==1 ){
				Zousyoku[i].RIGHTcount = 0;
				Zousyoku[i].LEFTcount = 0;
			}
			//(空中)自分の下に地面がなかったらあるところまで右(プレイヤーの方向)に動く
			if(Zousyoku[i].Jump==1 && Zousyoku[i].JumpMuki==1 && Zousyoku[i].X < Player->X){
				if(MAP_CHIP((383)/32,(Zousyoku[i].X)/32)==0 &&
					MAP_CHIP((383)/32,(Zousyoku[i].X+31)/32)==0){
						Zousyoku[i].RIGHTcount++;
				}
			}
			//(空中)自分の下に地面がなかったらあるところまで左(プレイヤーの方向)に動く
			if(Zousyoku[i].Jump==1 && Zousyoku[i].JumpMuki==0 &&  Zousyoku[i].X > Player->X){
				if(MAP_CHIP((383)/32,(Zousyoku[i].X)/32)==0 &&
					MAP_CHIP((383)/32,(Zousyoku[i].X+31)/32)==0){
						Zousyoku[i].LEFTcount++;
				}
			}
			//(空中)ジャンプして1マス以上動いてから自分の下に地面があったら移動をやめる
			if(Zousyoku[i].Jump==1 && Zousyoku[i].Count20 > 20){
				if(MAP_CHIP((383)/32,(Zousyoku[i].X)/32)!=0 &&
					MAP_CHIP((383)/32,(Zousyoku[i].X+31)/32)!=0){
						Zousyoku[i].RIGHTcount = 0;
						Zousyoku[i].LEFTcount = 0;
				}
			}
			//着地したら20フレームカウントをリセット
			if(Zousyoku[i].Jump==0){
				Zousyoku[i].Count20=0;
			}

			//↓キャラクターの移動処理///////////////////////////////////////////////////////////

			//天井との補正
			if(Zousyoku[i].JumpPower>0){
				if(MAP_CHIP((Zousyoku[i].Y)/32,(Zousyoku[i].X)/32)!=0 ||
					MAP_CHIP((Zousyoku[i].Y)/32,(Zousyoku[i].X+31)/32)!=0 ){
						Zousyoku[i].Y = (Zousyoku[i].Y/32)*32+32;
				}
			}

			//右との補正
			if(MAP_CHIP((Zousyoku[i].Y)/32,(Zousyoku[i].X+31)/32)!=0 ||
				MAP_CHIP((Zousyoku[i].Y+31)/32,(Zousyoku[i].X+31)/32)!=0){
					Zousyoku[i].X = (Zousyoku[i].X/32)*32;
			}
			//左との補正
			if(MAP_CHIP((Zousyoku[i].Y)/32,(Zousyoku[i].X)/32)!=0 ||
				MAP_CHIP((Zousyoku[i].Y+31)/32,(Zousyoku[i].X)/32)!=0){
					Zousyoku[i].X = (Zousyoku[i].X/32)*32+32;
			}

			//天井にぶつかったらジャンプ力を0
			if(Zousyoku[i].JumpPower>0 ){
				if(MAP_CHIP((Zousyoku[i].Y-1)/32,(Zousyoku[i].X)/32)!=0 ||
					MAP_CHIP((Zousyoku[i].Y-1)/32,(Zousyoku[i].X+31)/32)!=0 ){
						Zousyoku[i].JumpPower=0;
				}
			}

			//右を押したときに右に壁がなかったら
			if( Zousyoku[i].RIGHTcount > 0 ){
				if(MAP_CHIP((Zousyoku[i].Y)/32,(Zousyoku[i].X+32)/32)==0 &&
					MAP_CHIP((Zousyoku[i].Y+31)/32,(Zousyoku[i].X+32)/32)==0){
						Zousyoku[i].Muki=1;			//向きを右に
						Zousyoku[i].WalkCount++;	//歩きカウント増加
						Zousyoku[i].Image = Zousyoku[i].DivImage[(Zousyoku[i].WalkCount%32)/8];	//カウントで歩くアニメーション
						Zousyoku[i].X += (int)Zousyoku[i].Speed;
						Zousyoku[i].Speed += Zousyoku[i].Accel ;//加速度でスピードを増加
				}else{	//壁があったら
					Zousyoku[i].Speed=0;//スピードを0
					Zousyoku[i].Image = Zousyoku[i].DivImage[4];	//止まってる画像
				}
			}
			//右を離したら
			if(Zousyoku[i].Muki==1 && Zousyoku[i].RIGHTcount == 0){
				Zousyoku[i].Image = Zousyoku[i].DivImage[4];	//止まってる画像
				Zousyoku[i].WalkCount=0;						//カウント停止
				if(MAP_CHIP((Zousyoku[i].Y)/32,(Zousyoku[i].X+32)/32)==0 &&
					MAP_CHIP((Zousyoku[i].Y+31)/32,(Zousyoku[i].X+32)/32)==0){
						Zousyoku[i].X += (int)Zousyoku[i].Speed;
						Zousyoku[i].Speed -= Zousyoku[i].Accel ;	//壁がなかったら加速度でスピードを落とす
				}else{
					Zousyoku[i].Speed=0;	//壁があったらスピードを0
				}
			}
			//左を押したときに左に壁がなかったら
			if( Zousyoku[i].LEFTcount > 0 ){
				if(MAP_CHIP((Zousyoku[i].Y)/32,(Zousyoku[i].X-1)/32)==0 &&
					MAP_CHIP((Zousyoku[i].Y+31)/32,(Zousyoku[i].X-1)/32)==0){
						Zousyoku[i].Muki=0;			//向きを左に
						Zousyoku[i].WalkCount++;	//歩きカウント増加
						Zousyoku[i].Image = Zousyoku[i].DivImage[(Zousyoku[i].WalkCount%32)/8+8];//カウントでアニメーション
						Zousyoku[i].X -= (int)Zousyoku[i].Speed;
						Zousyoku[i].Speed += Zousyoku[i].Accel ;//加速度でスピードを増加
				}else{	//壁があったら
					Zousyoku[i].Speed=0;//スピードを0
					Zousyoku[i].Image = Zousyoku[i].DivImage[12];
				}
			}
			//左を離したら
			if(Zousyoku[i].Muki==0 && Zousyoku[i].LEFTcount == 0){

				Zousyoku[i].Image = Zousyoku[i].DivImage[12];	//止まってる画像
				Zousyoku[i].WalkCount=0;						//カウント停止
				if(MAP_CHIP((Zousyoku[i].Y)/32,(Zousyoku[i].X-1)/32)==0 &&
					MAP_CHIP((Zousyoku[i].Y+31)/32,(Zousyoku[i].X-1)/32)==0){
						Zousyoku[i].X -= (int)Zousyoku[i].Speed;
						Zousyoku[i].Speed -= Zousyoku[i].Accel ;	//壁がなかったら加速度でスピードを落とす
				}else{
					Zousyoku[i].Speed=0;	//壁があったらスピードを0
				}
			}


			//プレイヤーの速さは最大値2、最小値0
			if(Zousyoku[i].Speed <= 0)Zousyoku[i].Speed=0;
			if(Zousyoku[i].Speed >= 2)Zousyoku[i].Speed=2;


			//ジャンプする
			if(Zousyoku[i].Jump==0 && Zousyoku[i].Acount > 0 ){
				if(MAP_CHIP((Zousyoku[i].Y-1)/32,(Zousyoku[i].X)/32)==0 &&
					MAP_CHIP((Zousyoku[i].Y-1)/32,(Zousyoku[i].X+31)/32)==0 ){
						Zousyoku[i].JumpPower = 10;
						Zousyoku[i].Jump = 1;
				}
			}
			//歩いてるときに踏み外したらジャンプ状態
			if(Zousyoku[i].Jump==0){
				if(MAP_CHIP((Zousyoku[i].Y+32)/32,(Zousyoku[i].X)/32)==0 &&
					MAP_CHIP((Zousyoku[i].Y+32)/32,(Zousyoku[i].X+31)/32)==0 )
				{
					Zousyoku[i].Jump=1;
					Zousyoku[i].Humihazusi=1;
				}
			}

			//右向いてるジャンプ画像
			if(Zousyoku[i].Muki==1 && Zousyoku[i].Jump==1 ){
				if(Zousyoku[i].JumpPower > 0){
					Zousyoku[i].Image = Zousyoku[i].DivImage[4];
				}
				if(Zousyoku[i].JumpPower <= 0){
					Zousyoku[i].Image = Zousyoku[i].DivImage[4];
				}
			}
			//左向いてるジャンプ画像
			if(Zousyoku[i].Muki==0 && Zousyoku[i].Jump==1 ){
				if(Zousyoku[i].JumpPower > 0){
					Zousyoku[i].Image = Zousyoku[i].DivImage[12];
				}
				if(Zousyoku[i].JumpPower <= 0){
					Zousyoku[i].Image = Zousyoku[i].DivImage[12];
				}
			}

			//ジャンプ中は落下させる
			if(Zousyoku[i].Jump==1){
				Zousyoku[i].Y-=(int)Zousyoku[i].JumpPower;
				Zousyoku[i].JumpPower-=Zousyoku[i].JumpAccel;
			}

			//床との補正
			if(MAP_CHIP((Zousyoku[i].Y+31)/32,(Zousyoku[i].X)/32)!=0 ||
				MAP_CHIP((Zousyoku[i].Y+31)/32,(Zousyoku[i].X+31)/32)!=0 ){
					Zousyoku[i].Y = (Zousyoku[i].Y/32)*32;
			}

			//地面についたらジャンプをやめる
			if(Zousyoku[i].Jump==1 && Zousyoku[i].JumpPower<0 ){
				if(MAP_CHIP((Zousyoku[i].Y+32)/32,(Zousyoku[i].X)/32)!=0 ||
					MAP_CHIP((Zousyoku[i].Y+32)/32,(Zousyoku[i].X+31)/32)!=0 ){
						Zousyoku[i].JumpPower=0;
						Zousyoku[i].Jump=0;
						Zousyoku[i].Acount = 0;
						Zousyoku[i].Humihazusi=0;
				}
			}

			//画面外に落ちた場合は消えて初期化(存在フラグを0にする)
			if(Zousyoku[i].Y >= 384){
				Zousyoku[i].Flag = 0;
				Zousyoku[i].Image = Zousyoku[i].DivImage[4];
				Zousyoku[i].X     = 0;
				Zousyoku[i].Y     = 0;
				Zousyoku[i].Walk=0;
				Zousyoku[i].Muki=1;
				Zousyoku[i].WalkCount=0;
				Zousyoku[i].Speed=0;
				Zousyoku[i].Accel=0.5;
				Zousyoku[i].Jump=0;
				Zousyoku[i].JumpPower=0;
				Zousyoku[i].JumpAccel=0.5;

				Zousyoku[i].RIGHTcount=0;
				Zousyoku[i].LEFTcount=0;
				Zousyoku[i].Acount=0;
				Zousyoku[i].Bcount=0;

				Zousyoku[i].Count=0;
				Zousyoku[i].RandomJump=0;
				Zousyoku[i].Count20=0;
				Zousyoku[i].JumpMuki=0;
			}
			
		}
	}
}




//キャラクター描画
void Zousyoku_Draw(){

	for(int i = 0; i < 99; i++)
	{
		if(Zousyoku[i].Flag == 1)
			DrawGraph( Zousyoku[i].ViewX, Zousyoku[i].Y , Zousyoku[i].Image, TRUE ) ;
	}

}



ISLe
記事: 2650
登録日時: 15年前
連絡を取る:

Re: アクションゲームでプレイヤーの後を自動的についてくるキャラクター

#2

投稿記事 by ISLe » 14年前

プレイヤーが通過したマスを一定数記録しておいて、それを古いものから追いかけるようにしたら良いのではないでしょうか。

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

Re: アクションゲームでプレイヤーの後を自動的についてくるキャラクター

#3

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

ISLeさんの書かれた方法がひとつの方法ですが、ちゃんと不要な動作を刈り取らないと無意味なジャンプまで真似してしまう事になりねません。
カービィのヘルパーの様に自動的に付いてきてくれて攻撃までしてくるとかとなると人工知能の領分となり難しいものとなります。
ISLeさんのような処理と自動処理を適度に切り替えながら行うのもよいでしょう。

ただ、移動地形などがあると後を付く方法では解決しないジャンプアクションが出てきます。
こうなると人工知能的に先読みなどヤヤコシイ事が必要になってきます。

ついでに一番近い移動できる位置を知る方法として「最短経路探索」を紹介しておきます。
「ゲーム制作の舞台裏 ダイクストラで最短経路探索」
http://tkina.blog60.fc2.com/blog-entry-325.html
「ゲーム制作の舞台裏 エースターで最短経路探索」
http://tkina.blog60.fc2.com/blog-entry-326.html
「ダイクストラ法による最短ルートの求めかた」
http://www.sousakuba.com/Programming/algo_root.html
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Wirelessりちみ

Re: アクションゲームでプレイヤーの後を自動的についてくるキャラクター

#4

投稿記事 by Wirelessりちみ » 14年前

返信ありがとうございます。
プレイヤーが通過したマスをたどるというのも使えるとは思ったんですが、
マスではなく、プレイヤーの入力を時間差で真似するという方法でも可能なのでしょうか?

プレイヤーが穴に落ちてしまった場合、ついてくるキャラも真似して穴に落ちたりしないようにしたいのですが、
入力を真似する方法なら、不要な入力だけ真似しないようにするのも楽なのではないかと思ったのですが…

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

Re: アクションゲームでプレイヤーの後を自動的についてくるキャラクター

#5

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

Wirelessりちみ さんが書きました:返信ありがとうございます。
プレイヤーが通過したマスをたどるというのも使えるとは思ったんですが、
マスではなく、プレイヤーの入力を時間差で真似するという方法でも可能なのでしょうか?

プレイヤーが穴に落ちてしまった場合、ついてくるキャラも真似して穴に落ちたりしないようにしたいのですが、
入力を真似する方法なら、不要な入力だけ真似しないようにするのも楽なのではないかと思ったのですが…
リング(循環)バッファと言うアルゴリズムを使うのが良いでしょう。
入力が変化するたびにバッファ記録していって、記録しているバッファの60個ぐらい前(要調整)の情報でオプションキャラを操作します。

「C言語関数辞典 - C言語Tips集 配列を簡易的なキューとして使用する」
http://www.c-tipsref.com/tips/array/queue.html
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Wirelessりちみ

Re: アクションゲームでプレイヤーの後を自動的についてくるキャラクター

#6

投稿記事 by Wirelessりちみ » 14年前

ありがとうございます。参考にさせていただきます。
少し話が変わって申し訳ないのですが…

『人工知能』についてすこし興味がでて検索をしてみたのですが、マリオのようなアクションゲームの場合、
人工知能(AI)っていうのはどういう処理で作られているのでしょうか?
私が最初に箇条書きしたような処理を大量に書いたりするのでしょうか?

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

Re: アクションゲームでプレイヤーの後を自動的についてくるキャラクター

#7

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

Wirelessりちみ さんが書きました:ありがとうございます。参考にさせていただきます。
少し話が変わって申し訳ないのですが…

『人工知能』についてすこし興味がでて検索をしてみたのですが、マリオのようなアクションゲームの場合、
人工知能(AI)っていうのはどういう処理で作られているのでしょうか?
私が最初に箇条書きしたような処理を大量に書いたりするのでしょうか?
これをやれば人工知能と言うのはないのですが、どれも難しいですね。
・学習型:プレーヤーの行動を学習して状況に応じて最適行動を選択する。
・先読み型:今から行う行動を先行シミュレートして一番良い行動を選択する。
・行動パターンプログラム型:これがWirelessさんの方法に該当します。
・その他。私も知らないアルゴリズム。
あと、これらのハイブリッドです。

ここで説明出来るレベルではないので書籍を紹介しておきます。

「Amazon.co.jp: ゲームのアルゴリズム 改訂版 思考ルーチンと物理シミュレーション: 橋口 ゆうすけ: 本」

「Amazon.co.jp: ゲーム開発者のためのAI入門: David M. Bourg, Glenn Seemann, 株式会社クイープ: 本」

「Amazon.co.jp: 実例で学ぶゲームAIプログラミング: Mat Buckland, 松田 晃一: 本」
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

ISLe
記事: 2650
登録日時: 15年前
連絡を取る:

Re: アクションゲームでプレイヤーの後を自動的についてくるキャラクター

#8

投稿記事 by ISLe » 14年前

通過したすべてのマスを記録するのではなく、マップにチェックポイントを仕込んで通過したポイントを記録するというのはどうでしょうか。

Wirelessりちみ

Re: アクションゲームでプレイヤーの後を自動的についてくるキャラクター

#9

投稿記事 by Wirelessりちみ » 14年前

とりあえず、まずは簡単に移動地形などは作らずに、
プレイヤーが通過したマスをたどる・プレイヤーの入力を真似する・パターンで自動で動かす
の3つを使い分けることにして作ってみます。
アイデアと沢山の参考ありがとうございました。

閉鎖

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