ページ 11

キャラクターを動かすプログラム

Posted: 2009年1月26日(月) 16:43
by s-rush
いつもお世話になってます。
前回作っていた戦闘システム系のプログラムを少し凍結して
今はキャラクターを動かすプログラムを作っています。

ゲームプログラミングの館 第20章を参考にキャラクターの動く速度を可変できるプログラムを
作ってみたのですが、うまくいかない時があります。

 ”Zキーを入力しながら方向キーを入力と2倍の速度で動く”
というプログラムなんですが、時々本来なら通ることができないところを
通過してしまうときが生じてしまいます。
何度も実験をしているとどうやら
 方向キー入力中にZキーを入力 → Zキーを入力したまま方向キーを離す
とそのまま直進して壁をぶち破って進んでしまうようなんです。
現象が生じたときの画像を貼っておきます。
バグにより脱出不可能に(笑

必ずこのような手順で入力するとこの現象が起こってしまうのであれば
原因を見つけることができるとは思うのですが、
この現象が起こらないことの方が多いので何が原因なのか分からないです。

Re:キャラクターを動かすプログラム

Posted: 2009年1月26日(月) 16:45
by s-rush
続き
#include "DxLib.h"
 
typedef struct{
        int x,y,img,muki,walking_flag;
}ch_t;

int feild_map[15][20] = {
        { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 },
        { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 },
        { 1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1 },
        { 1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1 },
        { 1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1 },
        { 1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1 },
        { 1,1,1,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,1 },
        { 1,1,1,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,1 },
        { 1,1,1,1,1,0,0,0,0,0,1,0,0,0,1,0,0,0,1,1 },
        { 1,1,1,1,1,0,0,0,1,1,1,0,0,0,1,0,0,0,1,1 },
        { 1,1,1,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,1,1 },
        { 1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1 },
        { 1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1 },
        { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 },
        { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 },
};
 
int can_or_cannot(int x,int y,int muki){//進めるかを判定する
        if(muki==0)//上向きなら
                if(feild_map[y/32-1][x/32]==1)//進めるか判定
                        return 1;//エラー
        if(muki==1)//左向きなら
                if(feild_map[y/32][x/32-1]==1)
                        return 1;
        if(muki==2)//下向きなら
                if(feild_map[y/32+1][x/32]==1)
                        return 1;
        if(muki==3)//右向きなら
                if(feild_map[y/32][x/32+1]==1)
                        return 1;
        return 0;//正常
}

Re:キャラクターを動かすプログラム

Posted: 2009年1月26日(月) 16:46
by s-rush
もう一度続き
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
        
    int image[16],i,j;
	int map_chip[1];
	int map;
    char Key[256];
    ch_t ch;
 
    if( ChangeWindowMode(TRUE) != DX_CHANGESCREEN_OK || DxLib_Init() == -1 ) return -1; //ウィンドウ化と初期化処理
 
    ch.x    =320;
    ch.y    =160;
    ch.walking_flag=0;
    ch.muki=3;
	
	

    SetDrawScreen( DX_SCREEN_BACK ) ;                                  //描画先を裏画面に設定
    LoadDivGraph( "main_char.png" , 16 , 4 , 4 , 32 , 32 , image ) ;//画像を分割してimage配列に保存
  LoadDivGraph( "kusa.png" , 1 , 1 , 1 , 32 , 32 , map_chip ) ;//画像を分割してimage配列に保存
  PlayMusic( "masara_town.mid" , DX_PLAYTYPE_LOOP ) ; // test.midのバックグラウンド演奏 
  map = map_chip[0];
    while(!ProcessMessage() && !ClearDrawScreen() && !GetHitKeyStateAll( Key ) && !Key[KEY_INPUT_ESCAPE]){

 
                /*フィールドを描画*/
               for(i=0;i<15;i++)
                    for(j=0;j<20;j++)
                          if(feild_map[j]!=1)
                                DrawGraph( j*32,i*32 , map , TRUE ) ;    
 
               if(ch.x%32==0 && ch.y%32==0){         //座標が32で割り切れたら入力可能
                  ch.walking_flag=1;         //歩くフラグを立てる。
                  if     ( Key[ KEY_INPUT_UP   ]  == 1 )  //上ボタンが押されたら
                     ch.muki=0;         //上向きフラグを立てる
                  else if( Key[ KEY_INPUT_LEFT ]  == 1 )  //左ボタンが押されたら
                     ch.muki=1;         //左向きフラグを立てる
                  else if( Key[ KEY_INPUT_DOWN ]  == 1 )  //下ボタンが押されたら
                     ch.muki=2;         //下向きフラグを立てる
                  else if( Key[ KEY_INPUT_RIGHT]  == 1 )  //右ボタンが押されたら
                     ch.muki=3;         //右向きフラグを立てる
                  else                                    //何のボタンも押されてなかったら
                     ch.walking_flag=0; //歩かないフラグを立てる
               if(ch.walking_flag==1)    //もし歩くなら
                   if(can_or_cannot(ch.x,ch.y,ch.muki)==1)//行き先が歩けないなら
                       ch.walking_flag=0;                  //歩かないフラグを立てる。
         }
	
	//2倍速
	if(ch.walking_flag==1){        //歩くフラグが立っていたら
	   if(Key[KEY_INPUT_Z]){
		if(ch.muki==0)        //上向きならch.y座標を減らす
	            ch.y-=2;
		else if(ch.muki==1)        //左向きならch.x座標を減らす
	            ch.x-=2;
		else if(ch.muki==2)        //下向きならch.y座標を増やす
	  	   ch.y+=2;
		else if(ch.muki==3)        //右向きならch.x座標を増やす
		   ch.x+=2;
		}
	  //1倍速
             else{        //歩くフラグが立っていたら
		if(ch.muki==0)        //上向きならch.y座標を減らす
		   ch.y--;
		else if(ch.muki==1)        //左向きならch.x座標を減らす
		   ch.x--;
		else if(ch.muki==2)        //下向きならch.y座標を増やす
		   ch.y++;
		else if(ch.muki==3)        //右向きならch.x座標を増やす
		   ch.x++;
               }
   }
 
        ch.img=image[(ch.x%32+ch.y%32)/8 + ch.muki*4];            //画像をセット
 
        DrawGraph( ch.x , ch.y , ch.img , TRUE ) ;//画像を描画
 
        ScreenFlip();
    }
 
    DxLib_End();
    return 0;
}



開発環境はいつもと同じくVC++2008 EEです。

またみなさんの力をお貸しください。

Re:キャラクターを動かすプログラム

Posted: 2009年1月26日(月) 16:59
by non
ちょうど、32の倍数にならないときがあるからでは?

Re:キャラクターを動かすプログラム

Posted: 2009年1月26日(月) 18:39
by kazuoni
nonさんの仰る通り32の倍数にならないからだと思いますね。

例えば右に歩き始めて(xをインクリメントし始めて)
28→29に進む途中でzが押されたとします。
すると、次のループで
29+2=31
31+2=33
...
こんなことが起きるときもありますし、
無いときもあります。

解決策としては、
「キャラクターが止まっていて、Zキーが押されたら」
フラグをたて、
「フラグが立っていたら」
二倍速
みたいな感じで良いのではないでしょうか?

Re:キャラクターを動かすプログラム

Posted: 2009年1月26日(月) 19:03
by s-rush
nonさんやkazuoniさんのおっしゃるように
32の倍数になっていなかったのが原因のようでした。
if(ch.x%32==0 && ch.y%32==0){         //座標が32で割り切れたら入力可能
            ch.walking_flag=1;         //歩くフラグを立てる。
		if(Key[KEY_INPUT_Z])
			ch.speed = 1;
		else
			ch.speed = 0;
と変更し、スピード制御の条件式を変更したら正常に動作するようになりました。

あとこのプログラムを関数化したいのですが、どのようにすればいいのでしょうか?
void char_wakl()
{
ここは先ほどのプログラムと同じ制御
}
たぶんこのような感じでプログラムを書けば大丈夫だと思うのですが、
どこで、どのタイミングで関数を呼び出せばよいのか分からないです。

面倒ついでにこれについても教えていただいても構いませんか?

Re:キャラクターを動かすプログラム

Posted: 2009年1月26日(月) 19:47
by kazuoni
基本的にはキャラの座標移動の前にループ毎に呼び出せば良いと思います。
ただ、個人的な意見ですが、Zキー押しっぱなしは結構面倒ではないですか?
ポケモン制作だったらZ押せば自転車に乗る的な感じ
だったら操作する側は楽かなーって思ったりしちゃうのですが^^;
あ、人それぞれの実装があるので、流しておいてください。。

Re:キャラクターを動かすプログラム

Posted: 2009年1月27日(火) 11:27
by s-rush
>基本的にはキャラの座標移動の前にループ毎に呼び出せば良いと思います。
というのはどういうことなんでしょうか?

main関数内で方向キーが入力されたときに移動関数を呼び出す
ということなんですか?

>ポケモン制作だったらZ押せば自転車に乗る的な感じ
もちろんこれも実装しますよ^^
今のポケモンの操作制御は
歩行、ダッシュ、自転車(2段可変速)の4種ありますので
忠実に再現しようとしているのでダッシュも実装したかったのです。

確かにZキーを押しっぱなしにするのもユーザー側からすれば面倒かもしれないですが、
さすがに建物の中を自転車で爆走するのはどうかなって思いまして・・・

Re:キャラクターを動かすプログラム

Posted: 2009年1月29日(木) 00:04
by s-rush
このプログラムをchar_wakl()という関数にしたいのですが、
引数として何を設けてあげた方が処理がしやすくなりますか?

自キャラの座標と入力されたキーを格納する変数は少なくとも必要だと思うのですが。

Re:キャラクターを動かすプログラム

Posted: 2009年1月29日(木) 01:42
by BEMANI
>>s-rushさん
自分は自キャラの移動関数を作りましたが、関数内には

・十字キーを押せばキャラの移動
・マップとの当たり判定(移動限界の制御)
・歩行速度

という処理が書いてあるだけで、何も引数を使っていないです。
というのも、特に引数を必要としなかったからです。


s-rushさん的にはどのような情報があれば便利そうだとお考えでしょうか?
これがあれば便利! というものを引数にすればいいと思いますよ^^

Re:キャラクターを動かすプログラム

Posted: 2009年1月29日(木) 02:41
by 木霊
 s-rushさん、はじめましてですかね?

 このプログラムをそのまま関数にするなら最低でも
・構造体ch・・・1
・配列key[/url]・・・2
・配列image[/url]・・・3
の3つの引数がいることになります。
 多分今のままだと選択の余地がないと思うので少し処理を分けてみませんか?
 描画を別の関数にしてしまうのであれば1番と2番だけで済みますし(描画の時には1番と3番)
移動もキー入力と実際の移動を分ければ街の人等を動かすのにここで作った関数を使えそうですよね。

 あと、4段階のスピードを予定しているそうですが、それなら
int speed = 1;// 移動スピード(1歩行、2ダッシュ、4自転車低速、8自転車高速)
・・・(↑32の約数が1・2・4・8・16・32なので、それ以外の値にならないように処理しておく)
ch.x += 1 *speed;
・・・
という感じにしたらif文のまとまりをスピード毎に書かなくてもいいと思いますがどうでしょう?

 個人的にはスピード切り替え式より押しっぱなしの方が・・・ってそんなアンケートとってないですねw

Re:キャラクターを動かすプログラム

Posted: 2009年1月29日(木) 16:58
by s-rush
>>BEMANIさん
これがあると便利かなという情報がまだよく分かっていないです^^;
というのも移動関数を作ること自体が初めてなので・・・
いろいろと試行錯誤を重ねて考えてみます。

>>木霊さん
はじめましてです^^
自キャラ以外のキャラクターの移動にもできれば使用したいので、処理を分けて考えてみます。
となると必要な関数は
・キー入力
・移動
・描画
の3つが必要になるのですかね?

>個人的にはスピード切り替え式より押しっぱなしの方が・・・
原作同様にダッシュは押しっぱなしで、自転車のみ切り替え式にしようかと思ってます

Re:キャラクターを動かすプログラム

Posted: 2009年1月29日(木) 20:50
by 木霊
 それでいいと思いますよ。

 それだと、キー入力は主人公用で、他のキャラは別の関数(乱数で移動方向決定とか)になりますね。
 ただ、移動をマップ上を歩くキャラ共通で使えるようにするには引数を工夫しないと
無理なので少し苦労するかもしれません。
(構造体chをそのまま渡すのなら他のキャラも同じ構造体で作る必要がありますが、その場合主人公だけの情報
 を構造体に組み込めない。また、別の構造体で作るのならば引数の数が多くなってしまう。)

 実は原作未プレイですw

Re:キャラクターを動かすプログラム

Posted: 2009年1月29日(木) 22:19
by s-rush
関数化する前に先に自転車の速度制御も組み込みたいのですが、思った通りに動きません。

普通の状態でCを入力すると(グラフィックはまだ変わらないですが)自転車に乗る。
自転車に乗っている状態でXを入力すると低速、高速の切り替え。
自転車に乗っている状態でCを入力すると、自転車から降りる。
ダッシュとは違い押しっぱなしではなく、キーを一度入力すると移動速度が変化する、
という処理を実装したいのですが、一度キーを入力しても移動速度に変化が見られませんでした。
(キーを押しっぱなしにしていれば変わるようでしたが)

Re:キャラクターを動かすプログラム

Posted: 2009年1月29日(木) 22:19
by s-rush
コードが入らなかったので続きです。
#include "DxLib.h"
 
typedef struct{
  int x,y,img,muki,walking_flag, speed;
  int st;		//ステイト 歩き:0 自転車:1(低速)2(高速)
}ch_t;

(略)
void walk_or_bike(ch_t *ch, char Key[/url])
{
	//自転車の乗り降り
	if(ch->st == 0 && Key[KEY_INPUT_C])
	   ch->st = 1;
	else if(ch->st = 1 && Key[KEY_INPUT_C])
	   ch->st = 0;
	//自転車の速度の切り替え
	else if(ch->st = 1 && Key[KEY_INPUT_X])
	  ch->st = 2;
	else if(ch->st = 2 && Key[KEY_INPUT_X])
	  ch->st = 1;
}


int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
        
    int image[16],i,j;
    int map_chip[1];
    int map;
    char Key[256];
    ch_t ch;
    
    ch.st = 0;      //自転車に乗っていない状態
 
    if( ChangeWindowMode(TRUE) != DX_CHANGESCREEN_OK || DxLib_Init() == -1 ) return -1; //ウィンドウ化と初期化処理
 
    ch.x    =320;
    ch.y    =160;
    ch.walking_flag=0;
    ch.muki=3;
	
	

    SetDrawScreen( DX_SCREEN_BACK ) ;                           //描画先を裏画面に設定
    LoadDivGraph( "main_char.png" , 16 , 4 , 4 , 32 , 32 , image ) ;//画像を分割してimage配列に保存
    LoadDivGraph( "kusa.png" , 1 , 1 , 1 , 32 , 32 , map_chip ) ;//画像を分割してimage配列に保存
    PlayMusic( "masara_town.mid" , DX_PLAYTYPE_LOOP ) ; // test.midのバックグラウンド演奏 
    map = map_chip[0];
    while(!ProcessMessage() && !ClearDrawScreen() && !GetHitKeyStateAll( Key ) && !Key[KEY_INPUT_ESCAPE]){
            //↑メッセージ処理        ↑画面をクリア         ↑キーボード入力状態取得       ↑ESCが押されると終了
 
                /*白い壁を描画*/
                for(i=0;i<15;i++)
                        for(j=0;j<20;j++)
                                if(feild_map[j]!=1)
                                    DrawGraph( j*32,i*32 , map , TRUE ) ;    

 

            if(ch.x%32==0 && ch.y%32==0){         //座標が32で割り切れたら入力可能
		ch.walking_flag=1;         //歩くフラグを立てる。
		walk_or_bike(&ch, Key);

		if(Key[KEY_INPUT_Z] && ch.st==0)
		  ch.speed = 2;
		else if(ch.st == 1)
		  ch.speed =4;
		else if(ch.st == 2)
		  ch.speed = 8;
		else
		  ch.speed = 1;

                  if( Key[ KEY_INPUT_UP   ]  == 1 )  //上ボタンが押されたら
                    ch.muki=0;         //上向きフラグを立てる
                  else if( Key[ KEY_INPUT_LEFT ]  == 1 )  //左ボタンが押されたら
                    ch.muki=1;         //左向きフラグを立てる
                  else if( Key[ KEY_INPUT_DOWN ]  == 1 )  //下ボタンが押されたら
                    ch.muki=2;         //下向きフラグを立てる
                  else if( Key[ KEY_INPUT_RIGHT]  == 1 )  //右ボタンが押されたら
                    ch.muki=3;         //右向きフラグを立てる
                  else                                    //何のボタンも押されてなかったら
                    ch.walking_flag=0; //歩かないフラグを立てる

                  if(ch.walking_flag==1)    //もし歩くなら
                    if(can_or_cannot(ch.x,ch.y,ch.muki)==1)//行き先が歩けないなら
                       ch.walking_flag=0;                  //歩かないフラグを立てる。
        }

	         if(ch.walking_flag==1){        //歩くフラグが立っていたら
		    if(ch.muki==0)        //上向きならch.y座標を減らす
		       ch.y-=1*ch.speed;
		    else if(ch.muki==1)        //左向きならch.x座標を減らす
		       ch.x-=1*ch.speed;
		    else if(ch.muki==2)        //下向きならch.y座標を増やす
		       ch.y+=1*ch.speed;
		    else if(ch.muki==3)        //右向きならch.x座標を増やす
	 	       ch.x+=1*ch.speed;
		    } 
        ch.img=image[(ch.x%32+ch.y%32)/8 + ch.muki*4];            //画像をセット
 
        DrawGraph( ch.x , ch.y , ch.img , TRUE ) ;//画像を描画
 
        ScreenFlip();
    }
 
    DxLib_End();
    return 0;
}


自転車の乗り降りを制御する関数はwalk_or_bikeで、
キー入力が可能になるたびに呼び出しているので
ch.stの値が書き変わっていると思うのですが移動速度に反映されていないです。

どこがおかしいのでしょうか?

Re:キャラクターを動かすプログラム

Posted: 2009年1月29日(木) 22:25
by kazuoni
ifの条件で
ch->st==1じゃないですか?
あと二か所そうなってます。

--追加
VC++やeclipseならブレークポイントを立てて
変数の移り変わりを見る癖をつけると作業がスムーズになりますよ^^

Re:キャラクターを動かすプログラム

Posted: 2009年1月29日(木) 22:54
by s-rush
>ch->st==1じゃないですか?
これでした^^;
kazuoniさん、ありがとうございました。
超初歩的なミスですいませんでした。
自分ながら情けないorz

でもif(a=0)
のようにしてしまうとコンパイルエラーが出ませんでした?

これで自転車の速度制御ができるようになったのですが、
walk_or_bike()を呼び出して、キーを入力したとき、
変化が速すぎるのですが、ストッパーみたいなものって入れることはできないのですか?
キーをずっと押しっぱなしにしていると、ずっと変化してしまっているので。

Re:キャラクターを動かすプログラム

Posted: 2009年1月29日(木) 23:10
by kazuoni
=と==の違いはC言語の入門サイトに載ってますよ^^

>ストッパー
staticで変数を用意して、walk_or_bike()を呼び出すたびにインクリメントします。
この数が偶数のときにこの処理をする
・・・これで処理速度は元の約1/2になります。
こんな感じですかね。とっても単純ですけど^^;

Re:キャラクターを動かすプログラム

Posted: 2009年1月29日(木) 23:24
by 木霊
>変化が速すぎるのですが

 管理人さんの作ったこちらの関数を使ってみてはどうですか?

int GetHitKeyStateAll_2 ( int* KeyStateBuf );

 こちらはキーを押している間は数値が増え、離した瞬間に0になります。
 押した瞬間だけ(変数 == 1の時)フラグを入れ替えるようにすれば変化が早すぎることはなくなると思います。
 詳細はゲームプログラミングの館40aです。

Re:キャラクターを動かすプログラム

Posted: 2009年1月29日(木) 23:45
by kazuoni
あ、移動速度の事じゃなかったんですね^^;
コード読まずに発言して申し訳ありませんでした。。
切り替えなら木霊さんのおっしゃるように、
管理人さん作のキー監査で事は十分に足りると思います^^

Re:キャラクターを動かすプログラム

Posted: 2009年1月30日(金) 00:32
by s-rush
>管理人さんの作ったこちらの関数を使ってみてはどうですか?
ということは
int GetHitKeyStateAll_2(int KeyStateBuf[/url]){
        char GetHitKeyStateAll_Key[256];
        GetHitKeyStateAll( GetHitKeyStateAll_Key );
        for(int i=0;i<256;i++){
                if(GetHitKeyStateAll_Key==1) KeyStateBuf++;
                else                            KeyStateBuf=0;
        }
        return 0;
}

void walk_or_bike(ch_t *ch, char Key[/url])
{
	//自転車の乗り降り
	if(ch->st == 0 && Key[KEY_INPUT_C])
		ch->st = 1;
	else if((ch->st == 1 || ch->st == 2) && Key[KEY_INPUT_C])
		ch->st = 0;
	//自転車の速度の切り替え
	else if(ch->st == 1 && Key[KEY_INPUT_X])
		ch->st = 2;
	else if(ch->st == 2 && Key[KEY_INPUT_X])
		ch->st = 1;
}

この2つの関数を組み合わせるといいんですか?
(walk_or_bike()にGetHitKeyStateAll_2(int KeyStateBuf[/url])を組み込む?)

Re:キャラクターを動かすプログラム

Posted: 2009年1月30日(金) 01:08
by 木霊
>while(!ProcessMessage() && !ClearDrawScreen() && !GetHitKeyStateAll( Key ) && !Key[KEY_INPUT_ESCAPE]){

 今この場所で使ってる関数をGetHitKeyStateAll_2に入れ替えて、(その前にchar Key [ 256 ]をint Key [ 256 ]に変更)

void walk_or_bike(ch_t *ch, char *Key[/url])
{
//自転車の乗り降り
if(ch->st == 0 && Key[KEY_INPUT_C] == 1 )
ch->st = 1;
else if((ch->st == 1 || ch->st == 2) && Key[KEY_INPUT_C] == 1 )
ch->st = 0;
//自転車の速度の切り替え
else if(ch->st == 1 && Key[KEY_INPUT_X] == 1 )
ch->st = 2;
else if(ch->st == 2 && Key[KEY_INPUT_X] == 1 )
ch->st = 1;
}
で大丈夫だと思いますよ。

Re:キャラクターを動かすプログラム

Posted: 2009年1月30日(金) 11:44
by s-rush
>>木霊さん
GetHitKeyStateAll_2関数を使うといいですよ
と教えていただいてから同じプログラムを書いたのですが、
このように書くと、確かにCやXを入力した際の変化は改善されたのですが、
方向キーを入力した時も同じように(押しっぱなしにすると一歩しか動かない)
なってしまうのですが・・・

Re:キャラクターを動かすプログラム

Posted: 2009年1月30日(金) 12:11
by kazuoni
関数の中身を理解していますか?
この関数はボタン監査が1だと変数にインクリメントされていきます。
なので
if(Key[??]==1)
とやると一回目しか通りません。
歩く処理は
if(Key[??] >= 1)
としてください。

Re:キャラクターを動かすプログラム

Posted: 2009年1月30日(金) 12:57
by s-rush
kazuoniさん、ありがとうございます。
解決できました。
for(int i=0;i<256;i++){
     if(GetHitKeyStateAll_Key==1) KeyStateBuf++;
     else                            KeyStateBuf=0;
        }

の解釈を間違ってしていました。

あとはこの処理を関数化するだけなので、頑張ってみます。

Re:キャラクターを動かすプログラム

Posted: 2009年1月31日(土) 16:28
by s-rush
皆さんのおかげで、関数化できました。
ありがとうございました。

慣れた人から見ると無駄が多すぎだと思いますが^^;

少し話がずれますが龍神録を遊ばせていただきました。
シューティングゲームは結構自身があるんですが、それでも死にまくりで難しかったです。
そのプログラムを拝見させていただいたのですが、
ゲームのはじめ?のフィールド移動や店、キャラクターとの会話の処理のプログラムは
紹介されていませんでしたよね?

もしよければ、お時間のある時にソースを教えていただけるとありがたいのですが。

Re:キャラクターを動かすプログラム

Posted: 2009年1月31日(土) 16:55
by kazuoni
arrayさんのHP龍神録プログラミングの支館のサウンドノベルシステム
http://sinkai.net/rp/19.php
に会話に参考になりそうな所がありますよ。

自分もゲームプログラミングの支館つくろうかな・・・w
まだまだ実力不足ですね・・・

Re:キャラクターを動かすプログラム

Posted: 2009年1月31日(土) 23:46
by s-rush
>kazuoniさん
ありがとうございます。
教えていただいたHPを参考にしてセリフの表示を頑張ってみたいと思います。

Re:キャラクターを動かすプログラム

Posted: 2009年2月01日(日) 00:11
by Dixq (管理人)
私でよければ何か作って欲しいサンプルがあれば作りますよ^^
忙しい時期が終わったので、やっと一安心してるところです・・。

>>kazuoniさん

おぉ!ホントですか!
もしその時は全面協力させていただきます♪

Re:キャラクターを動かすプログラム

Posted: 2009年2月01日(日) 00:25
by kazuoni
まず一旦自分ですべて作ってみようかと思ってます。
ツールをw
やっぱりマップエディタは必須ですかね。。
さすがにすべてコードに書き込みはきついし、非効率ですからね・・・
でも細かくやってくと結局はRPGツクールを作ろう!になってしまいそうな・・・w

とりあえず当面はRPGを一度すべて作ってみようかと思います。
それから支える館を作っていこうかと考えています。
・・・今年の夏も目標にw

PS:太鼓の鉄人を変えてビーマニもどき作りましたが、一曲で挫折しました♪orz♪

Re:キャラクターを動かすプログラム

Posted: 2009年2月01日(日) 13:18
by s-rush
>私でよければ何か作って欲しいサンプルがあれば作りますよ^^
本当ですか?
今、移動処理に関するもので、
・マップのスクロール処理
・マップ同士のつながり
・マップの切り替え
・ほかのキャラクターの移動
・他のキャラクターとの会話?
のアルゴリズムを考えています。

Final storyを参考にマップの切り替え処理の考えはある程度理解できたのですが、
スクロール処理に困っています。
他のサイトでも紹介されているところも少ないので、良い考えが思い浮かばないです。

自分のいる座標を中心にその周りのマップを表示させ、
一歩歩くごとに表示するマップのエリアを1歩分ずらす。
またマップのつながりのために
自分のいるエリアのマップの東西南北のマップ情報も
別のマップ配列に読み込んでおく。
エリアが変われば、東西南北のマップ情報を更新する。

というアルゴリズムで実装してみようかなと考えているのですが、
処理時間が遅くなるのでは?
と思ってしまって、なかなか実装できずにいました。

もしよろしければ、スクロール処理のプログラムのサンプルを
書いていただければありがたいです。


>忙しい時期が終わったので、やっと一安心してるところです・・。
お疲れ様でした^^

Re:キャラクターを動かすプログラム

Posted: 2009年2月01日(日) 15:18
by Dixq (管理人)
>>kazuoniさん

あれは譜面をどうやって作りやすくするかが勝負ですよね^^;
作るのも難しいし・・。何か画期的なインターフェイスを考える必要がありそう・・。
ダンスマニアとかのデータってどうなってるかとか参考にしてみるといいかもしれませんb

>>s-rushさん

さしあたりこんなの作ってみましたが、どうでしょう?
ゲームプログラミングの館24章
http://dixq.net/g/#24
を拡張させたものです。
特に歩きながらロードはしていません。
というのも、100x100であろうが、1000x1000であろうが、BYTE型位なら
大した容量にならないので、読み込んだ方がコードが複雑にならなくていいと思ったからです。

スクロール処理を付け加えただけです。
後、コードが少し長いので関数わけしました。

http://dixq.net/code/ForS-rush1.cpp

Re:キャラクターを動かすプログラム

Posted: 2009年2月01日(日) 16:05
by s-rush
>> Dixqさん
早速のサンプルデータありがとうございます。
解析をしてみたのですが、Graph()関数のlxとchxの変数を何のために
使用しているのかが分かりませんでした。

chx(chy)は現在の座標を格納していることは分かるのですが、lx(ly)の意味が分からなかったので、
chxを何に利用しているのか分からないです。

Re:キャラクターを動かすプログラム

Posted: 2009年2月01日(日) 16:13
by Dixq (管理人)
スクロールする時、3パターンにわけて描画する必要があることはわかりますか?
まず、上下移動は無いものとして、左右だけ移動するものとして考えて下さい。


・キャラが一番左にいる時

 キャラが右に移動すると、マップは固定、キャラが右に移動します。


・キャラが中央にいる時
 
 キャラが左右に移動すると、キャラは中央に固定、マップ(背景)が左右に移動します。


・キャラが一番右にいる時

 キャラが左に移動すると、マップは固定、キャラが左に移動します。


(これについては実際にプログラムをコンパイルして実行していただけたらわかると思います。)
その為、3種類にわけて描画する座標を用意しているのです。
lxは背景描画する際の座標の引き算に使用するもので、chxはキャラの本当の座標ch.xから実際に描画すべき座標に変換したものです。

Re:キャラクターを動かすプログラム

Posted: 2009年2月01日(日) 17:13
by s-rush
ということは

キャラが中央にいるとき、
キャラの座標は中央で固定され、(裏の)マップが移動する。
キャラが端にいるとき、
マップが固定され、キャラが移動する(座標が移動に対応した値に変動する)

という感じですかね。

あとはマップのつながりなのですが、これも通常のスクロールみたいにスムーズにするには
どうすればいいのですか?

たとえば
int map1[7][7];
int map2[7][7];
を用意し、
マップ1      マップ2
0 0 1 1 1 0 0     0 0 0 0 0 0 0
0 1 1 1 1 1 0     0 1 1 1 1 1 0
0 1 1 1 1 1 0     0 1 1 1 1 1 0
0 1 1 1 1 1 0     0 1 1 1 1 1 0
0 1 1 1 1 1 0     0 1 1 1 1 1 0
0 1 1 1 1 1 0     0 1 1 1 1 1 0
0 0 0 0 0 0 0     0 0 1 1 1 0 0

というマップデータでそれぞれを初期化

このときマップ1、マップ2間を移動するときに
マップの切り替えをせずにスクロールして移動するにはどのようにすればいいのでしょうか?
マップの切り替えをするのであれば、できそうなのですが。

Re:キャラクターを動かすプログラム

Posted: 2009年2月01日(日) 18:15
by Dixq (管理人)
マップがわかれているのですか?
もし全部繋がっているマップならそのままくっつければいいだけじゃないでしょうか?

map1[7][7]とmap2[7][7]は横にくっつけるなら

map[7][7*2]

に一緒に出来ますよね。
さっきのプログラムの例では[30][30]でしたね。その部分にあたります。

Re:キャラクターを動かすプログラム

Posted: 2009年2月01日(日) 18:34
by s-rush
まだ作ってはいないのですが、
マップエディタを使用して別々のマップを作ってから、
それぞれのマップをつなげようと思っていました。
そうしないとエディタの容量オーバー?で、フィールドマップ全体を
作り出すことができなかったので・・・

map1[a] map2[c][d] map3[e][f]・・・のすべてのマップデータを
大きなマップを表すfield_map[α][β]にまとめることはできるのでしょうか?

Re:キャラクターを動かすプログラム

Posted: 2009年2月02日(月) 12:03
by s-rush
移動処理の関数を大きなプログラム内に組み込んでみたのですが、
キーを入力してもなにも反応がないです。
Escキーを入力するとプログラムが終了するので、認識はしていると思うのですが、
方向キーや、移動速度切り替えのキー(Z,X,Cのいずれか)を入力しても反応がありません。
その制御はOperateCharactor()で行っています。

コードが長くカオスなプログラムですが、一度見てもらえないでしょうか?
原因が分かりません。

あと画像を取り込んでいるはずなのに、map_chip[0]内に入っていないようで、
画像を表示できませんでした。
ちゃんと指定した場所に画像は入っています。

フォルダ内
main.cpp              メイン
char_calc.cpp     キャラ計算
graph.cpp       自キャラとマップの描画
load.cpp        画像のロード
Key.cpp        キー入力の処理
GV.h          変数宣言
function.h       関数宣言
中身は以上のようになっています。

Re:キャラクターを動かすプログラム

Posted: 2009年2月02日(月) 13:19
by kazuoni
大きくなっていくと、やはりプロジェクトごとアップしたほうがよいかと思います^^;
環境が分かりませんが、もしブレークポイントを立てれるならば
前回もいいましたが、ブレークポイントを立てて変数の移り変わりを見てみてください。
初めのうちは不具合をブレークポイントによって見つけられることが多いです。
(自分は熟練ではないのでよく頼りますが^^;)
まず方向キーだけ見ていってみてください。
・Key[/url]の変化
・ch.~~の変化(移動時)
・描写周辺
のあたりをあたってみてください。

Re:キャラクターを動かすプログラム

Posted: 2009年2月02日(月) 15:49
by s-rush
>>kazuoniさん
ブレークポイントと呼べるか分からないですが、
移動時のch.stの値の変化が見れるようにはしてあるんですが、
変化がありませんでした。

今外出中なので、より変化が分かるように改変してからプロジェクトごとアップさせていただきます。

Re:キャラクターを動かすプログラム

Posted: 2009年2月02日(月) 17:27
by kazuoni
環境は何を使っていますか?
Visual C++はおススメです。
ただちょっと重いですけど^^;
eclipseとかでもよいと思いますが。
ブレークポイントを立てることによって、
実行を停止し、その時の変数の値を見ることができます。

もっと使いやすい環境があるかも知れませんが、
自分はVisual C++で大満足しています。
(っというか使いこなせていないのですが・・・w)

Re:キャラクターを動かすプログラム

Posted: 2009年2月02日(月) 22:57
by s-rush
開発環境はVC++ 2008 EEです^^
確かに少し重いですよね。

値が変化するたびにその変数の中身を表示できるようにしてから、
プロジェクトごとアップさせていただきます。

まだ解決しなければ、新しいスレを立てさせていただきますので、
その時はよろしくお願いします。

Re:キャラクターを動かすプログラム

Posted: 2009年2月02日(月) 23:17
by kazuoni
ブレークポイントは添付画像のように
コードの左側をクリックすると赤丸が表示されます。
実行中はここを通る時に、停止します。

(UPできてるかな^^;)

Re:キャラクターを動かすプログラム

Posted: 2009年2月02日(月) 23:36
by s-rush
>実行中はここを通る時に、停止します。
1つ思ったのですが、もし2か所マークを付けていたらどうなるのでしょうか?

Re:キャラクターを動かすプログラム

Posted: 2009年2月02日(月) 23:58
by kazuoni
その行を通るたびに停止します。
何か所でも制限はありません。
ただ、変数はスコープ内のものしか見ることはできません。
(グローバル変数は常に見ることができます。)

Re:キャラクターを動かすプログラム

Posted: 2009年2月03日(火) 00:03
by s-rush
>kazuoniさん
わざわざ教えていただきありがとうございます。
次からはデバッグの際、利用してみます。


ー追伸ー
パソコンの電源を落とした後に再度プログラムを実行させたところ、
なぜかうまいこといきました^^
コードをいじっていないのになぜでしょうか?

Re:キャラクターを動かすプログラム

Posted: 2009年2月03日(火) 00:20
by kazuoni
>コードをいじっていないのになぜでしょうか?
断定はできないですけど、
たまたまの可能性が高いです。。
・キーボードの無線が届いていなかった
・Zボタンを押しているつもりがALTを押していた
・・・
などを除いてですが^^;

実行ファイルのみをアップしてもらえれば動作確認はしますが、
自分で何度も何度も実行してみるが一番いいです^^
(この作業で自分はJustyさんに何度もお世話になりました。。本当にありがとうございました・・・w)

質問:ゲームプログラミングの館での内容

Posted: 2009年2月16日(月) 06:11
by min
DXライブラリとうの勉強を大変有難くサイト内でさせてもらっているのですが、

10. 入力状態を取得する。 というテーマの中にあるプログラムで

Enterが押されている間ループするっていうのは、おかしいんじゃないかって思ったんですけど

どうでしょうか。

押されてない間だからこそループするので、

終了しないんじゃないかと思ったんですがどうでしょうか。

気になってしまもったのでよろしくお願いします。

Re:質問:ゲームプログラミングの館での内容

Posted: 2009年2月16日(月) 07:48
by SCI
ここの部分ですね?
while( CheckHitKey( KEY_INPUT_RETURN ) == 0 ){//ENTERが押されている間ループ
「押されるまで」でしょうね。
ただ、プログラム的には内容に忠実なので、コメントの誤記だと思います。

Re:質問:ゲームプログラミングの館での内容

Posted: 2009年2月16日(月) 08:22
by min
やっぱり、そうでしたか

スッキリしました

ありがとうございますm(__)m