突然画面がおかしなことに....

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
onehst
記事: 14
登録日時: 9年前
住所: 東京都

突然画面がおかしなことに....

#1

投稿記事 by onehst » 9年前

ゲーム製作をしていたところ、押されたキーのフレーム数を格納する関数を実装して、
デバックなしで実行してみたところ、実行画面がピンク1色になったり、緑1色になったり
いずれにせよ正常に描画されなくなりました。(音声は正常に出ていますが、やがてフリーズします。)
なお、ほかのプロジェクトは正常に実行されました。

最初は正常に描画されていて、新・ゲームプログラミングの館の2.9章にあるint gpUpdateKey()関数を
main.cppから専用のKey.cppに移したところで上のようなバグになりました。

そのあと、その関数関連の部分をコメントにして実行されないようにしても直りませんでした...
(自分の中では正常に描画されたときに戻した状態だったのですが...)

コンパイルエラーはないため、原因が分からず困惑しています。
どなたかお力を貸していただけませんでしょうか?
おそらく致命的なバグが起きているのだと思われます。一応私が原因があると思う部分だけこの掲示板に
貼りますが、、もし協力してもらえる方で情報が足りないと感じられたならば全てはります。

コード:

//main.cpp
#include "DxLib.h"
#include "GV.h"
#include "extern.h"
#include "define.h"

int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int){
        ChangeWindowMode(TRUE), DxLib_Init(), SetDrawScreen( DX_SCREEN_BACK ); //ウィンドウモード変更と初期化と裏画面設定
	    
        int Count=0;
		load(); //素材のロード 

        // while(裏画面を表画面に反映, メッセージ処理, 画面クリア)
        while( ScreenFlip()==0 && ProcessMessage()==0 && ClearDrawScreen()==0){

                if( Count == 240 ){ // 2秒に一度
                        PlaySoundMem( Handle[0], DX_PLAYTYPE_LOOP ); // 効果音を再生する
				}


              //マップの壁画
				mapdraw();  
              //少年の壁画
				if(BoyFlag)
				boydraw(Count);  
				//敵の壁画
				Enemydraw(Count);
			  //ボード項目の壁画
				Menudraw(Count);
			  //文字の壁画
				Mozidraw(Count);
		      //時間を加算する
                Count++;

        }

        DxLib_End(); // DXライブラリ終了処理
        return 0;
} 

コード:

//draw.cpp
#include "DxLib.h"
#include "define.h"
#include "Class.h"
#include "extern.h"
#include <math.h>

static Player player;
static Enemy ene[5]; //敵のインスタンスを生成
extern bool BoyFlag;
extern int Handle[8],HandleExplode[16];
extern char Sample[4][20];
extern Mozi mozi[5];
//extern int Key[256];

//マップの壁画
void mapdraw(){

	extern int HandleMap[2];

//ボードの作成
   DrawModiGraph(0,0,700,0,700,500,0,500,HandleMap[1],TRUE);
//ステージマップの作成
 for(int i=0;i<9;i++){
	for(int j=0;j<9;j++){
				DrawGraph(20+40*i,10+40*j,HandleMap[0],TRUE);
	}
 }

}

 //キャラとキャラ周りの壁画
 int boydraw(int Time){
	 
	 extern int Handleboy[12];	
	 int img; //画像を巡回させる

 //残機が0で死んだらおしまい(処理しない)
	 if(player.lives<0){
		 if(player.HitRemain==0){
		 PlaySoundMem( Handle[3], DX_PLAYTYPE_BACK );		 
		 }

		 if(++player.HitRemain>=60){	
			 player.x=-100; player.y=-100;     //人も場外に吹っ飛ばす
			 player.Shot_X=-100; player.Shot_Y=-100;  //弾の判定を場外に吹っ飛ばす
			  BoyFlag=false;
		}
		 int img=(player.HitRemain/4); 
		DrawRotaGraph(player.x+50,player.y+50,0.8f,0.0f,HandleExplode[img],TRUE);
		 return 0;	//処理を終わらせる
	  }


	//移動
	 if( CheckHitKey( KEY_INPUT_LEFT ) == 1 ){
			player.plus=3; player.route=1;
	 }else if(CheckHitKey( KEY_INPUT_RIGHT ) == 1 ){
		    player.plus=6; player.route=2;
	 }else if(CheckHitKey( KEY_INPUT_UP ) == 1){
			player.plus=9; player.route=3;
	 }else if(CheckHitKey( KEY_INPUT_DOWN ) == 1){
		   player.plus=0;  player.route=0;
	 }else  player.route=4; 
	
	 //キーによって歩く方向の処理をする
	switch(player.route){
			case 0: if(player.y<=FIELD_MAX_Y) player.y+=player.speed; break;
			case 1:  if(player.x>=FIELD_MIN_X)player.x-=player.speed; break;
			case 2:  if(player.x<=FIELD_MAX_X)player.x+=player.speed; break;
			case 3: if(player.y>=FIELD_MIN_Y) player.y-=player.speed; break;
			default: break;
			}

	 //歩行モーションを分ける
	  
	  if(player.route!=4)
      img=(Time%24)/8+player.plus;  //動いているとき
	  else
	  img=player.plus;  //止まってる時

	  //描画処理
	  if(player.HitFlag && player.HitRemain++<NO_HIT_TIME && player.HitRemain%2==0){
		  DrawGraph(40+player.x,40+player.y,Handleboy[img],TRUE);
	  }else if(player.HitFlag&&player.HitRemain>=NO_HIT_TIME){
		  player.HitRemain=0; player.HitFlag=false;
	  }else if(!player.HitFlag){
		  DrawGraph(40+player.x,40+player.y,Handleboy[img],TRUE); //描画でっせ
		//当たっているかの判定 
		  for(int i=0;i<5;i++){
		  EneHitPlayer(ene[i],player);	
		  EneBltHitPlayer(ene[i],player);
		  }

	  }

	  //残機の表示
	  for(int i=1; i<=player.lives; i++){
		 DrawRotaGraph(470+30*i,140,0.8f,0.0f,Handleboy[0],TRUE);
	  }
	 

	  //プレイヤーの攻撃
	  player.AttackP(Time);
	  
	  return 0;
	
 }

 //敵の描画
 void Enemydraw(int Time){
	 extern int HandleEnemy[12]; //敵の画像
	
	 static int plus[ENEMY_NUMBER]={0}; //方向を決める

	for(int i=0;i<ENEMY_NUMBER;i++){
		 if(ene[i].lives<0){
			 if(ene[i].HitRemain==0)
				 PlaySoundMem( Handle[3], DX_PLAYTYPE_BACK );
				 

		 if(++ene[i].HitRemain>=60){
			ene[i].x=-100;ene[i].y=-100;
			ene[i].Shot_X=-100; ene[i].Shot_Y=-100;
			  continue;
		}
		 int img=(ene[i].HitRemain/4); 
		DrawRotaGraph(ene[i].x+50,ene[i].y+50,0.8f,0.0f,HandleExplode[img],TRUE);
		 continue;	//処理を終わらせる
	 }



		if(Time%(ene[i].timing*45)==0){ //方向変換
			switch(GetRand(3)){
				case 0: plus[i]=0; ene[i].turn=0; break;
				case 1: plus[i]=3; ene[i].turn=1; break;
				case 2: plus[i]=6; ene[i].turn=2; break;
				case 3: plus[i]=9; ene[i].turn=3; break;
			  }
		}

	//移動可能範囲を絞る	
			switch(plus[i]){
			case 0: if(ene[i].y<=FIELD_MAX_Y) ene[i].y+=ene[i].speed; break;
			case 3:  if(ene[i].x>=FIELD_MIN_X)ene[i].x-=ene[i].speed; break;
			case 6:  if(ene[i].x<=FIELD_MAX_X)ene[i].x+=ene[i].speed; break;
			case 9: if(ene[i].y>=FIELD_MIN_Y) ene[i].y-=ene[i].speed; break;
			}	
	
	//画像を巡回させて描画
	 int img=(Time%24)/8+plus[i];

//描画処理
	  if(ene[i].HitFlag && ene[i].HitRemain++<NO_HIT_TIME && ene[i].HitRemain%2==0){
		  DrawGraph(40+ene[i].x,40+ene[i].y,HandleEnemy[img],TRUE);
	  }else if(ene[i].HitFlag&&ene[i].HitRemain>=NO_HIT_TIME){
		  ene[i].HitRemain=0; ene[i].HitFlag=false;
	  }else if(!ene[i].HitFlag){
 	 DrawGraph(40+ene[i].x,40+ene[i].y,HandleEnemy[img],TRUE);//描画でっせ
	 PlayerBltHitEne(ene[i],player);
	  }

	//方向変換するタイミングを変える
     ene[i].timing=GetRand(2)+1;
	 //攻撃を先にやる?(テスト)
	  ene[i].Attack(Time);
	}
	
 }

//メニューの壁画
 void Menudraw(int Time){ 
	 extern int Font00,Font01,Font02;
     extern int HandleNum[10];
	static int Englishnum[12]={19,20,28,35,8,23,10,6,25,14,19,12};
	extern int HandleArpha[36];
	extern int HandleItem[96];


	//NOW CREATING
 for(int i=0;i<12;i++){
	 DrawRotaGraph(20+30*(i+1),400+8*(sin(PI*(Time+3*i)/30)+1)/2,1.5f,0.0f,HandleArpha[Englishnum[i]],TRUE);
	
 }


	 //アイテムを表示(テスト)
	 DrawModiGraph(216+20*cos(PI+(PI*Time/120)),200,216+20*cos(PI*Time/120),
		 200,216+20*cos(PI*Time/120),240,216+20*cos(PI+(PI*Time/120)),240,HandleItem[4],TRUE);
	
    //文字(タイトルと作成者名)
	DrawStringToHandle( 420, 20, "Words", GetColor(255,255,255), Font02 );
	DrawStringToHandle( 480, 60, "Puzzle", GetColor(255,255,255), Font02 );
	DrawStringToHandle( 420, 360, "Created by", GetColor(255,255,0), Font01 );
    DrawStringToHandle( 440, 400, "High Stone.", GetColor(255,255,0), Font01 );

	//スコアとステータスボードの表示
	 DrawStringToHandle( 400, 100, "得点:", GetColor(255,255,255), Font00 );
	 DrawStringToHandle( 400, 130, "残機:", GetColor(255,255,255), Font00 );
	DrawStringToHandle( 400, 160, "レベル:", GetColor(255,255,255), Font00 );
	DrawStringToHandle( 400, 190, "ステータス", GetColor(255,255,255), Font00 );

	//スコアの表示
	 int score=player.score;

	  for(int i=0; score>=0; i++){
		DrawRotaGraph(570-20*i,110,1.2f,0.0f,HandleNum[score%10],TRUE);
		if(score>9)
		score/=10; //まだ9以上なら割る
		else break; //もう1桁ならやめる
	  }

 //ステータスの表示(1桁なら上三行はいらない)
	  int Attack=player.Attack;
	  int Difence=player.Difence;
	  int Speed=player.speed;

		DrawRotaGraph(440,275,1.2f,0.0f,HandleNum[Attack%10],TRUE); //攻撃力
		DrawRotaGraph(500,275,1.2f,0.0f,HandleNum[Difence%10],TRUE); //防御力
		DrawRotaGraph(560,275,1.2f,0.0f,HandleNum[Speed%10],TRUE); //スピード

		
	  //レベルの表示
	   DrawFormatString(565,165,GetColor(0,0,0),"1");
	   //ステータス画像の表示
	    DrawRotaGraph(440,240,1.6f,0,HandleItem[1],TRUE); //攻撃力
		DrawRotaGraph(500,240,1.6f,0,HandleItem[13],TRUE); //防御力
		DrawRotaGraph(560,240,1.6f,0,HandleItem[21],TRUE); //スピード

 }

//文字を描画する
 void Mozidraw(int Time){ 
		
	 static int num=0;
	 mozi[num].answerPutmap(Time);

	 if(CheckHitKey(KEY_INPUT_R) == 1){ //リセット処理(本当はここはフレーム数で判定します)
		 for(int i=0;i<mozi[num].num;i++){
			 mozi[num].Nowanswer[i]=' '; //回答をすっきりさせる
		 }
		 PlaySoundMem( Handle[7], DX_PLAYTYPE_BACK ); //キャンセル音
	    mozi[num].nownum=0;
		mozi[num].MoziInput(Sample[num]);
	 }


	 PlayerGetMozi(player,mozi[num]);
	 if(mozi[num].nownum==mozi[num].num){
		 if(mozi[num].answercheck()) player.score+=mozi[num].point;
			num++;
		
	 }

 }

コード:

//extern.h
#include "DxLib.h"
#include "Class.h"

//------------Key.cpp-----------------//
//extern int gpUpdateKey(void);
//------------draw.cpp----------------------//
//mapの壁画
extern void mapdraw(void);
//プレイヤーの壁画
extern int boydraw(int Time);
//敵の壁画
extern void Enemydraw(int Time);
//メニューの壁画
extern void Menudraw(int Time);
//文字の壁画
extern void Mozidraw(int Time);
//------------------------------------------//
//------------load.cpp--------------------//
//画像のロード
extern void load(void);
//------------------------------------------//
//-----------judge.cpp--------------------//
extern void EneHitPlayer(Enemy& enemy,Player& player);
extern void EneBltHitPlayer(Enemy& enemy,Player& player);
extern void PlayerBltHitEne(Enemy& enemy,Player& player);
extern void PlayerGetMozi(Player& player,Mozi& mozi);

長文になり申し訳ありません。なにとぞお願い申し上げます。

アバター
Dixq (管理人)
管理人
記事: 1662
登録日時: 14年前
住所: 北海道札幌市
連絡を取る:

Re: 突然画面がおかしなことに....

#2

投稿記事 by Dixq (管理人) » 9年前

新・ゲームプログラミングの館を参考にされているのであれば、関数内にstatic変数を作ったりextern宣言をしたりするのはやめましょう。
上記サイトに設計の仕方も紹介しています。
ここではグローバル変数なしに作る作り方を紹介しています。
また、キーの入力状態を取得するモジュールの作り方もサイトで紹介しています。

もし現在の作りのまま直したいのなら、プロジェクトを実行出来る形でUploadできますか?

onehst
記事: 14
登録日時: 9年前
住所: 東京都

Re: 突然画面がおかしなことに....

#3

投稿記事 by onehst » 9年前

返信ありがとうございます。誠に恥ずかしい限りなのですが....

>>もし現在の作りのまま直したいのなら、プロジェクトを実行出来る形でUploadできますか?

こちらの方法が分からないです...下のファイル添付の部分に貼れば良いのでしょうか?
一応ファイルをzip形式に圧縮したものを添付させていただきます。
もしやり方が違っているのでしたら正しい方法を教えていただけると助かります。

アバター
Dixq (管理人)
管理人
記事: 1662
登録日時: 14年前
住所: 北海道札幌市
連絡を取る:

Re: 突然画面がおかしなことに....

#4

投稿記事 by Dixq (管理人) » 9年前

> 下のファイル添付の部分に貼れば良いのでしょうか?

そうです。
「ファイル添付」>「参照」でzipファイルを選択し > 「ファイルの追加」をクリック
でOKです。

onehst
記事: 14
登録日時: 9年前
住所: 東京都

Re: 突然画面がおかしなことに....

#5

投稿記事 by onehst » 9年前

これで大丈夫でしょうか...?

お手数おかけして申し訳ございません....
何卒よろしくお願いします。
添付ファイル
Game.zip
要領が大きくなってしまったため、DxLibのファイルを入れていない状態です。
もしかしたら足りないものがあるかもしれません....
(7.85 MiB) ダウンロード数: 119 回

アバター
Dixq (管理人)
管理人
記事: 1662
登録日時: 14年前
住所: 北海道札幌市
連絡を取る:

Re: 突然画面がおかしなことに....

#6

投稿記事 by Dixq (管理人) » 9年前

うむむ・・これは直すべきコードが非常に多いですね・・。
もうちょっと小さいプログラムにしてレビュー依頼してもらえたら私でよければレビューして差し上げますよ。
最初は簡単なインベーダーゲームでもいいので綺麗な設計で書いてみて誰かに添削してもらうってのもいいかもしれません。
まぁそういう私も汚いコードで試行錯誤してやって来た人間ですが。。。

ただ一つだけ
・インデントがぐちゃぐちゃなのはバグのもとです。きちんとインデントしましょう。ファイルごとに全選択Ctrl+K+Fで自動整形されます。

で、本題ですが、

> int gpUpdateKey()関数を
> main.cppから専用のKey.cppに移したところで上のようなバグになりました。

プロジェクトを拝見したところ、Key.cppはなく、main.cpp内にありますよ。
(プロジェクトに入っていないKey.cppならありますが、中身が空っぽです)

また、Keyを使っている所って
if(Key[KEY_INPUT_R] == 1)
ここしかありませんね。
また、こちらのプロジェクトを動作させても特にフリーズもちらつきもありませんでした。
渡しているプロジェクトがあっているか確認お願いできませんか?
# Debugフォルダは消してからzipにしてください

p.s.
面白そうなゲームですね

onehst
記事: 14
登録日時: 9年前
住所: 東京都

Re: 突然画面がおかしなことに....

#7

投稿記事 by onehst » 9年前

返信ありがとうございます。

>うむむ・・これは直すべきコードが非常に多いですね・・。

ゲーム作成をやったことない人間が「とりあえず動けばよいだろ」っていう危険な思想の元、
やりたいことを書きまくったらこのようになりました。。。

>もうちょっと小さいプログラムにしてレビュー依頼してもらえたら私でよければレビューして差し上げますよ。
最初は簡単なインベーダーゲームでもいいので綺麗な設計で書いてみて誰かに添削してもらうってのもいいかもしれません。

ありがとうございます!!添削してくれる方がいるととても勉強になります。
簡単なやつですか....管理人様が公開されているサンプルゲームから製作難易度が比較的低めのゲームを
ダウンロードさせてもらってその設計を軸にアレンジなどをするなどでもよいのでしょうか?
それとも1から自分で作った方がよいのでしょうか?(まためちゃくちゃになりそうですが・・・)

>インデントがぐちゃぐちゃなのはバグのもとです。きちんとインデントしましょう。
以後そのようにします。

>で、本題ですが、(以下略)
gpUpdateKey()関数をmain.cppに戻したものをおくらさせていただきました。
後つけな理由で申し訳ないのですが... おそらく設計がめちゃくちゃだとおもってたので実行できるほうが
良いのかなと思ったり(汗) Key.cppにgpUpdateKey()関数を移すとフリーズすると思われます。
ですが、正直それ以外にも直すべきところがたくさんあるのでこのゲームは一旦設計を中断してさきほどのアドバイスとおり
簡単なものを作ってみようと思います。迷惑かけて申し訳ありません。

>p.s. 面白そうなゲームですね
こういっていただけると大変嬉しいです。ゲーム配布してみんなにこういってもらうのが夢なんでがんばります!!

アバター
Dixq (管理人)
管理人
記事: 1662
登録日時: 14年前
住所: 北海道札幌市
連絡を取る:

Re: 突然画面がおかしなことに....

#8

投稿記事 by Dixq (管理人) » 9年前

サンプルプログラミングの館は参考にしない方がいいです、、。
ゲームプログラミングの館に設計方法について説明しているページがあるのでそちらを参考にしてください。

onehst
記事: 14
登録日時: 9年前
住所: 東京都

Re: 突然画面がおかしなことに....

#9

投稿記事 by onehst » 9年前

分かりました!!色々教えてくださりありがとうございました。
これからもっと精進します。

閉鎖

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