C言語初心者です。よろしくお願いします。

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

C言語初心者です。よろしくお願いします。

#1

投稿記事 by fu » 13年前

今僕は専門学生でシューティングゲームを作っていて自機の移動、自機の弾発射、自機の当たり判定、敵の移動、敵の弾発射、敵の当たり判定までプログラムし、何となく関数化してみたのですが自機から弾がでなくなってしまいました。
なにが問題なのかもさっぱりわかりません。

コード:

 
          
#include "DxLib.h"

#define s 200

                 void PS(void);
				 void PM(void);
			     void EM(void);void PSM();
			     void ES(void); 
			     void PD(void);
			     void ED(void);
				 int Colision(int ob1x,int ob1y,int ob1w,int ob1h,
			                  int ob2x,int ob2y,int ob2w,int ob2h);
				 int jiki1x,jiki1y,jiki1graph;
				 int teki1x,teki1y,teki1Muki,teki1graph;
                 int tamaix[s],tamaiy[s],tamaigraph,tamaiFlag[s];
				 int jw,jh,tw,th;
				 int i;
				 int tamaiFlagB;
				 int tw1,th1;
				 int teki1damageFlag,teki1damageCounter,teki1damagegraph;
				 int etamaFlag,etamacounter;
				 int etamax,etamay,etamagraph,etamaw,etamah;
				 int jikidamageFlag,jikidamagecounter,jikidamagegraph;
				 int ret;
                
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
				 LPSTR lpCmdLine, int nCmdShow )
{
	

 
//ChangeWindowMode(TRUE);
ChangeWindowMode(FALSE);

SetGraphMode(640,480,16);
	if( DxLib_Init() == -1 )	// DXライブラリ初期化処理
	{
		 return -1;				// エラーが起きたら直ちに終了
	}
//描画先画面を裏画面にする
	SetDrawScreen(DX_SCREEN_BACK);


jiki1graph=LoadGraph("jiki1.bmp");
jiki1x=288;jiki1y=400;
//teki1のグラフィックをメモリにロード&表示座標をセット
	teki1graph=LoadGraph("teki1.bmp");
	teki1x=0;teki1y=50;
//tama1のグラフィックをメモリにロード
	tamaigraph=LoadGraph("tama1.bmp");
   for(i=0;i<s;i++)
	{
		tamaiFlag[s]=0;
	}
		tamaiFlagB=0;
//teki1の移動方向をセット
	teki1Muki=1;
		GetGraphSize(tamaigraph,&tw,&th);
	jikidamagegraph=LoadGraph("gathisuke.bmp");

	jikidamageFlag=0;

	etamacounter=0;

	teki1damagegraph=LoadGraph("ahopanman.bmp");

    GetGraphSize(jiki1graph,&jw,&jh);
	teki1damageFlag=0;

	

	
	while(1)

	{

		//画面に描かれたものを一回消す
		ClsDrawScreen();
		{

               
	     	   PM();
			   PS();
			   PSM();
			   ED();
			   EM(); 
			   ES();
			   PD();
			  
         
			if(Colision(jiki1x,jiki1y,jw,jh,etamax,etamay,etamaw,etamah))
			{
				etamaFlag=0;
               jikidamageFlag=1;
			

				jikidamagecounter=0;
			}
	for(i=0;i<s;i++)
	{
		if(tamaiFlag[s]==1)
		{

			if(Colision(tamaix[s],tamaiy[s],tw,th,teki1x,teki1y,tw1,th1) == 1){
				tamaiFlag[s]=0;

				teki1damageFlag=1;

				teki1damageCounter=0;
			}
		}
	}
		}
	
	

	//裏画面の内容を表画面に表示
	ScreenFlip();


	//Windowsシステムからくる情報を処理
	if(ProcessMessage()==-1)break;

	//ESCキーが押されたらループから抜ける
	if(CheckHitKey(KEY_INPUT_ESCAPE)==1)break;
	
	}
	
	WaitKey() ;					// キーの入力待ち((7-3)『WaitKey』を使用)

	DxLib_End() ;				// DXライブラリ使用の終了処理

	return 0 ;					// ソフトの終了

	

}
void PM(){


	
//上下左右のキー入力に対応してx,yの座標を変更する

	
	    if(CheckHitKey(KEY_INPUT_LEFT)==1)jiki1x-=10;
		if(CheckHitKey(KEY_INPUT_RIGHT)==1)jiki1x+=10;
		if(CheckHitKey(KEY_INPUT_UP)==1)jiki1y-=10;
		if(CheckHitKey(KEY_INPUT_DOWN)==1)jiki1y+=10;
		if(jiki1x<0)jiki1x=0;
		if(jiki1x>640-72)jiki1x=640-72;
		if(jiki1y<0)jiki1y=0;
		if(jiki1y>480-70)jiki1y=480-70;
        DrawGraph(jiki1x,jiki1y,jiki1graph,FALSE);

}
	
void PD(){	
if(jikidamageFlag==1)
		{

			DrawGraph(jiki1x,jiki1y,jikidamagegraph,FALSE);

			jikidamagecounter++;

			if(jikidamagecounter==30)
			{

				jikidamageFlag=0;
			}
		}
else
{
 PM();
 PS();
}
}
void EM(){

{
if(teki1Muki==1)teki1x+=10;
if(teki1Muki==0)teki1x-=10;

	

	


	if(teki1x>640-105)
	{
		teki1x=640-105;
		teki1Muki=0;
	}


	if(teki1x<0)
	{
		teki1x=0;
		teki1Muki=1;
	}


	DrawGraph(teki1x,teki1y,teki1graph,FALSE);
}
}

void ED(){
if(teki1damageFlag==1)
		

			DrawGraph(teki1x,teki1y,teki1damagegraph,FALSE);

			teki1damageCounter++;

			if(teki1damageCounter==30)
			{

				teki1damageFlag=0;
			}
		
		
}





void PS(){
	
	//スペース

	if(CheckHitKey(KEY_INPUT_SPACE))
	
		if(tamaiFlagB==0)
	
		{
	for(i=0;i<s;i++)
	{
		if(tamaiFlag[s]==0)
		{
		//jiki1とtama1の画像サイズを得る
 
	GetGraphSize(jiki1graph,&jw,&jh);
	GetGraphSize(tamaigraph,&tw,&th);
        //tama1の位置セット

	tamaix[s]=(jw-tw)/2+jiki1x;
	tamaiy[s]=(jh-th)/2+jiki1y;  
	tamaiFlag[s]=1;
	
	break;
	}
	}
	
	tamaiFlagB=1;
	DrawGraph(tamaix[s],tamaiy[s],tamaigraph,FALSE);
	}
	else
	{
		tamaiFlagB=0;
	}
}

	void PSM()
	{
//tama1移動
	for(i=0;i<s;i++)
	{

	if(tamaiFlag[s]==1)
	{

		tamaiy[s]-=5;

		if(tamaiy[s]<-20)
		{
			tamaiFlag[s]=0;
		}

		DrawGraph(tamaix[s],tamaiy[s],tamaigraph,FALSE);

	
	}
	}
	}




void ES(){
	{
	

	GetGraphSize(teki1graph,&tw1,&th1);

	etamagraph=LoadGraph("tama1.bmp");
	GetGraphSize(etamagraph,&etamaw,&etamah);
	etamaFlag=0;
	
	{
			ret=GetRand(100);
			if(ret<2)
			{
etamacounter++;

	if(etamacounter==1)
	{
        
			
		if(etamaFlag==0)
		{
			etamax=teki1x+tw1/2-etamaw/2;
			etamay=teki1y+th1/2-etamah/2;


			etamaFlag=1;
		
		}
			
		etamacounter=0;
	}
			}
	}
	}
	
	if(etamaFlag==1)
 
			
	{
		etamay+=15;

		if(etamay>480)etamaFlag=0;
		DrawGraph(etamax,etamay,etamagraph,FALSE);
	}
			}




int Colision(int ob1x,int ob1y,int ob1w,int ob1h,
			 int ob2x,int ob2y,int ob2w,int ob2h)
{
	int colflg=0;
	if(((ob1x>ob2x&&ob1x<ob2x+ob2w)||
	   (ob2x>ob1x&&ob2x<ob1x+ob1w))&&
	   ((ob1y>ob2y&&ob1x<ob2y+ob2h)||
	   (ob2y>ob1y&&ob2y<ob1y+ob1h)))
	{
		colflg=1;
	}
	return(colflg);
}		
	  
         あとタイトル画面からゲームに移行するやり方やボードの表示の仕方背景の表示の仕方もよくわかりません。
長文で申し訳ありません。
どなたかわかる方がおられましたら教えていただけると幸いです

ぬっち
記事: 105
登録日時: 13年前
連絡を取る:

Re: C言語初心者です。よろしくお願いします。

#2

投稿記事 by ぬっち » 13年前

とりあえずすぐに答えられるものを答えます。

>あとタイトル画面からゲームに移行するやり方やボードの表示の仕方背景の表示の仕方もよくわかりません。
タイトル画面からゲームに移行するやり方は「状態遷移」というもので、簡単な方法としてはループしている場所で、switchによる分岐を使って行います。

コード:

enum State
{
	STATE_TITLE	= 1,
	STATE_STAGE_1	= 2,
};

State g_State = STATE_TITLE;

int main()
{
	while( 1 ){
		//メインループの処理
		switch( g_State ){
			case STATE_TITLE:
				Title();		// タイトル画面の処理
				break;
			case STATE_STAGE_1:
				Stage1();		// ステージ1の処理
				break;
			default:
				break;
		}
	}
}

void Title()
{
	// タイトル画面でのいろいろな処理。
	if( //ステージへ移行したい時の条件 ){
		g_State = STATE_STAGE_1;
	}
}
としたらどうでしょうか?
ボードの表示の仕方や背景の表示の仕方とは何でしょうか?
ただ単に描画順番に気をつければよいのでは?

アバター
結城
記事: 52
登録日時: 13年前
連絡を取る:

Re: C言語初心者です。よろしくお願いします。

#3

投稿記事 by 結城 » 13年前

とりあえず私にわかる範囲としては

コード:

void PS(){
    
    //スペース
 
    if(CheckHitKey(KEY_INPUT_SPACE))
    
        if(tamaiFlagB==0)
    
        {
    for(i=0;i<s;i++)
	{
        if(tamaiFlag[s]==0)
		{
        //jiki1とtama1の画像サイズを得る
 
    GetGraphSize(jiki1graph,&jw,&jh);
    GetGraphSize(tamaigraph,&tw,&th);
        //tama1の位置セット
 
    tamaix[s]=(jw-tw)/2+jiki1x;
    tamaiy[s]=(jh-th)/2+jiki1y;  
    tamaiFlag[s]=1;
    
    break;
    }
    }
    
    tamaiFlagB=1;
    DrawGraph(tamaix[s],tamaiy[s],tamaigraph,FALSE);
    }
    else
    {
        tamaiFlagB=0;
    }
}
の所の{と}の対応がめちゃくちゃになっている…というか
最初のifの{無いんじゃないですか?
それ直したらもしかしたら描画されるんじゃないでしょうか
ANGE;ART

アバター
bitter_fox
記事: 607
登録日時: 13年前
住所: 大阪府

Re: C言語初心者です。よろしくお願いします。

#4

投稿記事 by bitter_fox » 13年前

問題の箇所見っけ。。(疲れたナリ)(涙

定数 sはMAXにしています。こんなことが起こるから、defineは大文字にするんですね。わかります。

コード:

//
//
//////////////////////////////////////////////////////////////////////
void PS()
{
    //スペースが押されたら
    if(CheckHitKey(KEY_INPUT_SPACE)) // きわどい文法 commented by bitter_fox
        if(tamaiFlagB==0)
        {
		    for(i=0;i<MAX;i++)
		    {
		        if(tamaiFlag[MAX]==0) // <== ここ
		        {
		        //jiki1とtama1の画像サイズを得る
 
				    GetGraphSize(jiki1graph,&jw,&jh);
				    GetGraphSize(tamaigraph,&tw,&th);
        //tama1の位置セット
 
				    tamaix[MAX]=(jw-tw)/2+jiki1x; // <== ここ
				    tamaiy[MAX]=(jh-th)/2+jiki1y;   // <== ここ
				    tamaiFlag[MAX]=1; // <== ここ
				    break;
			    }
		    }

        	tamaiFlagB=1;
		    DrawGraph(tamaix[MAX],tamaiy[MAX],tamaigraph,FALSE); // <== ここ
	    }
	    else
	    {
	        tamaiFlagB=0;
	    }
}

//
// 自機のタマの移動 commented by bitter_fox
//////////////////////////////////////////////////////////////////////
void PSM()
{
//tama1移動
	for(i = 0; i < MAX; i++)
    {
	    if(tamaiFlag[MAX] == 1) // <== ここ
	    {
	        tamaiy[MAX] -= 5; // <== ここ
 
	        if(tamaiy[MAX] < -20) // <== ここ
	        {
	            tamaiFlag[MAX] = 0; // <== ここ
	        }
 
	        DrawGraph(tamaix[MAX], tamaiy[MAX], tamaigraph, FALSE); // <== ここ
	    }
    }
}
もうお分かりですね、、
にしても、類まれに見る斬新なインデントと関数名ですね。きれいにインデントしてそれを投稿してから、細かく見ようと思ったけどそこまで行く前に見つけられて良かった。(結構インデントしたけど)
ま、こんなことを繰り返してうまくなっていくんですよね。

アバター
結城
記事: 52
登録日時: 13年前
連絡を取る:

Re: C言語初心者です。よろしくお願いします。

#5

投稿記事 by 結城 » 13年前

あと、綺麗に並べ替えられたのを見ていてふと思ったのが一つ

コード:

            for(i=0;i<MAX;i++)
            {
                if(tamaiFlag[MAX]==0) // <== ここ
                {
                //jiki1とtama1の画像サイズを得る
 
                    GetGraphSize(jiki1graph,&jw,&jh);
                    GetGraphSize(tamaigraph,&tw,&th);
        //tama1の位置セット
 
                    tamaix[MAX]=(jw-tw)/2+jiki1x; // <== ここ
                    tamaiy[MAX]=(jh-th)/2+jiki1y;   // <== ここ
                    tamaiFlag[MAX]=1; // <== ここ
                    break;
                }
            }
↑この中でtama1をセットするならforの中でtama関連の変数にMAXを当てても意味がありません
MAXは固定値ですから、MAXの時のみ初期化されてしまいます
iを入れてやるとうまく初期されると思いますよ

コード:

//
//comment by hinari
//////////////////////////////////////////////////////////////////////
void PS()
{
    //スペースが押されたら
    if(CheckHitKey(KEY_INPUT_SPACE)) 
        if(tamaiFlagB==0)
        {
            for(i=0;i<MAX;i++)
            {
                if(tamaiFlag[i]==0) // <== ここ
                {
                //jiki1とtama1の画像サイズを得る
 
                    GetGraphSize(jiki1graph,&jw,&jh);
                    GetGraphSize(tamaigraph,&tw,&th);
        //tama1の位置セット
 
                    tamaix[i]=(jw-tw)/2+jiki1x; // <== ここ
                    tamaiy[i]=(jh-th)/2+jiki1y;   // <== ここ
                    tamaiFlag[i]=1; // <== ここ
                    break;
                }
            }
 
            tamaiFlagB=1;
            DrawGraph(tamaix[MAX],tamaiy[MAX],tamaigraph,FALSE);
        }
        else
        {
            tamaiFlagB=0;
        }
}
これですべての弾が初期化されるはずですがどうでしょうかね
ANGE;ART

アバター
bitter_fox
記事: 607
登録日時: 13年前
住所: 大阪府

Re: C言語初心者です。よろしくお願いします。

#6

投稿記事 by bitter_fox » 13年前

もうひとつ気になったことがあるので。

コード:


//
// プレイヤーがダメージを負ったときの処理 commented by bitter_fox
//////////////////////////////////////////////////////////////////////
void DamagedPlayer()//PD() changed by bitter_fox
{  
	if(jikidamageFlag==1) // 自機がダメージを負ったら comment by bitter_fox
    {

		DrawGraph(jiki1x,jiki1y,jikidamagegraph,FALSE); // ダメージエフェクトを表示 comment by bitter_fox
 
	    jikidamagecounter++; // ダメージカウンタを増加 commented by bitter_fox
 
    	if(jikidamagecounter==30) // ダメージカウンタが30で commented by bitter_fox
	    {
    		jikidamageFlag=0; // フラグをリセット commented by bitter_fox
    	}
    }
	else
	{
		CheckKeyAndMovePlayer();
		PS();
	}
}

//
// 敵がダメージを負ったときの処理 commented by bitter_fox
//////////////////////////////////////////////////////////////////////
void DamagedEnemy() //ED() changed by bitter_fox
{
	if(teki1damageFlag==1)
		DrawGraph(teki1x,teki1y,teki1damagegraph,FALSE);

	teki1damageCounter++; // 常に実行 commented by bitter_fox

	if(teki1damageCounter==30) // ダメージカウンターが30でリセット commented by bitter_fox
	{
		teki1damageFlag=0;
	}
}
EDだと、単行if文なので
teki1damageCounter++;
が常に実行されてしまいますよ。
この処理は、PDのときと同様に、ifが真のときだけでよいのではないですか??
そのあとの、ダメージフラグの部分も同様です。

Hinari さんが書きました: MAXは固定値ですから、MAXの時のみ初期化されてしまいます
iを入れてやるとうまく初期されると思いますよ
ですね。
tama____[MAX]は、確保した範囲の外を参照しているので、アプリケーションエラーが出ないのは奇跡ですよね。ガクガクブルブル
それから、DrawGraphの所とPSMの所も同様にしてあげる必要がありますね。

fu

Re: C言語初心者です。よろしくお願いします。

#7

投稿記事 by fu » 13年前

みなさん素晴らしい解答ありがとうございました
おかげさまで弾が出るようになり一安心です。

閉鎖

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