ページ 1 / 1
太鼓の鉄人に・・・
Posted: 2014年12月21日(日) 02:57
by Remi
夜分失礼します。
前に太鼓の鉄人がビルドできない・・・とか言ってた初心者です。
あれからあーだこーだいいながら色々試しながら遊んでたのですが
音ゲーなのにコンボ表示がないことに違和感を感じたので作ったみたいと思ったのですが
全くといっていいほど、どこから手を付ければいいかわかりません。
一応
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画像で表示されてしまいます。
色々変なところもあると思うのですが・・・・・。ご教示お願い致します。
Re: 太鼓の鉄人に・・・
Posted: 2014年12月21日(日) 03:23
by zxc
コード:
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]に有効なグラフィックハンドルが入ることはないような気がしますし、同じ変数に同じ画像を二回ロードする意図がわかりません(厳密には同じではないかもしれませんけど)。そういうデバッグ方法なら構いませんが・・・
もしまだやっていないのなら、関数の返り値やグラフィックハンドルが有効なものなのかを調べるべきです。
Re: 太鼓の鉄人に・・・
Posted: 2014年12月21日(日) 11:55
by Remi
色々やっていたら グラフィックの分割に失敗しました in CreateDivGraphFromGraphImageというエラーがでるようになりました。
関数LoadDivGraph(FileName,AllNum,XNum,YNum,XSize,YSize,HandleBuf);の値は使っている画像サイズに対してどう計算すれば良いのでしょうか?
ちなみに数字画像はサイズが100×10で0~9が横並びになっているものです。
よろしくお願い致します。
Re: 太鼓の鉄人に・・・
Posted: 2014年12月21日(日) 12:07
by みけCAT
Remi さんが書きました:関数LoadDivGraph(FileName,AllNum,XNum,YNum,XSize,YSize,HandleBuf);の値は使っている画像サイズに対してどう計算すれば良いのでしょうか?
ちなみに数字画像はサイズが100×10で0~9が横並びになっているものです。
よろしくお願い致します。
リファレンスを見てもわからないですか?
Re: 太鼓の鉄人に・・・
Posted: 2014年12月21日(日) 12:20
by Remi
0~9の10分割,横並びなのでXnum=10 Ynum=1とするとこまではいいのですがXSize,Ysizeを決めかねてる状況です。ポインタはimg_numに格納しています。
LoadDivGraph("dat/img/num.png",10,10,1,XSize,YSize,img_num);
Re: 太鼓の鉄人に・・・
Posted: 2014年12月21日(日) 12:30
by みけCAT
XSize, YSizeは分割後の画像1個の大きさを入れます。
「サイズが100×10で0~9が横並びになっている」ということなので、多分XSize=10, YSize=10だと思います。
Re: 太鼓の鉄人に・・・
Posted: 2014年12月21日(日) 12:43
by Remi
なるほど、そういった決め方をしているんですね。
LoadDivGraph( "dat/img/num.png",10,10,1,10,10,img_num ); //0から9を分割したのち配列img_numにしまう。
としてやってみたら無事分割されました。ただ分割しただけなので表示されるのは「0」だけですが笑。
一番初めにもお伝えしたようにどこから手を付ければいいんだ・・・状態なので次にやるべきことのヒントを与えてくだされば・・・なんて思います。
一からコツコツ確認しながらやっていこうと思いますのでお願いします。
Re: 太鼓の鉄人に・・・
Posted: 2014年12月21日(日) 13:08
by softya(ソフト屋)
音ゲーのコンボがわからないので答えようが無いですが、具体的に何が出来ないのか質問されたほうが良いと思います。
分からないことを整理して下さい。
プログラムを作るというのは物事を順序だって整理することから始まりますよ。
Re: 太鼓の鉄人に・・・
Posted: 2014年12月21日(日) 13:30
by Remi
すみません。画像の分割に成功したので次に考えてるのはキーを入力した際
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;
}
}
}
コーディングはまだ特にしていないです。サンプルプログラムを元に作らせていただこうと思います。
Re: 太鼓の鉄人に・・・
Posted: 2014年12月21日(日) 15:20
by softya(ソフト屋)
では、やってみたらどうでしょうか?
試行錯誤したいってことなら、やってみることです。
Re: 太鼓の鉄人に・・・
Posted: 2014年12月21日(日) 15:22
by みけCAT
余計なお世話かもしれませんが、
Gitを使うと、失敗してこんがらがった時に元に戻しやすくなるので、
実験がやりやすくなるかもしれません。
Re: 太鼓の鉄人に・・・
Posted: 2014年12月21日(日) 16:58
by Remi
全然わかりませんでしたorz(震え声。
頭ではこれをこうして・・・と思い浮かんでもいざ書いてみると全くかけません。ダメダメでした・・・・
噫無情。 (タスケテクダサイ)
Re: 太鼓の鉄人に・・・
Posted: 2014年12月21日(日) 17:05
by みけCAT
Remi さんが書きました:頭ではこれをこうして・・・と思い浮かんでも
まずそれを(C++ではなく、擬似コードや日本語などで)書くことはできますか?
Re: 太鼓の鉄人に・・・
Posted: 2014年12月21日(日) 17:55
by Remi
流れというか役割?・・・。
1.graph.cppdでは数字画像の分割読み込み→それをただ描画(ここまでできてる)
2.bullet.cpp では加算部分の作成
graph.cppではただ分割読み込みしただけなので数字が増える又は0に戻る仕組みをここで作りたいです。。。
↓のような感じを想像していました。
void ○○{
if(もし弾がヒット距離内なら){
変数○を代入(+)していって
else
そうじゃなかったら0に戻す
}
3.char.cppでは入力処理の追加を・・・・
ここはさっぱりです
これくらいしか。。。 やること多すぎて難しくて頭を抱えてますw
ただ、ちょっとずつでもわかってくると楽しいですね~w 理解するのにだいぶ挫けてる気がしますが。。
Re: 太鼓の鉄人に・・・
Posted: 2014年12月21日(日) 18:06
by beat'
頭でやることが分かっていて一応文章でも表せる(?)ようなので、ほんとその通り実装してみれば良いだけの気がしますがねぇ…
分からない分からない言って教えを乞うているだけでは思考放棄と同じですよ。
時間が掛かっても良いので、全部を一変に作ろうとせずそれぞれの処理を順々に作っていきましょう(=゚ω゚)ノ
Re: 太鼓の鉄人に・・・
Posted: 2014年12月21日(日) 18:15
by Remi
beat'さん>
そうですよね。それぞれの処理をゆっくり作ってみようと思います。
Re: 太鼓の鉄人に・・・
Posted: 2014年12月23日(火) 00:05
by Remi
できそうなことからやっていこうということで
コード:
//スコアの描画
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
Re: 太鼓の鉄人に・・・
Posted: 2014年12月23日(火) 20:23
by softya(ソフト屋)
それはメモリリークですね。 mallocしたまま開放されていないメモリがあります。
メモリリークが累積した場合はPCが遅くなり、やがてゲームが異常終了します。
Re: 太鼓の鉄人に・・・
Posted: 2014年12月23日(火) 21:55
by Remi
なるほど解放されてないメモリですか・・・
どこが解放されてないか探してみます・・・
Re: 太鼓の鉄人に・・・
Posted: 2014年12月23日(火) 22:41
by softya(ソフト屋)
DXライブラリの画像ハンドルの管理に失敗しても異常終了するのでそちらもご確認を。
LoadGraphした画像ハンドルをdeleteGraphせずに上書きするなど、LoadGraphを毎フレーム呼び出してしまっていたりするとあっという間です。
Re: 太鼓の鉄人に・・・
Posted: 2014年12月23日(火) 22:51
by Remi
softyaさんの言うとおりでした。
見なおしていたらLoadGraphの1つにdeleteGraphがなくそのせいでどんどんメモリがくわれてたみたいです。
最初のテーマ内容についてはわかったし今の内容がそれとだいぶ違っているのでここらへんで終わりにしますね;;。
色々なことを教えてくださった
みけCATさん、softyaさん、beat'さんありがとうございました。