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

#1

投稿記事 by hiro » 13年前

敵を倒すとコインが1枚出るようにしたいのですが
複数の敵がいるとき敵を倒すと1体目を倒すとで普通に出るのですがコインを取らずに
もう一体の敵を倒すと一体目のときに出たコインが消えて二体目の

コード:

// ************************************************************
//
// コイン
//
// ************************************************************

//コイン処理

#include"gs.h"
#include"Coin.h"
#include"def.h"//ゲーム全体での共通定義
#include<stdio.h>


extern OBJ kikori;//王
OBJ gCoin[COIN_MAX];//コインの数

gsTexture sCoin[4];//コイン


//----------------------------------------------------------
//コイン読み込み
//----------------------------------------------------------
void CoinLoad(void)
{
	int i;
	//コインの数
	for(i=0; i<COIN_MAX; i++)
	{
		gsLoadTexture(&sCoin[0], "BMP\\Coin01.png", 0xffffffff);//コイン1
		gsLoadTexture(&sCoin[1], "BMP\\Coin02.png", 0xffffffff);//コイン2
		gsLoadTexture(&sCoin[2], "BMP\\Coin03.png", 0xffffffff);//コイン3
		gsLoadTexture(&sCoin[3], "BMP\\Coin04.png", 0xffffffff);//コイン4
	}
}

//-----------------------------------------------------------
//コイン初期化
//-----------------------------------------------------------
void CoinInit(void)
{
	int i;
	//コインの数
	for(i=0; i<COIN_MAX; i++)
	{
		gCoin[i].flg =OFF;		//コイン存在フラグ
		gCoin[i].y = 500;		//コインY座標
		gCoin[i].hp=10;			//コイン獲得ポイント
		gCoin[i].dir = Stop;	//コイン初期方向
	}
}

//-----------------------------------------------------------
//コイン解放
//-----------------------------------------------------------
void CoinTerm(void)
{
		gsReleaseTexture(sCoin[0]);//コイン1
		gsReleaseTexture(sCoin[1]);//コイン2
		gsReleaseTexture(sCoin[2]);//コイン3
		gsReleaseTexture(sCoin[3]);//コイン4

}

//----------------------------------------------------------------------
//コイン処理
//----------------------------------------------------------------------
void CoinMain()
{
	int i;
	//コインの数
	for(i=0; i<COIN_MAX; i++)
	{
		if(gCoin[i].flg == ON)//コインが存在したら
		{
			CoinAnimation();//コインアニメーション
			CoinMove(i);//コイン移動
			KikoriCoinHit(i);//王とコインの当たり判定
		}
	}
}
//----------------------------------------------------------------------
//コイン表示
//----------------------------------------------------------------------
void CoinDraw()
{
	//char str[100];
	int i;

	//sprintf(str,"kikoro.x=%d",kikori.x);
	//gsDrawText(10,100,str);

	//コインの数
	for(i=0; i<COIN_MAX; i++)
	{
		if(gCoin[i].flg == ON)//コインが存在すれば
		{
			CoinAnimation();//コインアニメーション

			//sprintf(str,"coin.x=%d",gCoin[i].x);
			//gsDrawText(10,140+i*20,str);
		}
	}
}

//------------------------------------------------------------
// コイン発生
//------------------------------------------------------------
void CoinSet(int x, int y)
{
	int i;
	//コインの数
	for(i=0; i<COIN_MAX; i++)
	{
		gCoin[i].flg = ON;//コインが存在する
		gCoin[i].x = x+20;//コインX座標を決定
		gCoin[i].y = y;	//コインY座標を決定
	}
}

//-----------------------------------------------------------
//コイン移動
//-----------------------------------------------------------
void CoinMove(int i)
{
	//コインの数
	for(i=0; i<COIN_MAX; i++)
	{
		if(gCoin[i].flg == ON)//コインが存在していれば
		{
			//gCoin[i].x++;//コインを右へ移動
		}
	}
}

//------------------------------------------------------------------
//王とコインの当たり判定
//------------------------------------------------------------------
void KikoriCoinHit(int i)
{
	//コインの数
	for(i=0; i<COIN_MAX; i++)
	{
		if( kikori.x + SHIPSIZE_X > gCoin[i].x  &&	//王の右>コインの左
			kikori.x < gCoin[i].x + COIN_XSIZE  &&	//王の右<コインの右
			kikori.y + SHIPSIZE_Y > gCoin[i].y &&	//王の左>コインの左
			kikori.y < gCoin[i].y + COIN_YSIZE)		//王の左<コインの左
		{	
			gCoin[i].flg = OFF;//コインの存在をOFFにする
			gCoin[i].hp += 10;//所持金を加算
		}
	}
}


//-------------------------------------------------------------------
//コインアニメーション
//-------------------------------------------------------------------
void CoinAnimation()
{
	int i;
	//コインの数
	for(i=0; i<COIN_MAX; i++)
	{
		gCoin[i].ct++;//コインのカウントを加算
		if(gCoin[i].ct>80) gCoin[i].ct=0;//コインのカウントが40になったら0にする

		//消滅デバッグ
		if(gCoin[i].x>800) gCoin[i].flg=OFF;


		if ( gCoin[i].ct >= 1 && gCoin[i].ct <= 20 )//カウントが20まで
		{
			gsDraw2D(sCoin[0], gCoin[i].x, gCoin[i].y);//コイン1
		}
		if (gCoin[i].ct >= 21 && gCoin[i].ct <= 40 )//カウントが40まで
		{
			gsDraw2D(sCoin[1], gCoin[i].x, gCoin[i].y);//コイン2
		}
		if ( gCoin[i].ct >= 41 && gCoin[i].ct <= 60)//カウントが60まで
		{
			gsDraw2D(sCoin[2], gCoin[i].x, gCoin[i].y);//コイン3
		}
		if ( gCoin[i].ct >= 61 && gCoin[i].ct <= 80)//カウントが80まで
		{
			gsDraw2D(sCoin[3], gCoin[i].x, gCoin[i].y);//コイン4
		}
	}
}

hiro

Re: 。

#2

投稿記事 by hiro » 13年前

すいません。
間違って送信してしまいました。

敵を倒すとコインが1枚出るようにしたいのですが
複数の敵がいるとき敵を倒すと1体目を倒すとコインが普通に出るのですがコインを取らずに
もう一体の敵を倒すと一体目のときに出たコインが消えて二体目の敵がいたとこにコインが出ます。

これを一体目の敵を倒したときコインが出てそれを取らずに
二体目の敵を倒したと二体目の敵のところにもコインを出すようにしたいのですがどうしたらいいでしょうか

jay
記事: 314
登録日時: 14年前
住所: 大阪市
連絡を取る:

Re: 。

#3

投稿記事 by jay » 13年前

そうですねぇ…

コード:

void CoinSet(int x, int y)
{
    int i;
    //コインの数
    for(i=0; i<COIN_MAX; i++)
    {
        gCoin[i].flg = ON;//コインが存在する
        gCoin[i].x = x+20;//コインX座標を決定
        gCoin[i].y = y; //コインY座標を決定
    }
}
この部分を

コード:

void CoinSet(int x, int y)
{
    int i;
    //コインの数
    for(i=0; i<COIN_MAX; i++)
    {
        if(gCoin[i].flg == OFF)
        {
             gCoin[i].flg = ON;//コインが存在する
             gCoin[i].x = x+20;//コインX座標を決定
             gCoin[i].y = y; //コインY座標を決定
        }
    }
}
こう変えてみてはどうでしょうか?

変更前の場合、flgがONだろうとOFFだろうと強制的に0番に登録されてしまうと思われます。
検索された番号のflgがOFFの場合のみ登録できる仕様にすればいいと思います
♪僕たちは まだ森の中 抜け出そう 陽のあたる場所へ

hiro

Re: 。

#4

投稿記事 by hiro » 13年前

コード:

//------------------------------------------------------------
// コイン発生
//------------------------------------------------------------
void CoinSet(int x, int y)
{
	int i;
	//コインの数
	for(i=0; i<COIN_MAX; i++)
	{
		if(gCoin[i].flg == OFF)
		{
			gCoin[i].flg = ON;//コインが存在する
			gCoin[i].x = x+20;//コインX座標を決定
			gCoin[i].y = y;	//コインY座標を決定
		}
	}
}
上のソースに変えてみましたが2体目を倒したとき1体目のコインが消えなくなりましたが2体目を倒したときコインが発生しませんでした。

ふりかけ

Re: 。

#5

投稿記事 by ふりかけ » 13年前

break文を使って、for文を抜けないと1枚コインを設定しても終わらずにCOIN_MAXまで繰り返されてしまいます。
COIN_MAX枚のコインが重なることになります。

コード:

for(i=0; i<COIN_MAX; i++)
    {
        if(gCoin[i].flg == OFF)
        {
            gCoin[i].flg = ON;//コインが存在する
            gCoin[i].x = x+20;//コインX座標を決定
            gCoin[i].y = y; //コインY座標を決定
            break;
        }
}

hiro

Re: 。

#6

投稿記事 by hiro » 13年前

breakを追加して実行してみたところ、1体目の敵を倒すと2枚のコインが発生してしまいます。
1枚は敵のいたところ、もう一枚は画面の左端のほうで発生。
敵のいたところで発生したコインには当たり判定があり、もう一枚のコインには当たり判定がない。2体目以降も同様。

1体目ででたコインを取らずに2体目を倒すと画面上に3枚のコインが存在し、
1体目と同様に倒した敵の場所にコインには当たり判定があり、2枚には当たり判定がありません。



考えているプログラム
敵を倒したらその敵のいた場所に1枚のコインを発生させる。
コインを取らずに2体目を倒すと1枚目のコインをそのままに2枚目のコインが発生させる。
コインと接触するとコインは消える。

jay
記事: 314
登録日時: 14年前
住所: 大阪市
連絡を取る:

Re: 。

#7

投稿記事 by jay » 13年前

hiro さんが書きました:breakを追加して実行してみたところ、1体目の敵を倒すと2枚のコインが発生してしまいます。
1枚は敵のいたところ、もう一枚は画面の左端のほうで発生。
そうなると今度は呼び出しの部分に不具合がある可能性が出て来ますね…
本来は敵を倒した時に一回だけ呼び出せばいい筈なのに、何故だか二回呼び出されてしまっているとか…
差し支えなければCoinSet関数を呼び出している部分のコードを張ってもらってもいいでしょうか?
♪僕たちは まだ森の中 抜け出そう 陽のあたる場所へ

ISLe
記事: 2650
登録日時: 14年前
連絡を取る:

Re: 。

#8

投稿記事 by ISLe » 13年前

CoinAnimation関数の中でループ回してるのがおかしいのではないですか?

hiro

Re: 。

#9

投稿記事 by hiro » 13年前

ISLe さんが書きました:CoinAnimation関数の中でループ回してるのがおかしいのではないですか?
そこはコインを回転させているので回りっぱなしで問題ないと思います。

コード:


//王と敵の当たり判定---------------------------
void EnemyAtari(void)
{
	int flag=0;

	if(kikori.dir==0)
	{
		if( Enemy[0].x+ENEMYSIZE_X>kikori.x && 
			Enemy[0].x<kikori.x+SHIPSIZE_X+ONOSIZE_X2 &&
			Enemy[0].y+ENEMYSIZE_Y>kikori.y &&
			Enemy[0].y<kikori.y+SHIPSIZE_Y)

		{
			flag=1;
		}
	}
	else
	{

		if(Enemy[0].x + ENEMYSIZE_X > kikori.x + ONOSIZE_X2 &&
			Enemy[0].x < kikori.x + SHIPSIZE_X &&
			Enemy[0].y + ENEMYSIZE_Y > kikori.y &&
			Enemy[0].y < kikori.y + SHIPSIZE_Y)
		{
			flag=1;
		}
	}

	if((ONOflag==GO||ONOflag==atack3||ONOflag==atack4) &&
		flag==1 && ENEMYflag1!=OFF)
	{		
		ENEMYflag1=OFF;
		flag=0;
		point++;//ポイントを加算
		CoinSet(Enemy[0].x,Enemy[0].y);//コイン発生
	}
}
自分で書いたソースではないのでわかりにくいとは思いますが
簡単にソースの説明を王と敵の当たり判定です。それと敵の存在消し、ポイント加算そしてCoinSetです。

ISLe
記事: 2650
登録日時: 14年前
連絡を取る:

Re: 。

#10

投稿記事 by ISLe » 13年前

hiro さんが書きました:
ISLe さんが書きました:CoinAnimation関数の中でループ回してるのがおかしいのではないですか?
そこはコインを回転させているので回りっぱなしで問題ないと思います。
そうですか。
フラグがONではないコインも描画しているように見えるのですがわたしの思い込みのようです。

jay
記事: 314
登録日時: 14年前
住所: 大阪市
連絡を取る:

Re: 。

#11

投稿記事 by jay » 13年前

ISLe さんが書きました:フラグがONではないコインも描画しているように見えるのですがわたしの思い込みのようです。
言われてみたら僕にもそう見えて来ました…

CoinMain関数でちゃんとコインの最大数分ループしているのに、移動や当たり判定やアニメーションの部分にもループがあるのはおかしいですね。
そのせいでどこかしら可笑しな挙動が出ているものと思われます。

もうひとつ疑問に思ったのですが、王と敵の当たり判定においてEnemyという配列で敵の情報を管理しているにも関わらず
Enemy[0]しか判定や処理がされてないのは何故なのでしょうか?
複数の敵を配列で管理しているのなら、敵の数だけ処理をループさせる必要があると思うのですが…。
♪僕たちは まだ森の中 抜け出そう 陽のあたる場所へ

hiro

Re: 。

#12

投稿記事 by hiro » 13年前

CoinAnimation関数について
for文は必要なさそうですね。
if文をfor文と勘違いしてました。

⇑のことを修正しました。
とりあえず敵を倒すとコインが1個だけ発生するようになりました。
(前回までは1体の敵に対して2個のコインが発生)

Enemyに関して自分が書いているわけではないのでコメントがほとんどないのでなぜこうなっているのかわかりません。
なので明日そのプログラマに聞いてみます。
とりあえずEnemy[0]のとこはEnemyとしてください。

hiro

Re: 。

#13

投稿記事 by hiro » 13年前

遅くなりなした。
メインプログラマーに聞いたところEnemy[0]はミスだったようです。
正しくはEnemyだそうです。
それを踏まえて改めてお願いします。

それともう一つ追加です。
コインの動きについてです。
敵が王の右にいるとき王が敵を倒したときコインを右に移動、
敵が王の左にいるとき王が敵を倒したときコインを左に移動させたいのですが
⇓のソースだと新たに敵が出るとコインがその方向に向かって動いてしまいます。
なんとなくはわかりのですがいざ書くとなるとわかりません。

コード:

//-----------------------------------------------------------
//コイン移動
//-----------------------------------------------------------
void CoinMove(int i)
{
	if(kikori.x < Enemy[i].x)//敵が王の右のとき
	{
		if(Enemy[i].flg == OFF)//敵の存在をしないならば
		{
			gCoin[i].x++;	//コインを右へ移動
		}
	}
	else if(kikori.x > Enemy[i].x)//敵が王の左のとき
	{
		if(Enemy[i].flg == OFF)//敵の存在しないならば
		{
			gCoin[i].x--;//コインを左へ移動
		}
	}
}

jay
記事: 314
登録日時: 14年前
住所: 大阪市
連絡を取る:

Re: 。

#14

投稿記事 by jay » 13年前

hiro さんが書きました:敵が王の右にいるとき王が敵を倒したときコインを右に移動、
敵が王の左にいるとき王が敵を倒したときコインを左に移動させたいのですが
そうですねぇ・・・

hiroさんが書いているコードは
if(Enemy.flg == OFF)//敵の存在をしないならば

となっていますよね?
でもiフラグがOFFになっていたら、新しくそこに敵が登録されてしまう可能性がある訳ですよね?
そうなるとiに既にコインがあるのに新しく敵がiに登録されて動作がおかしくなる、ということもあり得ると思います。

なのでここはコインの構造体に"移動方向"というメンバを作って
敵が王の右にいるとき王が敵を倒したときコインを右に移動、
つまりコインが登録されるときに移動方向をプラス方向(この場合は1でいいでしょう)設定してやって
コインの移動関数で毎F毎に移動方向の分だけ座標を動かしてやればいいですよ

敵が王の左にいるときも同じく、今度は移動方向をマイナス(-1ですね)に設定してやってください
後は上と同じようにすれば大丈夫です。

コインの登録関数だけでなく、移動関数もちゃんと書き変えてくださいね。
最後に編集したユーザー jay on 2011年12月04日(日) 23:50 [ 編集 1 回目 ]
♪僕たちは まだ森の中 抜け出そう 陽のあたる場所へ

hiro

Re: 。

#15

投稿記事 by hiro » 13年前

すいません。混乱してます。
”移動方向”のメンバとして”dir”を作りました。

コード:

//-----------------------------------------------------------
//コイン移動
//-----------------------------------------------------------
void CoinMove(int i)
{
	if(kikori.x < Enemy[i].x)//敵が王の右のとき
	{
		if(Enemy[i].dir == 1)
		{
		if(Enemy[i].flg == OFF)//敵の存在をしないならば
		{
			gCoin[i].x++;	//コインを右へ移動
		}
		}
	}
	else if(kikori.x > Enemy[i].x)//敵が王の左のとき
	{
		if(Enemy[i].dir = -1)
		{
		if(Enemy[i].flg == OFF)//敵の存在しないならば		
		{
			gCoin[i].x--;//コインを左へ移動
		}
		}
	}
}
こういうことでしょうか
一様、これでやってみましたが最初のコインが停止していてその後3つ目のコインから動きだしましたが進行方向を急に変わったりします。

jay
記事: 314
登録日時: 14年前
住所: 大阪市
連絡を取る:

Re: 。

#16

投稿記事 by jay » 13年前

こういうことでしょうか。 と聞かれたら「違います」と答えちゃいます。
やっぱり一遍に指摘しても分かりづらいですよね。 ひとつひとつ順番に指摘すればよかったと反省。

とりあえずまどろっこしくなってきたので正解のコード張り付けます。 まぁテストできないので責任は持てませんが(苦笑)
上手くいかなかった時は具体的にどこがダメだったのか教えてください・・・。

コード:

//------------------------------------------------------------
// コイン発生
//------------------------------------------------------------
void CoinSet(int x, int y)
{
	int i;
	//コインの数
	for(i=0; i<COIN_MAX; i++)
	{
		if(gCoin[i].flg == OFF)	//フラグの立っていない番号を検索
		{
			gCoin[i].flg = ON;//コインのフラグを立てる
			gCoin[i].x = x+20;//コインX座標を決定
			gCoin[i].y = y; //コインY座標を決定

			//移動量の決定
			if(kikori.x < gCoin[i].x)//コインの発生地点が王の右のとき
				gCoin[i].dir = 1;	//移動量を右方向へ

			else	//コインの発生地点が王の左のとき
				gCoin[i].dir = -1;	//移動量を左方向へ
		}
	}
}
//-----------------------------------------------------------
//コイン移動
//-----------------------------------------------------------
void CoinMove(int i)
{
	//移動量の分だけコインを移動させる
	gCoin[i].x += gCoin[i].dir;	
}
コインの移動はコード1行だけなのでコイン処理の関数に纏めてもいいかも知れませんね、お好きな方をどうぞ(どっちにしても登録関数はちゃんと書き変えてくださいね)

コード:

//----------------------------------------------------------------------
//コイン処理
//----------------------------------------------------------------------
void CoinMain()
{
	int i;
	//コインの数
	for(i=0; i<COIN_MAX; i++)
	{
		if(gCoin[i].flg == ON)//コインが存在したら
		{
			CoinAnimation();//コインアニメーション
			gCoin[i].x += gCoin[i].dir;	            //移動量の分だけコインを移動させる

			KikoriCoinHit(i);//王とコインの当たり判定
		}
	}
}
hiroさんのコードで根本的におかしいと思われるのはこの部分です

コード:

if(Enemy[i].flg == OFF)//敵の存在しないならば     
        {
            gCoin[i].x--;//コインを左へ移動
        }
コインはコインで単独で処理されるのに何故敵のフラグを判定する必要があるのでしょうか?
例えばgCoinの0番にコインを新しく登録したとします。
0番にコインを登録するということはつまりEnemyの0に登録されていた敵が倒されたということですよね。
つまりEnemy[0].flagはOFFになります
この状態だとhiroさんのコードの場合、コインが0番にまだ登録されている状態で新しくEnemyの0番に敵が登録されてしまったら(Enemy[0].flagがONになったら)動作がおかしくなってしまうのではないでしょうか? ということです。

コインはコインでちゃんとフラグの管理をしているのでそちらだけで判断すれば問題ないですよ
後は単にフラグが立っているコインを移動量の分だけ移動させればいいだけです。

まだ疑問が残るようなら質問してくださいね、答えますので。
♪僕たちは まだ森の中 抜け出そう 陽のあたる場所へ

hiro

Re: 。

#17

投稿記事 by hiro » 13年前

遅くなりなりました。

時間はかかりましたが1つ目の質問と後のコインの移動についてなんとか解決しました。
jayさんありがとうございました。

閉鎖

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