マウスクリック位置表示がデバックではOKなのに実行では1つ目だけ表示されるのはなぜでしょう?

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
うさぎ太郎
記事: 3
登録日時: 11年前

マウスクリック位置表示がデバックではOKなのに実行では1つ目だけ表示されるのはなぜでしょう?

#1

投稿記事 by うさぎ太郎 » 11年前

[1] 質問文
 [1.1] 自分が今行いたい事は何か
  海戦ゲームを作成中で、まずマウスクリックした位置に丸を表示させ、一度クリックした所を白抜き丸にして履歴を残したいと思っています。
 [1.2] どのように取り組んだか(プログラムコードがある場合記載)
  「龍神」をベースにして、以下のコードように行っています。
char.cpp

コード:

#include "../include/GV.h"

//キャラクタ画像計算(24周期で1周。4種類の画像をループ)
void calc_ch(){
 if(ch.cnt==0 && ch.flag==2){ //今の瞬間死んだら
  ch.x=FIELD_MAX_X/2;
  ch.y=FIELD_MAX_Y+30;
  ch.mutekicnt++; //無敵状態へ
 }
	if(ch.flag==2){ //死んで浮上中なら
		unsigned int push=CheckStatePad(configpad.left)+
			CheckStatePad(configpad.right)+
			CheckStatePad(configpad.up)+
			CheckStatePad(configpad.down);
		ch.y-=1.5; //キャラ(自機)を上に上げる
		//1秒以上か、キャラがある程度上にいて、何か押されたら
		if(ch.cnt>60 || (ch.y<FIELD_MAX_Y-20 && push)){
			ch.cnt=0;
			ch.flag=0; //キャラステータスを元に戻す
		}
	}
	if(ch.mutekicnt>0){ //無敵中なら(カウントが0でないなら)
		ch.mutekicnt++;
		if(ch.mutekicnt>120) //無敵中が2秒以上だったら
			ch.mutekicnt=0; //無敵解除(元に戻す)
	}

    ch.cnt++; //キャラクタのカウントアップ
    ch.img=(ch.cnt%24)/6; //現在の画像決定
}

void ch_move(){//キャラクタの移動制御
        int i,sayu_flag=0,joge_flag=0;
        double x,y,mx,my,naname=1;
        double move_x[4]={-4.0,4.0,0,0},move_y[4]={0,0,4.0,-4.0};//{左,右,下,上}のスピード
        int inputpad[4];
        inputpad[0]=CheckStatePad(configpad.left); inputpad[1]=CheckStatePad(configpad.right);
        inputpad[2]=CheckStatePad(configpad.down); inputpad[3]=CheckStatePad(configpad.up);

        if(CheckStatePad(configpad.left)>0)//左キーが押されていたら
                ch.img+=4*2;//画像を左向きに
        else if(CheckStatePad(configpad.right)>0)//右キーが押されていたら
                ch.img+=4*1;//画像を右向きに

        for(i=0;i<2;i++)//左右分
                if(inputpad[i]>0)//左右どちらかの入力があれば
                        sayu_flag=1;//左右入力フラグを立てる
        for(i=2;i<4;i++)//上下分
                if(inputpad[i]>0)//上下どちらかの入力があれば
                        joge_flag=1;//上下入力フラグを立てる
        if(sayu_flag==1 && joge_flag==1)//左右、上下両方の入力があれば斜めだと言う事
                naname=sqrt(2.0);//移動スピードを1/ルート2に

        for(int i=0;i<4;i++){//4方向分ループ
                if(inputpad[i]>0){//i方向のキーボード、パッドどちらかの入力があれば
                        x=ch.x , y=ch.y;//今の座標をとりあえずx,yに格納
                        mx=move_x[i];   my=move_y[i];//移動分をmx,myに代入
                        if(CheckStatePad(configpad.slow)>0){//低速移動なら
                                mx=move_x[i]/3; my=move_y[i]/3;//移動スピードを1/3に
                        }
                        //x+=mx , y+=my;//スピード1より速い
                        x+=mx/naname , y+=my/naname;//今の座標と移動分を足す
                        if(!(x<10 || x>FIELD_MAX_X-10 || y<5 || y>FIELD_MAX_Y-5)){//計算結果移動可能範囲内なら
                                ch.x=x , ch.y=y;//実際に移動させる
                        }
                }
        }
}

void own_set(){ //自軍セット
	int Cr = GetColor( 255 , 0 , 255 ) ;

	int MouseInput = GetMouseInput();
	while((MouseInput & MOUSE_INPUT_LEFT) == 0){
	    // メッセージ処理
        if( ProcessMessage() == -1 )
        {
            break ;    // エラーが起きたらループから抜ける
        }
		MouseInput = GetMouseInput() ;

	}
	int MouseX , MouseY ;
	GetMousePoint( &MouseX , &MouseY ) ;
	DrawCircle( MouseX , MouseY , 10 , Cr , TRUE ) ;
	if(draw_count<OWN_MAX){
		own[draw_count].x=MouseX;
		own[draw_count].y=MouseY;
		draw_count++;
	}
	int Cr_y = GetColor( 0, 255 , 255 ) ;
	for(int i=0; i<OWN_MAX; i++){
		DrawCircle( own[i].x , own[i].y , 10 , Cr_y , FALSE ) ;
	}

}

上の内、void own_set(){ //自軍セットが自分で追加している部分です。

以下のコードは、メイン画面のステージ座標を表示しています。
graph.cpp

コード:

#include "../include/GV.h"

void graph_enemy(){
        int i;
        for(i=0;i<ENEMY_MAX;i++){
                if(enemy[i].flag==1){
	                DrawRotaGraphF(enemy[i].x+FIELD_X,enemy[i].y+FIELD_Y,1.0f,0.0f,img_enemy[0][enemy[i].img],TRUE);
                }
        }
}

void graph_ch(){
	if(ch.mutekicnt%2==0)
		DrawRotaGraphF(ch.x+FIELD_X,ch.y+FIELD_Y,1.0f,0.0f,img_ch[0][ch.img],TRUE);
}

void graph_board(){
	//座標ステージ表示
    int Cr = GetColor( 255 , 255 , 255 ) ;    // 白色の値を取得
	//for(int stage_x=FIELD_X; stage_x<640; stage_x=stage_x+INTERVAL)
	//	DrawLine(stage_x, FIELD_Y, stage_x, 480-FIELD_Y, Cr) ;    // 縦線を描画
	//for(int stage_y=FIELD_Y; stage_y<480; stage_y=stage_y+INTERVAL)
	//	DrawLine(FIELD_X, stage_y, 640-FIELD_X, stage_y, Cr) ;    // 横線を描画
	//自軍
	for(int stage_x=FIELD_X+30; stage_x<330; stage_x=stage_x+INTERVAL)
		DrawLine(stage_x, FIELD_Y+20, stage_x, 480-20-FIELD_Y, Cr) ;    // 縦線を描画
	for(int stage_y=FIELD_Y+20; stage_y<480-10; stage_y=stage_y+INTERVAL)
		DrawLine(FIELD_X+30, stage_y, 320, stage_y, Cr) ;    // 横線を描画
	//敵軍
	for(int stage_x=350; stage_x<640; stage_x=stage_x+INTERVAL)
		DrawLine(stage_x, FIELD_Y+20, stage_x, 480-20-FIELD_Y, Cr) ;    // 縦線を描画
	for(int stage_y=FIELD_Y+20; stage_y<480-10; stage_y=stage_y+INTERVAL)
		DrawLine(350, stage_y, 640-FIELD_X, stage_y, Cr) ;    // 横線を描画
	//テキスト表示
    // 白色の値を取得
    int Cr_t = GetColor( 255 , 255 , 255 ) ;

    // 文字列の描画
	//縦軸
    DrawString( 40 , 45 , "1" , Cr_t );
    DrawString( 40 , 65 , "2" , Cr_t );
    DrawString( 40 , 85 , "3" , Cr_t );
    DrawString( 40 , 105 , "4" , Cr_t );
    DrawString( 40 , 125 , "5" , Cr_t );
    DrawString( 40 , 145 , "6" , Cr_t );
    DrawString( 40 , 165 , "7" , Cr_t );
    DrawString( 40 , 185 , "8" , Cr_t );
    DrawString( 40 , 205 , "9" , Cr_t );
    DrawString( 35 , 225 , "10" , Cr_t );
    DrawString( 35 , 245 , "11" , Cr_t );
    DrawString( 35 , 265 , "12" , Cr_t );
    DrawString( 35 , 285 , "13" , Cr_t );
    DrawString( 35 , 305 , "14" , Cr_t );
    DrawString( 35 , 325 , "15" , Cr_t );
    DrawString( 35 , 345 , "16" , Cr_t );
    DrawString( 35 , 365 , "17" , Cr_t );
    DrawString( 35 , 385 , "18" , Cr_t );
    DrawString( 35 , 405 , "19" , Cr_t );
    DrawString( 35 , 425 , "20" , Cr_t );
    //DrawString( 35 , 445 , "21" , Cr_t );
    //DrawString( 35 , 465 , "22" , Cr_t );
	//横軸
    DrawString( 77 , 10 , "A" , Cr_t );
    DrawString( 97 , 10 , "B" , Cr_t );
    DrawString( 117 , 10 , "C" , Cr_t );
    DrawString( 137 , 10 , "D" , Cr_t );
    DrawString( 157 , 10 , "E" , Cr_t );
    DrawString( 177 , 10 , "F" , Cr_t );
    DrawString( 197 , 10 , "G" , Cr_t );
    DrawString( 217 , 10 , "H" , Cr_t );
    DrawString( 237 , 10 , "I" , Cr_t );
    DrawString( 257 , 10 , "J" , Cr_t );
    DrawString( 277 , 10 , "K" , Cr_t );
    DrawString( 297 , 10 , "L" , Cr_t );
    //DrawString( 317 , 10 , "M" , Cr_t );
    DrawString( 365 , 10 , "a" , Cr_t );
    DrawString( 385 , 10 , "b" , Cr_t );
    DrawString( 405 , 10 , "c" , Cr_t );
    DrawString( 425 , 10 , "d" , Cr_t );
    DrawString( 445 , 10 , "e" , Cr_t );
    DrawString( 465 , 10 , "f" , Cr_t );
    DrawString( 485 , 10 , "g" , Cr_t );
    DrawString( 505 , 10 , "h" , Cr_t );
    DrawString( 525 , 10 , "i" , Cr_t );
    DrawString( 545 , 10 , "j" , Cr_t );
    DrawString( 565 , 10 , "k" , Cr_t );
    DrawString( 585 , 10 , "l" , Cr_t );
    //DrawString( 605 , 10 , "m" , Cr_t );
    int Cr_t2 = GetColor( 255 , 0 , 0 ) ;
    DrawString( 177 , 453 , "OWN" , Cr_t2 );
    DrawString( 460 , 453 , "ENEMY" , Cr_t2 );
	

//    DrawGraph(  0,  0,img_board[10],FALSE);
}
//弾丸の描画
void graph_bullet(){
	int i,j;
	SetDrawMode(DX_DRAWMODE_BILINEAR); //線形補完描画
	for(i=0; i<SHOT_MAX; i++){ //敵の弾幕数分ループ
		if(shot[i].flag>0){ //弾幕データがオンなら
			for(j=0; j<SHOT_BULLET_MAX; j++){ //その弾幕が持つ弾の最大数分ループ
				if(shot[i].bullet[j].flag!=0){ //弾データがオンなら
					if(shot[i].bullet[j].eff==1)
						SetDrawBlendMode(DX_BLENDMODE_ADD,255);

					//DrawRotaGraphF(
					//	shot[i].bullet[j].x+FIELD_X,shot[i].bullet[j].y+FIELD_Y,
					//	1.0, shot[i].bullet[j].angle+PI/2,
					//	img_bullet[shot[i].bullet[j].knd][shot[i].bullet[j].col],TRUE);

					DrawRotaGraphF(
						shot[i].bullet[j].x+FIELD_X,shot[i].bullet[j].y+FIELD_Y,
						1.0, shot[i].bullet[j].angle+3.141529/2,
						img_bullet[shot[i].bullet[j].knd][shot[i].bullet[j].col],TRUE);

					if(shot[i].bullet[j].eff==1)
						SetDrawBlendMode(DX_BLENDMODE_NOBLEND,0);
				}
			}
		}
	}
	SetDrawMode(DX_DRAWMODE_NEAREST); //描画形式を戻す
}

//自機ショット描画
void graph_cshot(){
	for(int i=0; i<CSHOT_MAX; i++){
		if(cshot[i].flag>0){
			DrawRotaGraphF(cshot[i].x+FIELD_X,cshot[i].y+FIELD_Y
				,1,0,img_cshot[cshot[i].knd],TRUE);
		}
	}
}


void graph_effect(int knd){
	for(int i=0; i<EFFECT_MAX; i++){
		if(effect[i].flag>0 && effect[i].knd==knd){
			if(effect[i].eff==1) //エフェクトが光エフェクトなら
				SetDrawBlendMode(DX_BLENDMODE_ADD,effect[i].brt);
			if(effect[i].eff==2) //エフェクトがαエフェクトなら
				SetDrawBlendMode(DX_BLENDMODE_ALPHA,effect[i].brt);
			DrawRotaGraphF(effect[i].x+FIELD_X+dn.x
				,effect[i].y+FIELD_Y+dn.y
				,effect[i].r,effect[i].ang,effect[i].img,TRUE);
			if(effect[i].eff==1 || effect[i].eff==2)
				SetDrawBlendMode(DX_BLENDMODE_NOBLEND,0);
		}
	}
}


extern void graph_back_main();

void graph_main(){
	graph_back_main(); //背景描画メイン
	graph_effect(0); //敵が死ぬエフェクト
    graph_enemy(); //敵の描画
	graph_cshot(); //自機ショットの描画

	if(bright_set.brt!=255)SetDrawBright(255,255,255);

    graph_ch(); //自機の描画

	if(bright_set.brt!=255)
		SetDrawBright(bright_set.brt,bright_set.brt,bright_set.brt);
	graph_bullet();

	if(bright_set.brt!=255)SetDrawBright(255,255,255);

    graph_effect(1); //ボムのエフェクト
    graph_effect(2); //ボム線のエフェクト
    graph_effect(3); //ボムキャラのエフェクト

	graph_board(); //ボードの描画
}
さらに、次のコードは描画エリアの設定です。
graph_back.cpp

コード:

#include "../include/GV.h"

void graph_back00(){
	//SetDrawArea(32,16,416,464); //描画可能エリアを設定
	//windowsizeは640,480
	//SetDrawArea(32,16,608,464); //(x1,y1)=(32,16),(x2,y2)=(640-32,480-16)
	SetDrawArea(30,10,611,471); //(x1,y1)=(32,16),(x2,y2)=(640-30+1,480-10+1)
	////0の480上からcount分ずつ下に描画
	DrawGraph(FIELD_X,count%480+FIELD_Y-480,img_back[0],FALSE);
	////0からcount分ずつ下に描画
	DrawGraph(FIELD_X,count%480+FIELD_Y    ,img_back[0],FALSE);
	//SetDrawArea(0,0,640,480); //描画可能エリアを戻す
}

void graph_back_main(){
	graph_back00();
}
そして、以下のコードがメインルーチンです。
main.cpp

コード:


#define GLOBAL_INSTANCE 
#include "../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){//メインループ
		music_ini();
        switch(func_state){
            case 0://初回のみ入る処理
                load();        //データロード
                first_ini();//初回の初期化
                func_state=99;
                break;
            case 99://STGを始める前に行う初期化
                ini();
				load_story();
                func_state=100;
                break;
            case 100://通常処理
    //            calc_ch();    //キャラクタ計算
    //            ch_move();    //キャラクタの移動制御
				//cshot_main(); //自機ショットメイン
    //            enemy_main();//敵処理メイン
				//shot_main(); //敵ショットメイン
				//out_main(); //当たり計算
				//effect_main(); //エフェクトメイン
                graph_main();//描画メイン
				own_set();
                stage_count++;
                break;
            default:
                printfDx("不明なfunc_state\n");
                break;
        }
		music_play();
        if(CheckStateKey(KEY_INPUT_ESCAPE)==1)break;//エスケープが入力されたらブレイク
        ScreenFlip();//裏画面反映
		count++;
    }
    DxLib_End();//DXライブラリ終了処理
    return 0;
}
 [1.3] どのようなエラーやトラブルで困っているか(エラーメッセージが解る場合は記載)
  困っていることは、デバッグでは狙い通り、クリックした位置に丸が表示され、2回目以降のクリックは履歴が白抜き丸で残るようになるのですが、実行するとなぜか一回目だけ履歴が残り後は消えてしまいます。
 [1.4] 今何がわからないのか、知りたいのか
  今後何をしていけばいいのかがわからないので、指針を教えていただけたらと思っています。
  よろしくお願いします。

[2] 環境  
 [2.1] OS : Windows, Linux等々
  Windows7
 [2.2] コンパイラ名 : VC++ 2008EE, Borand C++, gcc等々
  VC++2008EE
[3] その他
 ・どの程度C言語を理解しているか
  メモリの状態をある程度イメージできる程度。
  ゲームはまともに作るのは初めてです。
 ・ライブラリを使っている場合は何を使っているか
  DXライブラリ

※すいません、送信前にプレビューしてみたところ、コードが改行とかうまくいかず間延びしてしまっています。直そうとしてみましたがダメでした。
見づらくてすいません。ソースファイルを添付しましたので、そちらをご覧ください。

以上よろしくお願いします。
添付ファイル
graph.cpp
(6.01 KiB) ダウンロード数: 102 回
main.cpp
(1.78 KiB) ダウンロード数: 96 回
char.cpp
(3.51 KiB) ダウンロード数: 99 回

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

Re: マウスクリック位置表示がデバックではOKなのに実行では1つ目だけ表示されるのはなぜでしょう?

#2

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

雑にしか見てませんが、own配列の初期化が見当たらないようです。
もしかしたら、 draw_countも初期化がないかもしれません。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

うさぎ太郎
記事: 3
登録日時: 11年前

Re: マウスクリック位置表示がデバックではOKなのに実行では1つ目だけ表示されるのはなぜでしょう?

#3

投稿記事 by うさぎ太郎 » 11年前

早速のレスありがとうございます。
申し訳ありません、初期化は別のファイルで行っています。
ini.cppの//ゲームの初期化のvoid ini()です。
載せないですいませんでした。
以下にコード載せます。

ini.cpp

コード:

#include "../include/GV.h"

//渡された情報を構造体に入れる関数
void input_bullet_info(bullet_info_t *binfo,int size_x,int size_y,int col_num,double range){
	binfo->size_x =size_x;  binfo->size_y =size_y;
	binfo->col_num=col_num; binfo->range  =range;
}

//一番最初の初期化
void first_ini(){
        configpad.down=0;
        configpad.left=1;
        configpad.right=2;
        configpad.up=3;
        configpad.bom=4;
        configpad.shot=5;
        configpad.slow=11;
        configpad.start=13;
        configpad.change=6;
		//例:弾0は76×76ピクセルで、5色あり、当たり判定17ピクセル
		input_bullet_info(&bullet_info[0],76, 76, 5,17.0);
		input_bullet_info(&bullet_info[1],22, 22, 6, 4.0);
		input_bullet_info(&bullet_info[2], 5,120,10, 2.5);
		input_bullet_info(&bullet_info[3],19, 34, 5, 2.0);
		input_bullet_info(&bullet_info[4],38, 38,10, 2.0);
		input_bullet_info(&bullet_info[5],14, 16, 3, 3.5);
		input_bullet_info(&bullet_info[6],14, 18, 3, 2.0);
		input_bullet_info(&bullet_info[7],16, 16, 9, 2.5);
		input_bullet_info(&bullet_info[8],12, 18,10, 1.5);
		input_bullet_info(&bullet_info[9],13, 19, 3, 2.0);

}

//ゲームの初期化
void ini(){
        stage_count=1;
        memset(&ch,0,sizeof(ch_t));//自機データの初期化(0)
        ch.x=FIELD_MAX_X/2;
        ch.y=FIELD_MAX_Y*3/4;
        memset(own,0,sizeof(own_t)*OWN_MAX);//ownデータの初期化
        memset(enemy,0,sizeof(enemy_t)*ENEMY_MAX);//敵データの初期化
		memset(enemy_order,0,sizeof(enemy_order_t)*ENEMY_ORDER_MAX);//敵の出現情報初期化
		memset(shot,0,sizeof(shot_t)*SHOT_MAX);
		// 自機ショット用
		memset(cshot,0,sizeof(cshot_t)*CSHOT_MAX);
		ch.power=500;
		//エフェクト用
		memset(effect,0,sizeof(effect_t)*EFFECT_MAX);
		memset(del_effect,0,sizeof(del_effect_t)*DEL_EFFECT_MAX);
		//ボム用
		memset(&bom,0,sizeof(bom_t));
		memset(&bright_set,0,sizeof(bright_set_t));
		memset(&dn,0,sizeof(dn_t));
		bright_set.brt=255;

		//艦隊座標表示用
		draw_count=0;



}


改めて何かありましたらよろしくお願いします。

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

Re: マウスクリック位置表示がデバックではOKなのに実行では1つ目だけ表示されるのはなぜでしょう?

#4

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

部分的にしかない動かせないコードなので、想像でしか書けませんが、問題と関係なくここの処理はマズイことになると思います。
一時的に停止してしまいます。

コード:

    int MouseInput = GetMouseInput();
    while((MouseInput & MOUSE_INPUT_LEFT) == 0){
        // メッセージ処理
        if( ProcessMessage() == -1 )
        {
            break ;    // エラーが起きたらループから抜ける
        }
        MouseInput = GetMouseInput() ;
 
    }
ゲームプログラミンの館にも有るように、後々持て余すような処理は書かないほうが良いです。
「補足資料.11章 書いてはいけない4つの処理」
http://dixq.net/g/h_11.html

> 困っていることは、デバッグでは狙い通り、クリックした位置に丸が表示され、2回目以降のクリックは履歴が白抜き丸で残るようになるのですが、実行するとなぜか一回目だけ履歴が残り後は消えてしまいます。

上記処理は、マウスのクリックが押されるのを待ちますが押されると連続ですり抜けます。
つまり、1フレームに1回draw_count++されて行きます。
これが狙いなら良いですが、狙いではないのならバグで有ることは確かです。
同じ場所に連続でセットされることに成りますから。

どちらかと言うとデバッグの動作のほうが不思議な気がします。
マウスのクリックについても、キーのように押されているフレームを数をカウントして、==1の時だけ処理するようにして下さい。
そうすれば、このwhile((MouseInput & MOUSE_INPUT_LEFT) == 0){のループもいらないはずです。
あと龍神録を見本とするのなら、描画と処理は分けて頂きたいところですね。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

閉鎖

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