ページ 11

龍神録の9章で自機の画像を差し替えながらの移動が上手くいかない

Posted: 2011年9月16日(金) 19:29
by dast
何度も何度もお世話になっています。龍神録プログラムをみながらプログラミングの勉強をしている者です。
「左右移動をするときは自機の画像を左右移動用に差し替える」ようにプログラムを組んだのですが、それを実際に動かすと自機がキーに合わせて動いてくれません。ただ左右に動かすだけならキーに合わせて動きます。これをちゃんとキーに合わせて画像を差し替えつつ動くようにすればどうすればいいでしょうか?ご指導のほどよろしくお願いします。

char.cpp

コード:

#include "../ヘッダー/GV.h"

void calc_ch(){//画像ループ用関数
	ch.cnt++;
	ch.img=(ch.cnt%48)/12;
}

void calc_move(){
	if(CheckStatePad(configpad.left)>0)//左に押されていたら
		ch.cnt+=8;//←‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐この行を追加すると自機が動かなくなる
		ch.x-=2;//座標を左に
	if(CheckStatePad(configpad.right)>0)//右に押されていたら
		ch.cnt+=4;//←‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐この行を追加すると自機が動かなくなる
		ch.x+=2;//座標を右に
}
graph.cpp

コード:

#include "../ヘッダー/GV.h"

void graph_ch(){
	DrawRotaGraph(ch.x,444,1.0,0.0,img[ch.cnt%48/12],TRUE);
}//graph_ch()の中にimgの0番(自機の上向き画像)の作画作業を入れる

void graph_board(){
	DrawGraph(0,0,img_board10,TRUE);
}


void graph_main(){//描画メイン
	graph_ch();
	graph_board();
}//graph_main()の中にgraph_ch()を入れる
ini.cpp

コード:

#include "../ヘッダー/GV.h"

//初期化関数
void first_ini(){//初期化
	ch.x=FIELD_MAX_X/2;//初期の自機座標の設定

	configpad.left=1;
	configpad.right=2;
	configpad.shot=0;
	configpad.bom=4;
	configpad.start=7;
}
key.cpp

コード:

#include "../ヘッダー/GV.h"

unsigned int stateKey[256];

int GetHitKeyStateAll_2(){//ここからGetHitKeyStateAll_2()関数(現在のキー入力処理を行う)
    char GetHitKeyStateAll_Key[256];
    GetHitKeyStateAll( GetHitKeyStateAll_Key );
    for(int i=0;i<256;i++){
        if(GetHitKeyStateAll_Key[i]==1) stateKey[i]++;
        else                            stateKey[i]=0;
    }
    return 0;
}//ここまでGetHitKeyStateAll_2()関数(受け取ったキー番号の現在のキー入力状態を返す)
int CheckStateKey(unsigned char Handle){//ここからCheckStateKey(unsigned char Handle)関数(受け取ったキー番号の現在の入力状態を返す)
        return stateKey[Handle];
}//ここまでCheckStateKey(unsigned char Handle)関数

//パッドの入力状態を入れる変数(struct.h参照)
pad_t pad;

//引数1と引数2のうち大きい方を引数1に代入する
void input_pad_or_key(int *p, int k){
	*p = *p>k ? *p : k;
}

//パッドとキーボードの両方の入力状態をチェックする関数
void GetHitPadStateAll(){
	int i,PadInput,mul=1;
	PadInput = GetJoypadInputState(DX_INPUT_PAD1);//パッドの入力状態を取得
	for(i=0;i<16;i++){
		if(PadInput & mul) pad.key[i]++;
		else pad.key[i]=0;
		mul*=2;
	}
	input_pad_or_key(&pad.key[configpad.left]   ,CheckStateKey(KEY_INPUT_LEFT));
	input_pad_or_key(&pad.key[configpad.right]  ,CheckStateKey(KEY_INPUT_RIGHT));
	input_pad_or_key(&pad.key[configpad.shot]   ,CheckStateKey(KEY_INPUT_A));
	input_pad_or_key(&pad.key[configpad.bom]    ,CheckStateKey(KEY_INPUT_S));
	input_pad_or_key(&pad.key[configpad.start]  ,CheckStateKey(KEY_INPUT_X));
}

//渡されたパッドキーの入力状態を返す。返り値が-1なら不正
int CheckStatePad(unsigned int Handle){
	if(0<=Handle && Handle<PAD_MAX){
		return pad.key[Handle];
	}
	else{
		printfDx("CheckStatePadに渡した値が不正です\n");
		return -1;
	}
}
load.cpp

コード:

#include "../ヘッダー/GV.h"
void load(){//データをロードする
	img_board10 = LoadGraph("画像/システム/枠.png");
	img_back10 = LoadGraph("画像/背景/神社周辺.png");
	LoadDivGraph("画像/キャラグラ/自機.png",12,4,3,38,41,img);
}
main01.cpp

コード:

#define GLOBAL_INSTANCE
#include "../ヘッダー/GV.h"

//ループで必ず行う3大処理
int ProcessLoop(){
    if(ProcessMessage()!=0)return -1;//プロセス処理がエラーなら-1を返す
    if(ClearDrawScreen()!=0)return -1;//画面クリア処理がエラーなら-1を返す
    GetHitKeyStateAll_2();//現在のキー入力処理を行う
	GetHitPadStateAll();//現在のパッド入力処理を行う
    return 0;
}


int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
    ChangeWindowMode(TRUE);//ウィンドウモード
    if(DxLib_Init() == -1 || SetDrawScreen( DX_SCREEN_BACK )!=0) return -1;//初期化と裏画面化

    while(ProcessLoop()==0){//ProcessLoopの内容を行う
		switch(func_state){
			case 0://func_stateが0の時
				load();//function.hの関数load()を実行する
				first_ini();//function.hの関数first_ini()を実行する
				func_state = 100;//func_stateを100にする
				break;
			case 100:
				graph_main();//function.hの関数graph_main()を実行する
				calc_ch();//function.hの関数calc_ch()を実行する

				break;
			default://上記のcase以外の場合
				printfDx("不明なfunc_state%d\n",func_state);
				break;
		}

		if(CheckStateKey(KEY_INPUT_ESCAPE)==1)break;//エスケープが入力されたらブレイク



        //ココ!!




        ScreenFlip();

    }

    DxLib_End();
    return 0;
}

define.h

コード:


#define FIELD_MAX_X 619
#define FIELD_X 20
//パッドキーの最大数
#define PAD_MAX 16

#include"struct.h"
function.h

コード:

//graph.cpp
GLOBAL void graph_main();//描画メイン

//key.cpp
GLOBAL int GetHitKeyStateAll_2();//現在のキー入力を行う
GLOBAL int CheckStateKey(unsigned char Handle);//受け取ったキー番号の現在の入力状態を返す

//load.cpp
GLOBAL void load();//データをロードする

//ini.ccp
GLOBAL void first_ini();//初期化する

//char.cpp
GLOBAL void calc_ch();//画像のループさせる為の準備

//key.cpp
GLOBAL void GetHitPadStateAll();
GLOBAL int CheckStatePad(unsigned int Handle);
GV.h

コード:

#include "DxLib.h"
#include "define.h"

#ifdef GLOBAL_INSTANCE
#define GLOBAL
#else
#define GLOBAL extern
#endif

#include"function.h"//関数宣言(function.hの読み込み)

//画像用変数宣言部分
GLOBAL int img[12];//自機画像
GLOBAL int img_board10;//枠画像
GLOBAL int img_back10;//一面背景

//構造体変数宣言部分
GLOBAL ch_t ch;

//メインループ用変数宣言部分
GLOBAL int func_state;

//コントローラー用構造体変数宣言部分
GLOBAL configpad_t configpad;
struct.h

コード:

//キャラクタに関する構造体
typedef struct{
	int cnt;       //画像処理の為のカウンタ
	int num;       //残機数
	int score;     //スコア
	int mutekicnt; //無敵状態とカウント
	int img;       //画像
	double x,y;    //座標
}ch_t;

//コントローラに関する構造体
typedef struct{
	int key[PAD_MAX];
}pad_t;

//コンフィグに関する構造体
typedef struct{
	int left,right, shot, bom, start;
}configpad_t;

Re: 龍神録の9章で自機の画像を差し替えながらの移動が上手くいかない

Posted: 2011年9月16日(金) 19:54
by box
dast さんが書きました: 「左右移動をするときは自機の画像を左右移動用に差し替える」ようにプログラムを組んだのですが、それを実際に動かすと自機がキーに合わせて動いてくれません。

コード:

void calc_move(){
	if(CheckStatePad(configpad.left)>0)//左に押されていたら
		ch.cnt+=8;//←‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐この行を追加すると自機が動かなくなる
		ch.x-=2;//座標を左に
	if(CheckStatePad(configpad.right)>0)//右に押されていたら
		ch.cnt+=4;//←‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐この行を追加すると自機が動かなくなる
		ch.x+=2;//座標を右に
}
この関数を呼び出していないように見えます。私の見間違え、あるいは提示されていない部分で実行しているならばよいのですが…。

Re: 龍神録の9章で自機の画像を差し替えながらの移動が上手くいかない

Posted: 2011年9月16日(金) 19:58
by h2so5
if文のぶら下がりによる典型的なミスです。
分かりやすくするとこうなります。

コード:

    if(CheckStatePad(configpad.left)>0)//左に押されていたら
        ch.cnt+=8;//←‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐この行を追加すると自機が動かなくなる

    ch.x-=2;//座標を左に

    if(CheckStatePad(configpad.right)>0)//右に押されていたら
        ch.cnt+=4;//←‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐この行を追加すると自機が動かなくなる

    ch.x+=2;//座標を右に


Re: 龍神録の9章で自機の画像を差し替えながらの移動が上手くいかない

Posted: 2011年9月17日(土) 02:03
by dast
>>boxさん
すみません。プログラムを調べるときに何度も関数を呼び出す文をつけたり消したりしていたのでその文を消した状態のmain01.cppとfunction.hを書き込んでしまったようです。申し訳ありません。正しくは次の通りです。

main01.cpp

コード:

#define GLOBAL_INSTANCE
#include "../ヘッダー/GV.h"

//ループで必ず行う3大処理
int ProcessLoop(){
    if(ProcessMessage()!=0)return -1;//プロセス処理がエラーなら-1を返す
    if(ClearDrawScreen()!=0)return -1;//画面クリア処理がエラーなら-1を返す
    GetHitKeyStateAll_2();//現在のキー入力処理を行う
	GetHitPadStateAll();//現在のパッド入力処理を行う
    return 0;
}


int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
    ChangeWindowMode(TRUE);//ウィンドウモード
    if(DxLib_Init() == -1 || SetDrawScreen( DX_SCREEN_BACK )!=0) return -1;//初期化と裏画面化

    while(ProcessLoop()==0){//ProcessLoopの内容を行う
		switch(func_state){
			case 0://func_stateが0の時
				load();//function.hの関数load()を実行する
				first_ini();//function.hの関数first_ini()を実行する
				func_state = 100;//func_stateを100にする
				break;
			case 100:
				graph_main();//function.hの関数graph_main()を実行する
				calc_ch();//function.hの関数calc_ch()を実行する
                calc_move();
				break;
			default://上記のcase以外の場合
				printfDx("不明なfunc_state%d\n",func_state);
				break;
		}

		if(CheckStateKey(KEY_INPUT_ESCAPE)==1)break;//エスケープが入力されたらブレイク



        //ココ!!




        ScreenFlip();

    }

    DxLib_End();
    return 0;
}

function.h

コード:

//graph.cpp
GLOBAL void graph_main();//描画メイン

//key.cpp
GLOBAL int GetHitKeyStateAll_2();//現在のキー入力を行う
GLOBAL int CheckStateKey(unsigned char Handle);//受け取ったキー番号の現在の入力状態を返す

//load.cpp
GLOBAL void load();//データをロードする

//ini.ccp
GLOBAL void first_ini();//初期化する

//char.cpp
GLOBAL void calc_ch();//画像のループさせる為の準備
GLOBAL void calc_move();

//key.cpp
GLOBAL void GetHitPadStateAll();
GLOBAL int CheckStatePad(unsigned int Handle);
>>h2so5さん
ご指摘を受けてchar.cppを次のように変更して見たところ、動くようにはなったのですが動くときに画像が変更されなくなってしまいました。
・・・というよりはどうやらchar.cppにあるch.img=~の文がどれ一つ適用されていないようです。
この場合どうやったらch.img=~が適用されるようになるのでしょうか?

char.cpp

コード:

#include "../ヘッダー/GV.h"

void calc_ch(){//画像ループ用関数
	ch.cnt++;
	ch.img=(ch.cnt%48)/12;
}

void calc_move(){
	if(CheckStatePad(configpad.left)>0){//左に押されていたら
		ch.img+=8;
		ch.x-=2;//座標を左に
	}
	if(CheckStatePad(configpad.right)>0){//右に押されていたら
		ch.img+=4;
		ch.x+=2;//座標を右に
	}
}

Re: 龍神録の9章で自機の画像を差し替えながらの移動が上手くいかない

Posted: 2011年9月17日(土) 05:06
by box
dast さんが書きました:

コード:

		ch.img+=8;
		ch.img+=4;
この箇所、前のコードでは確かch.cntだったような気がします。
結局のところ、ch.imgとch.cntのどちらに8とか4とかを加えたいのでしょうか?

Re: 龍神録の9章で自機の画像を差し替えながらの移動が上手くいかない

Posted: 2011年9月17日(土) 10:31
by dast
前までのは間違いでした。ch.cntの方に数を加えると不具合が生じてしまうので。
構想としては
・ループするごとに1づつ増えていくch.cntを設定する
・ch.imgの番号を(ch.img%48)/12と設定することでch.cntが0から12進むごとに画像が切り替わり48になったら0に戻る
・右に押している間のみch.imgは4増える
・左に押している間のみch.imgは8増える
という風にしているつもりです。ちなみに画像の番号としては次のようになっています
|[0]|[1]| [2]| [3]|静止時の画像
|[4]|[5]| [6]| [7]|右移動時の画像
|[8]|[9]|[10]|[11]|左移動時の画像

Re: 龍神録の9章で自機の画像を差し替えながらの移動が上手くいかない

Posted: 2011年9月17日(土) 15:29
by box
dast さんが書きました: ・ch.imgの番号を(ch.img%48)/12と設定することでch.cntが0から12進むごとに画像が切り替わり48になったら0に戻る
(ch.cnt%48)/12
ですね?

ところで、
dast さんが書きました: 画像の番号としては次のようになっています
|[0]|[1]| [2]| [3]|静止時の画像
|[4]|[5]| [6]| [7]|右移動時の画像
|[8]|[9]|[10]|[11]|左移動時の画像
こういった、プログラム内部での考え方に関する内容をコメントとして書いておく方が
いいのではないかと思います。
dast さんが書きました:

コード:

            case 0://func_stateが0の時
                load();//function.hの関数load()を実行する
                first_ini();//function.hの関数first_ini()を実行する
                func_state = 100;//func_stateを100にする
                break;
            case 100:
                graph_main();//function.hの関数graph_main()を実行する
                calc_ch();//function.hの関数calc_ch()を実行する
こういうコメントは、「コードを見ればわかる」わけで、なくてもいいのではないかなと思います。

あと、よくわからないのは、変数func_stateの存在意義です。本当に必要なのでしょうか。

Re: 龍神録の9章で自機の画像を差し替えながらの移動が上手くいかない

Posted: 2011年9月17日(土) 18:13
by ISLe
dast さんが書きました:この場合どうやったらch.img=~が適用されるようになるのでしょうか?
描画しているのはgraph.cppのgraph_ch関数ですよね。
ch.imgを使ってないのでは?

Re: 龍神録の9章で自機の画像を差し替えながらの移動が上手くいかない

Posted: 2011年9月18日(日) 00:03
by 否妻
自分も初心者で気になったことがあるのですがトピックを立てるまでもないので質問させてください

loadgraphでロードした画像のデータが入った変数って戻り値とか引数とかで
描画関数に渡さなくてもよいのですか? ただのローカル変数とは違うのでしょうか?

Re: 龍神録の9章で自機の画像を差し替えながらの移動が上手くいかない

Posted: 2011年9月18日(日) 00:05
by COFE
>否妻さん
専用のトピックを自分で作ってください
どんな些細な内容でもこのフォーラムの人なら丁寧に教えてくれますよ
ここはdastさんのトピックということをお忘れなく

Re: 龍神録の9章で自機の画像を差し替えながらの移動が上手くいかない

Posted: 2011年9月18日(日) 18:36
by dast
ISLeさんのご指摘通りch.imgを使っていなかったようです。
なのでcnt%48/12の値を入れるimg_cntという変数を用意し、(imgという変数はすでに他で使われてたので)そこの値をキーを押したときに足すという方法でできるようになりました。ありがとうございました。変更した場所は次の通りです。

struct.h

コード:

//キャラクタに関する構造体
typedef struct{
	int cnt;       //画像処理の為のカウンタ
	int imgcnt;
	int num;       //残機数
	int score;     //スコア
	int mutekicnt; //無敵状態とカウント
	int img;       //画像
	double x,y;    //座標
}ch_t;

//コントローラに関する構造体
typedef struct{
	int key[PAD_MAX];
}pad_t;

//コンフィグに関する構造体
typedef struct{
	int left,right, shot, bom, start;
}configpad_t;
graph.cpp

コード:

#include "../ヘッダー/GV.h"

void graph_ch(){
	DrawRotaGraph(ch.x,444,1.0,0.0,img[ch.imgcnt],TRUE);
}//graph_ch()の中にimgの0番(自機の上向き画像)の作画作業を入れる

void graph_board(){
	DrawGraph(0,0,img_board10,TRUE);
}


void graph_main(){//描画メイン
	graph_ch();
	graph_board();
}//graph_main()の中にgraph_ch()を入れる
char.cpp

コード:

#include "../ヘッダー/GV.h"

void calc_ch(){//画像ループ用関数
	ch.cnt++;
	ch.imgcnt=(ch.cnt%48)/12;
}

void calc_move(){
	if(CheckStatePad(configpad.left)>0){//左に押されていたら
		ch.imgcnt+=8;
		ch.x-=2;//座標を左に
	}
	if(CheckStatePad(configpad.right)>0){//右に押されていたら
		ch.imgcnt+=4;
		ch.x+=2;//座標を右に
	}
}
>>boxさん
コード内のコメントはプログラミング中に書いた私のノート代わりのようなものです。気分を害されたのでしたら謝ります。

それとfunc_state変数は一度画像のロードと初期化の作業を行ってからこれから作るゲーム部分を繰り返すという流れにしたかったのでこういう形にしました。

Re: 龍神録の9章で自機の画像を差し替えながらの移動が上手くいかない

Posted: 2011年9月18日(日) 19:10
by box
別に気分を害してなどいないです。

コード:

    i = 1; // iに1を代入する
というようなコメントは冗長であって、自分だったら書かないな、と思っただけです。