太鼓の鉄人に・・・

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

太鼓の鉄人に・・・

#1

投稿記事 by Remi » 10年前

夜分失礼します。
前に太鼓の鉄人がビルドできない・・・とか言ってた初心者です。
あれからあーだこーだいいながら色々試しながら遊んでたのですが
音ゲーなのにコンボ表示がないことに違和感を感じたので作ったみたいと思ったのですが
全くといっていいほど、どこから手を付ければいいかわかりません。
一応 http://dixq.net/rp/41.html ここを見て
graph.cpp

コード:

//ヒットしたときの結果表示描画
void graph_kekka(){
	int i,flag=0;
	int keta;
	int combo;
	for(i=0;i<KEKKA_MAX;i++){
		if(kekka[i].flag==1){
			DrawRotaGraphF(kekka[i].x, kekka[i].y, kekka[i].range, 0.0, img_kekka[kekka[i].knd], TRUE); //結果表示
			 DrawRotaGraphF(kekka[i].x-20.0, kekka[i].y-16.0, kekka[i].range, 0.0, img_num[0], TRUE); //コンボと表示
			 combo=ch.combo;
				for(keta=0; combo !=0; keta++) combo/=10; //10で割った余りを使いコンボ数を調べる

			combo=ch.combo;
				for(int k=keta; k>0; k--){//コンボ数表示
					DrawRotaGraphF(kekka[i].x+30.0*k, kekka[i].y-20.0, kekka[i].range,0.0,img_num[combo%10],TRUE);
						combo/=10;
				}
			}
	}
}
load.cpp

コード:

void load(){
	img_back[0]=LoadGraph("dat/img/back.png");
	img_taiko[0]=LoadGraph("dat/img/taiko.png");
	img_taiko[1]=LoadGraph("dat/img/taiko2.png");
	img_effect[0]=LoadGraph("dat/img/hit.png");

	img_kekka[0]=LoadGraph("dat/img/kekka0.png");
	img_kekka[1]=LoadGraph("dat/img/kekka1.png");
	img_kekka[2]=LoadGraph("dat/img/kekka2.png");

	img_board[0]=LoadGraph("dat/img/score.png");
	img_board[1]=LoadGraph("dat/img/oya.png");

	img_num[0]=LoadGraph("dat/img/num.png");
	LoadDivGraph( "num.png" , 10 , 5, 2 , 16 , 18 , img_num ); //0から9を分割したのち配列img_numにしまう。
	sound_se[0]=LoadSoundMem("dat/se/don.wav");
	sound_se[1]=LoadSoundMem("dat/se/ka.wav");

	music.handle=LoadSoundMem("dat/music/0.ogg");

	
	color[0] = GetColor(255,255,255);//白
	color[1] = GetColor(  0,  0,  0);//黒
	color[2] = GetColor(255,  0,  0);//赤
	color[3] = GetColor(  0,255,  0);//緑
	color[4] = GetColor(  0,  0,255);//青
	color[5] = GetColor(255,255,  0);//黄色
	color[6] = GetColor(  0,255,255);//青緑
	color[7] = GetColor(255,  0,255);//紫
}
struct.h

コード:

//キャラクターに関する構造体
typedef struct{
	int flag;		//フラグ
	int cnt;		//カウンタ
	int score;		//スコア
	int num;		//残機数
	int state;		//ステータス
	int don,ka;	//ドン、カが押されたか
	int combo; //コンボ
	ch_hit_t hit;
}ch_t;
GV.h

コード:

//画像用変数宣言部
GLOBAL int img_back[10];	//バック画像
GLOBAL int img_taiko[10];	//たいこ画像
GLOBAL int img_effect[10];	//エフェクト画像
GLOBAL int img_kekka[10];	//ヒット結果表示画像
GLOBAL int img_board[10];	//ボード画像
GLOBAL int img_num[10]; //コンボ画像

こんな感じに変更したらnum.pngが表示されるにはされるのですが分割されてないただのpng画像で表示されてしまいます。
色々変なところもあると思うのですが・・・・・。ご教示お願い致します。 

zxc
記事: 79
登録日時: 13年前
住所: 日本の背骨(?)あたり

Re: 太鼓の鉄人に・・・

#2

投稿記事 by zxc » 10年前

コード:

    img_num[0]=LoadGraph("dat/img/num.png");
    LoadDivGraph( "num.png" , 10 , 5, 2 , 16 , 18 , img_num ); //0から9を分割したのち配列img_numにしまう。
 この部分にどういう意図があるんでしょうか。とりあえず同名の画像ファイルがそれぞれの階層に存在しない限りimg_num[1]~img_num[9]に有効なグラフィックハンドルが入ることはないような気がしますし、同じ変数に同じ画像を二回ロードする意図がわかりません(厳密には同じではないかもしれませんけど)。そういうデバッグ方法なら構いませんが・・・
 もしまだやっていないのなら、関数の返り値やグラフィックハンドルが有効なものなのかを調べるべきです。

Remi

Re: 太鼓の鉄人に・・・

#3

投稿記事 by Remi » 10年前

色々やっていたら グラフィックの分割に失敗しました in CreateDivGraphFromGraphImageというエラーがでるようになりました。

関数LoadDivGraph(FileName,AllNum,XNum,YNum,XSize,YSize,HandleBuf);の値は使っている画像サイズに対してどう計算すれば良いのでしょうか?
ちなみに数字画像はサイズが100×10で0~9が横並びになっているものです。
よろしくお願い致します。

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: 太鼓の鉄人に・・・

#4

投稿記事 by みけCAT » 10年前

Remi さんが書きました:関数LoadDivGraph(FileName,AllNum,XNum,YNum,XSize,YSize,HandleBuf);の値は使っている画像サイズに対してどう計算すれば良いのでしょうか?
ちなみに数字画像はサイズが100×10で0~9が横並びになっているものです。
よろしくお願い致します。
リファレンスを見てもわからないですか?
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

Remi

Re: 太鼓の鉄人に・・・

#5

投稿記事 by Remi » 10年前

0~9の10分割,横並びなのでXnum=10 Ynum=1とするとこまではいいのですがXSize,Ysizeを決めかねてる状況です。ポインタはimg_numに格納しています。
LoadDivGraph("dat/img/num.png",10,10,1,XSize,YSize,img_num);

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: 太鼓の鉄人に・・・

#6

投稿記事 by みけCAT » 10年前

XSize, YSizeは分割後の画像1個の大きさを入れます。
「サイズが100×10で0~9が横並びになっている」ということなので、多分XSize=10, YSize=10だと思います。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

Remi

Re: 太鼓の鉄人に・・・

#7

投稿記事 by Remi » 10年前

なるほど、そういった決め方をしているんですね。 
LoadDivGraph( "dat/img/num.png",10,10,1,10,10,img_num ); //0から9を分割したのち配列img_numにしまう。
としてやってみたら無事分割されました。ただ分割しただけなので表示されるのは「0」だけですが笑。
一番初めにもお伝えしたようにどこから手を付ければいいんだ・・・状態なので次にやるべきことのヒントを与えてくだされば・・・なんて思います。
一からコツコツ確認しながらやっていこうと思いますのでお願いします。

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

Re: 太鼓の鉄人に・・・

#8

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

音ゲーのコンボがわからないので答えようが無いですが、具体的に何が出来ないのか質問されたほうが良いと思います。
分からないことを整理して下さい。
プログラムを作るというのは物事を順序だって整理することから始まりますよ。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Remi

Re: 太鼓の鉄人に・・・

#9

投稿記事 by Remi » 10年前

すみません。画像の分割に成功したので次に考えてるのはキーを入力した際 
PERFECT,GOODまでの範囲になっているなら画像の数字が+1されてそうではないなら0になる、というものです。(これでコンボ数を表現したい)

bullet.cppに加算を意味するadd関数があったのでこれを使ってなんとかならないのかな?と思っています。

コード:

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

extern void enter_kekka(int n, int knd, double x, double y);
extern int serch_kekka();

//スコア加算
void add_score(int knd){
	int score[3]={20,0,-50};
	ch.state+=score[knd];
	if(ch.state<0)
		ch.state=0;
	if(ch.state>1000)
		ch.state=1000;
}	

//登録可能な弾を見つける
int serch_bullet(){
	int i;
	for(i=0;i<BULLET_MAX;i++){
		if(bullet[i].flag==0){
			return i;
		}
	}
	return -1;
}

//弾を実際に登録する
void enter_bullet(int n, int knd, double spd){
	bullet[n].flag=1;
	bullet[n].x=HIT_X+stage.spd*180;
	bullet[n].y=HIT_Y;
	bullet[n].knd=knd;
	bullet[n].spd=spd;
}

//弾の登録計算
void input_bullet(){
	int k;
	double sc0=stage.cnt*16.6666666666, sc1=(stage.cnt+1)*16.6666666666;
	double cnt=music.term*humen[stage.humen_cnt].cnt;
	if(sc0<=cnt && cnt<sc1){
		if((k=serch_bullet())!=-1){
			enter_bullet(k,humen[stage.humen_cnt].knd-1,stage.spd);
		}
		stage.humen_cnt++;
	}
}

//弾の計算
void calc_bullet(){
	int i,j,k;
	for(i=0;i<BULLET_MAX;i++){
		if(bullet[i].flag==1){
			bullet[i].x-=bullet[i].spd;
			bullet[i].cnt++;
			if(bullet[i].x<HIT_X-BOO_X){
				if((k=serch_kekka())!=-1){
					enter_kekka(k,2,bullet[i].x,HIT_Y-40);
					add_score(2);
				}
				bullet[i].flag=0;
			}
		}
	}
	for (i = 0; i < BULLET_MAX; i++) {
		for (j = i + 1; j < BULLET_MAX; j++) {
			if (bullet[i].flag==1 && bullet[j].flag==1 && bullet[i].x < bullet[j].x) {
				bullet_t t;
				t=bullet[i];	bullet[i]=bullet[j];	bullet[j]=t;
			}
		}
	}
}

/*
本当はここで、ヒットした弾IDと弾の座標を記憶しておき、
ヒットが近かった物を結果ヒットとする処理と、
もし同じ距離の2つヒットした弾があれば左側をヒットとする処理を追加する必要がある
*/

//ヒットしたデータを格納するもの
#define HIT_DAT_MAX 20
typedef struct{
	int flag,id,knd;
	double x;
}hit_dat_t;

//ヒットしたデータを格納する登録可能番号を返す
int serch_hit_dat(hit_dat_t hit_dat[]){
	int i;
	for(i=0;i<HIT_DAT_MAX;i++){
		if(hit_dat[i].flag==0){
			return i;
		}
	}
	return -1;
}

//ヒットしたデータを登録する
void enter_hit_dat(int n, int id, int knd, double x, hit_dat_t hit_dat[]){
	hit_dat[n].flag=1;
	hit_dat[n].id=id;
	hit_dat[n].knd=knd;
	hit_dat[n].x=x;
}

//ヒットしたかどうかを判定する
void hit_bullet(){
	int i,j,k,knd;
	double x,pre_x,x0,x1;
	double line_x[3]={PERFECT_X,GOOD_X,BOO_X};
	hit_dat_t hit_dat[HIT_DAT_MAX];
	memset(hit_dat,0,sizeof(hit_dat_t)*HIT_DAT_MAX);

	for(i=0;i<BULLET_MAX;i++){//弾分ループ
		if(bullet[i].flag==1){//弾が存在していて
			knd=-1;
			pre_x=bullet[i].x+bullet[i].spd;
			x=bullet[i].x;
			for(j=0;j<3;j++){
				x0=HIT_X-line_x[j];
				x1=HIT_X+line_x[j];
				if(x<x0 && x0<pre_x || x<x1 && x1<pre_x || x0<x && x<x1 || x0<pre_x && pre_x<x1){//距離ヒット以内なら
					knd=j;
					break;
				}
			}
			//距離OKでその時たたいていたら
			if(knd!=-1 && (ch.don==1  && bullet[i].knd==0 || bullet[i].knd==1 && ch.ka==1)){
				if((k=serch_hit_dat(hit_dat))!=-1){
					enter_hit_dat(k,i,knd,bullet[i].x,hit_dat);
				}
			}
		}
	}
	int num=0;
	for(i=0;i<HIT_DAT_MAX;i++){//ヒットした分
		if(hit_dat[i].flag==1){//数える
			num++;
		}
	}
	if(num>0){//ヒットしたもんがあったら
		/*ここでヒットしたデータをkndごとにソートする*/
		/*今回はここは省略し、単にHIT_Xに近い物をヒットとする*/
		for (i = 0; i < num - 1; i++) {
			for (j = i + 1; j < num; j++) {
				if (fabs(hit_dat[i].x-HIT_X) > fabs(hit_dat[j].x-HIT_X)) {
					hit_dat_t t;
					t=hit_dat[i];	hit_dat[i]=hit_dat[j];	hit_dat[j]=t;
				}
			}
		}
		i=hit_dat[0].id; knd=hit_dat[0].knd; x=hit_dat[0].x;
		//登録処理
		if((k=serch_kekka())!=-1){
			enter_kekka(k,knd,x,HIT_Y-40);
			add_score(knd);
		}
		bullet[i].flag=0;
	}
	//効果音を鳴らす
	if(ch.don==1)
		se_flag[0]=1;
	if(ch.ka==1)
		se_flag[1]=1;
}

void auto_play(){
	int i;
	double x,x0,x1;
	for(i=0;i<BULLET_MAX;i++){//弾分ループ
		if(bullet[i].flag==1){//弾が存在していて
			x=bullet[i].x;
			x0=HIT_X-1;
			x1=HIT_X+1;
			if(x0<x && x<x1){//距離ヒット以内なら
				if(bullet[i].knd==0)
					ch.don=1;
				if(bullet[i].knd==1)
					ch.ka=1;
			}
		}
	}
}

void bullet_main(){

	/*ここの注釈を外すとオートプレイになる*/
	//	auto_play();

	input_bullet();
	calc_bullet();
	hit_bullet();
}

またchar.cppにキー入力の処理を追加することでなんとかならないかな・・・?なんて思っています。

コード:

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

void calc_ch(){
	
	//入力に対してステータスを変化させる
	if(CheckStateKey(KEY_INPUT_LEFT)==1 || CheckStateKey(KEY_INPUT_RIGHT)==1)
		ch.ka=1;
	else
		ch.ka=0;
	if(CheckStateKey(KEY_INPUT_DOWN)==1)
		ch.don=1;
	else
		ch.don=0;

	//入力が行われた時におこるエフェクトを登録
	if(ch.ka==1 || ch.don==1){
		ch.hit.flag=1;
	}
	if(ch.hit.flag==1){
		ch.hit.cnt++;
		if(ch.hit.cnt>HIT_EFFECT_CNT){
			ch.hit.flag=0;
			ch.hit.cnt=0;
		}
	}
}
コーディングはまだ特にしていないです。サンプルプログラムを元に作らせていただこうと思います。

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

Re: 太鼓の鉄人に・・・

#10

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

では、やってみたらどうでしょうか?
試行錯誤したいってことなら、やってみることです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: 太鼓の鉄人に・・・

#11

投稿記事 by みけCAT » 10年前

余計なお世話かもしれませんが、
Gitを使うと、失敗してこんがらがった時に元に戻しやすくなるので、
実験がやりやすくなるかもしれません。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

Remi

Re: 太鼓の鉄人に・・・

#12

投稿記事 by Remi » 10年前

全然わかりませんでしたorz(震え声。
頭ではこれをこうして・・・と思い浮かんでもいざ書いてみると全くかけません。ダメダメでした・・・・
噫無情。     (タスケテクダサイ)

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: 太鼓の鉄人に・・・

#13

投稿記事 by みけCAT » 10年前

Remi さんが書きました:頭ではこれをこうして・・・と思い浮かんでも
まずそれを(C++ではなく、擬似コードや日本語などで)書くことはできますか?
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

Remi

Re: 太鼓の鉄人に・・・

#14

投稿記事 by Remi » 10年前

流れというか役割?・・・。

1.graph.cppdでは数字画像の分割読み込み→それをただ描画(ここまでできてる)

2.bullet.cpp では加算部分の作成
graph.cppではただ分割読み込みしただけなので数字が増える又は0に戻る仕組みをここで作りたいです。。。

↓のような感じを想像していました。
void ○○{
if(もし弾がヒット距離内なら){
 変数○を代入(+)していって
else
そうじゃなかったら0に戻す


3.char.cppでは入力処理の追加を・・・・
ここはさっぱりです

これくらいしか。。。 やること多すぎて難しくて頭を抱えてますw 
ただ、ちょっとずつでもわかってくると楽しいですね~w 理解するのにだいぶ挫けてる気がしますが。。

beat'

Re: 太鼓の鉄人に・・・

#15

投稿記事 by beat' » 10年前

頭でやることが分かっていて一応文章でも表せる(?)ようなので、ほんとその通り実装してみれば良いだけの気がしますがねぇ…
分からない分からない言って教えを乞うているだけでは思考放棄と同じですよ。
時間が掛かっても良いので、全部を一変に作ろうとせずそれぞれの処理を順々に作っていきましょう(=゚ω゚)ノ

Remi

Re: 太鼓の鉄人に・・・

#16

投稿記事 by Remi » 10年前

beat'さん>
そうですよね。それぞれの処理をゆっくり作ってみようと思います。 

Remi

Re: 太鼓の鉄人に・・・

#17

投稿記事 by Remi » 10年前

できそうなことからやっていこうということで

コード:

//スコアの描画
void mozi(){
	SetFontSize(30);
	DrawFormatString(0,0,color[0],"現在のスコア%d",ch.state);
}

コード:

//スコア加算
void add_score(int knd){
	int score[3]={20,0,-50};
	ch.state+=score[knd];
	if(ch.state<0)
		ch.state=0;
	if(ch.state>1000)
		ch.state=1000;
}	
コンボ表示ではなくスコアの表示を作ってみましたw ch.stateの値は0にしておいてそこか増えたり減ったり・・・みたいな感じですw
画像を使うとなんかイマイチなので普通に文字で描写してみました。

そうそう、あのサンプルプログラムを弄り倒してたらこんなのが表示されました。これは何を意味するのでしょうか?
実行してみて放置していると一定の時間になったら強制終了してしまいますw
Alloc memory dump
size:3000(2.930kb) file: line:0 ID:36211 addr:0e734028 data:<...~~...........> [fd fd da 7e 7e fc fd fd fd fd fd fd fc fc fc fd]
Total size:3000(2.930kb) Alloc num:1

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

Re: 太鼓の鉄人に・・・

#18

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

それはメモリリークですね。 mallocしたまま開放されていないメモリがあります。
メモリリークが累積した場合はPCが遅くなり、やがてゲームが異常終了します。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Remi

Re: 太鼓の鉄人に・・・

#19

投稿記事 by Remi » 10年前

なるほど解放されてないメモリですか・・・
どこが解放されてないか探してみます・・・

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

Re: 太鼓の鉄人に・・・

#20

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

DXライブラリの画像ハンドルの管理に失敗しても異常終了するのでそちらもご確認を。
LoadGraphした画像ハンドルをdeleteGraphせずに上書きするなど、LoadGraphを毎フレーム呼び出してしまっていたりするとあっという間です。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Remi

Re: 太鼓の鉄人に・・・

#21

投稿記事 by Remi » 10年前

softyaさんの言うとおりでした。
見なおしていたらLoadGraphの1つにdeleteGraphがなくそのせいでどんどんメモリがくわれてたみたいです。
最初のテーマ内容についてはわかったし今の内容がそれとだいぶ違っているのでここらへんで終わりにしますね;;。

色々なことを教えてくださった
みけCATさん、softyaさん、beat'さんありがとうございました。

閉鎖

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