龍神録で、画像がボードからはみ出し半透明に表示されてしまう。

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

龍神録で、画像がボードからはみ出し半透明に表示されてしまう。

#1

投稿記事 by Itaru » 14年前

龍神録プログラミングをやっている者です。
他に特別なエラーも出なかったのでしばらく無視し続けてきたのですが、やはり直さなければならないと思い質問しました。
画像
この画像のように、自機画像や敵のショットなどがボード外に出てしまいます。
自機はボード内から外へ移動することはできませんのでゲーム進行に支障はありませんが、
やはり演出として気になります。

どういったエラーなのかわからないのでコードもどれを張ればいいかわかりません。
ご指摘等ございましたらいただければと思います。

Itaru

Re: 龍神録で、画像がボードからはみ出し半透明に表示されてしまう。

#2

投稿記事 by Itaru » 14年前

すみません、画像が表示されませんでした。リンクを張っておきます。
http://kie.nu/2eZ

Itaru

Re: 龍神録で、画像がボードからはみ出し半透明に表示されてしまう。

#3

投稿記事 by Itaru » 14年前

http://kie.nu/2f3
背景表示(20章)までいったらそれどころじゃありませんでした…
全部半透明になってしまってます。
ブレンドモードが間違ってるんでしょうか?
ご指摘よろしくお願いします。

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

Re: 龍神録で、画像がボードからはみ出し半透明に表示されてしまう。

#4

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

龍神録のプロジェクトはダウンロードできますので、そのソースコード比較して見ることをお勧めします。

便利なツール。
「WinMerge」
http://winmerge.org/

勘ですがSetDrawBlendMode()の使い方と自機や弾の生存・移動範囲のチェック処理あるいは範囲の値に問題があると思います。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Itaru

Re: 龍神録で、画像がボードからはみ出し半透明に表示されてしまう。

#5

投稿記事 by Itaru » 14年前

codeタグを修正させて頂きました。投稿前にプレビューでご確認下さい。  by softya(ソフト屋)

ありがとうございます。あれから教えていただいたソフトも使えるようになり、いろいろ試してみたんですがやはりだめでした…
WinMergeで比較し、正しく修正してもうまくいかないので、龍神録の20章のお手本ファイルをそのままコピーしたのですが、
「1>enemy.obj : error LNK2001: 外部シンボル ""void __cdecl enemy_pattern0(int)" (?enemy_pattern0@@YAXH@Z)" は未解決です。」
というエラーが出てしまいます。
enemy.cppのファイルなのですが、私の作成しているファイルの方にはお手本にはない敵の行動制御0番が入っていました。
もちろんenemyactの方にも0番は登録してあるのですが…そこを消してしまうとこのエラーが出てしまうようです。
本当に申し訳ないのですが八方ふさがりです。思い当たるコードを張らせていただきますので、
もしよろしければおかしなところ等ご教授願えればと思います。

enemy.cpp

コード:

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

extern void enemy_pattern0(int);
extern void enemy_pattern1(int);
extern void enemy_pattern2(int);
extern void enemy_pattern3(int);
extern void enemy_pattern4(int);
extern void enemy_pattern5(int);
extern void enemy_pattern6(int);
extern void enemy_pattern7(int);
extern void enemy_pattern8(int);
extern void enemy_pattern9(int);
extern void enemy_pattern10(int);

void(*enemy_pattern[ENEMY_PATTERN_MAX])(int) = {
	enemy_pattern0,
	enemy_pattern1,
	enemy_pattern2,
	enemy_pattern3,
	enemy_pattern4,
	enemy_pattern5,
	enemy_pattern6,
	enemy_pattern7,
	enemy_pattern8,
	enemy_pattern9,
	enemy_pattern10,
};

//敵の移動パターン0での移動制御

void enemy_pattern0(int i){
	int t=enemy[i].cnt;
	if(t == 0)
		enemy[i].vy=2;//降下
	if(t == 60)
		enemy[i].vy=0;//止まる
	if(t==60+enemy[i].wait)//停滞し
		enemy[i].vy=-2;//上がる
	}

//あいている敵番号を検索
int enemy_num_search(){
	for(int i=0;i<ENEMY_MAX;i++){
		if(enemy[i].flag==0){
	return i;//使用可能番号を返す
		}
	}
	return -1;//全部埋まっていたらエラーを返す
}
	//enemyのi番目のcntが60以下ならば
//enemyのi番目のyはy+2.0
//さらに、enemyのi番目のcntが300以上ならば
//enemyのi番目のyはy-2.0

//敵データ登録
void enemy_enter(){
	int i,j,t;
	for(t=0;t<ENEMY_ORDER_MAX;t++){
	if(enemy_order[t].cnt==stage_count){//現在の瞬間がオーダーの瞬間なら
		if((i=enemy_num_search())!=-1){
		enemy[i].flag	=1;//フラグ
		enemy[i].cnt	=0;//カウンタ
		enemy[i].pattern=enemy_order[t].pattern;//移動パターン
		enemy[i].muki	=1;//向き
		enemy[i].knd	=enemy_order[t].knd;
		enemy[i].x		=enemy_order[t].x;
		enemy[i].y		=enemy_order[t].y;
		enemy[i].sp		=enemy_order[t].sp;
		enemy[i].bltime	=enemy_order[t].bltime;
		enemy[i].blknd	=enemy_order[t].blknd;
		enemy[i].blknd2	=enemy_order[t].blknd2;
		enemy[i].col	=enemy_order[t].col;
		enemy[i].wait	=enemy_order[t].wait;
		enemy[i].hp		=enemy_order[t].hp;
		enemy[i].hp_max	=enemy[i].hp;
		enemy[i].vx		=0;
		enemy[i].vy		=0;
		enemy[i].ang	=0;
		enemy[i].back_col=GetRand(4);
		for(j=0;j<6;j++)
			enemy[i].item_n[j]=enemy_order[t].item_n[j];
			}
		}
	}
}

//弾幕開始制御
void enter_shot(int i){
	int j;
	for(j=0;j<SHOT_MAX;j++){//ショットフラグの立ってない敵を検索
		if(shot[j].flag==0){//ショットのフラグも立ってなかったら
			memset(&shot[j],0,sizeof(shot_t));//shot[j]を0でshot_t分だけ初期化
			shot[j].flag=1;
			shot[j].knd=enemy[i].blknd;//ショットの種類は敵の方から取得
			shot[j].num=i;//どの敵から発射されたものか
			shot[j].cnt=0;
			return;
		}
	}
}

			
//敵の行動制御
void enemy_act(){
	int i;
	for(i=0;i<ENEMY_MAX;i++){//iがenemyより大きくなる直前までiを足す
		if(enemy[i].flag==1){//i番目の敵のフラグがオンなら
			if(0<=enemy[i].pattern && enemy[i].pattern<ENEMY_PATTERN_MAX){
				enemy_pattern[enemy[i].pattern](i);
			enemy[i].x+=cos(enemy[i].ang)*enemy[i].sp;
			enemy[i].y+=sin(enemy[i].ang)*enemy[i].sp;
			enemy[i].x+=enemy[i].vx;
			enemy[i].y+=enemy[i].vy;
			enemy[i].cnt++;//enemyのi番目のcntに1足す
			enemy[i].img=enemy[i].muki*3+(enemy[i].cnt%18)/6;
			//敵が画面外に行ったら消す
			if(enemy[i].x<-20 || FIELD_MAX_X+20<enemy[i].x || enemy[i].y<-20 || FIELD_MAX_Y+20<enemy[i].y)
				enemy[i].flag=0;
			if(enemy[i].bltime==enemy[i].cnt)//敵の弾幕開始がカウントと同期したら
				enter_shot(i);//ショットを開始
		}
			else
				printfDx("enemy[i].patternの%d値が不正です。",enemy[i].pattern);
	}
}

}
//敵処理メイン
void enemy_main(){
	enemy_enter();//登録して
	enemy_act();//動かす
}


enemy_act_pattern.cpp

コード:

#include "../include/GV.h"
//-ang~angまでのランダムな角度を返す"rang関数"
double rang(double ang){
	return ( -ang + ang*2 * GetRand(10000)/10000.0);
}

//移動パターン0
//下がってきて停滞して上がっていく
void enemy_patturn0(int i){
	int t=enemy[i].cnt;
	if(t==0)
		enemy[i].vy=3;//下がってくる
	if(t==40)
		enemy[i].vy=0;//止まる
	if(t==40+enemy[i].wait)//登録された時間だけ停滞
		enemy[i].vy=-3;//上がる
}


//移動パターン1
//下がってきて停滞して左下に行く
void enemy_pattern1(int i){
    int t=enemy[i].cnt;
    if(t==0)
        enemy[i].vy=3;//下がってくる
    if(t==40)
        enemy[i].vy=0;//止まる
    if(t==40+enemy[i].wait){//登録された時間だけ停滞して
        enemy[i].vx=-1;//左へ
        enemy[i].vy=2;//下がっていく
        enemy[i].muki=0;//左向きセット
    }
}

//移動パターン2
//下がってきて停滞して右下に行く
void enemy_pattern2(int i){
    int t=enemy[i].cnt;
    if(t==0)
        enemy[i].vy=3;//下がってくる
    if(t==40)
        enemy[i].vy=0;//止まる
    if(t==40+enemy[i].wait){//登録された時間だけ停滞して
        enemy[i].vx=1;//右へ
        enemy[i].vy=2;//下がっていく
        enemy[i].muki=2;//右向きセット
    }
}

//行動パターン3
//すばやく降りてきて左へ
void enemy_pattern3(int i){
    int t=enemy[i].cnt;
    if(t==0)
        enemy[i].vy=5;//下がってくる
    if(t==30){//途中で左向きに
        enemy[i].muki=0;
    }
    if(t<100){
        enemy[i].vx-=5/100.0;//左向き加速
        enemy[i].vy-=5/100.0;//減速
    }
}

//行動パターン4
//すばやく降りてきて右へ
void enemy_pattern4(int i){
    int t=enemy[i].cnt;
    if(t==0)
        enemy[i].vy=5;//下がってくる
    if(t==30){//途中で右向きに
        enemy[i].muki=2;
    }
    if(t<100){
        enemy[i].vx+=5/100.0;//右向き加速
        enemy[i].vy-=5/100.0;//減速
    }
}

//行動パターン5
//斜め左下へ
void enemy_pattern5(int i){
    int t=enemy[i].cnt;
    if(t==0){
        enemy[i].vx-=1;
        enemy[i].vy=2;
        enemy[i].muki=0;
    }
}

//行動パターン6
//斜め右下へ
void enemy_pattern6(int i){
    int t=enemy[i].cnt;
    if(t==0){
        enemy[i].vx+=1;
        enemy[i].vy=2;
        enemy[i].muki=2;
    }
}

//移動パターン7
//停滞してそのまま左上に
void enemy_pattern7(int i){
    int t=enemy[i].cnt;
    if(t==enemy[i].wait){//登録された時間だけ停滞して
        enemy[i].vx=-0.7;//左へ
        enemy[i].vy=-0.3;//上がっていく
        enemy[i].muki=0;//左向き
    }
}

//移動パターン8
//停滞してそのまま右上に
void enemy_pattern8(int i){
    int t=enemy[i].cnt;
    if(t==enemy[i].wait){//登録された時間だけ停滞して
        enemy[i].vx=+0.7;//右へ
        enemy[i].vy=-0.3;//上がっていく
        enemy[i].muki=2;//右向き
    }
}

//移動パターン9
//停滞してそのまま上に
void enemy_pattern9(int i){
    int t=enemy[i].cnt;
    if(t==enemy[i].wait)//登録された時間だけ停滞して
        enemy[i].vy=-1;//上がっていく
}


//移動パターン10
//下がってきてウロウロして上がっていく
void enemy_pattern10(int i){
    int t=enemy[i].cnt;
    if(t==0) enemy[i].vy=4;//下がってくる
    if(t==40)enemy[i].vy=0;//止まる
    if(t>=40){
        if(t%60==0){
            int r=cos(enemy[i].ang)< 0 ? 0 : 1;
            enemy[i].sp=6+rang(2);
            enemy[i].ang=rang(PI/4)+PI*r;
            enemy[i].muki=2-2*r;
        }
        enemy[i].sp*=0.95;
    }
    if(t>=40+enemy[i].wait){
        enemy[i].vy-=0.05;
    }
}


cshot.cpp

コード:

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

int cshot0num[2]	={2,4};
int cshot0pos_x[4]	={-10, 10,-30, 30};
int cshot0pos_y[4]={-30,-30,-10,-10};

//ショット登録の空いている番号を返す
int search_cshot(){
	for(int i=0;i<CSHOT_MAX;i++){
		if(cshot[i].flag==0)
			return i;
	}
	return -1;
}

//通常ショット登録
void ch0_shot_pattern(){
	int k;
	for(int i=0;i<cshot0num[ch.power<200?0:1];i++){//a?b:c...aは真か偽か、真ならb、偽ならcを行う
	if((k=search_cshot())!=-1){
		cshot[k].flag=1;
		cshot[k].cnt=0;
		cshot[k].angle=-PI/2;
		cshot[k].spd=20;
		cshot[k].x=ch.x+cshot0pos_x[i];
		cshot[k].y=ch.y+cshot0pos_y[i];
		cshot[k].power=23;
		cshot[k].knd=0;
		}
	}
se_flag[2]=1;
}

//低速ショット登録
void ch1_shot_pattern(){
	int k;
	for(int i=0;i<cshot0num[ch.power<200?0:1];i++){//a?b:c...aは真か偽か、真ならb、偽ならcを行う
	if((k=search_cshot())!=-1){
		cshot[k].flag=1;
		cshot[k].cnt=0;
		cshot[k].angle=-PI/2;
		cshot[k].spd=20;
		cshot[k].x=ch.x+cshot0pos_x[i]/3;
		cshot[k].y=ch.y+cshot0pos_y[i]/2;
		cshot[k].power=23;
		cshot[k].knd=0;
		}
	}
se_flag[2]=1;
}

//ショット登録部
void enter_shot(){
	//ショットボタンが押されていたら
	if(CheckStatePad(configpad.shot)>0){
		ch.shot_cnt++;
		if(ch.shot_cnt%3==0){//3カウントに1回(連射制御?
			if(CheckStatePad(configpad.slow)>0)//低速移動中か?
				ch1_shot_pattern();
			else
				ch0_shot_pattern();
		}
	}
	else
		ch.shot_cnt=0;
}

//ショット移動計算
void calc_cshot(){
	for(int i=0;i<CSHOT_MAX;i++){
		if(cshot[i].flag==1){
			int dranx=cshot[i].spd+11/2,drany=cshot[i].spd;55/2;
			cshot[i].x+=cos(cshot[i].angle)*cshot[i].spd;
			cshot[i].y+=sin(cshot[i].angle)*cshot[i].spd;
			cshot[i].cnt++;
			if(cshot[i].x<-dranx || cshot[i].x>FIELD_MAX_X+dranx || cshot[i].y<-drany || cshot[i].y>FIELD_MAX_Y+drany)
				cshot[i].flag=0;//画面から消す
		}
	}
}

//自機ショットに関する関数全部
void cshot_main(){
	calc_cshot();//軌道計算
	enter_shot();//ショット登録
}
shot.cpp

コード:


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

extern void shot_bullet_H000(int);
extern void shot_bullet_H001(int);
extern void shot_bullet_H002(int);
extern void shot_bullet_H003(int);
extern void shot_bullet_H004(int);
extern void shot_bullet_H005(int);
extern void shot_bullet_H006(int);
extern void shot_bullet_H007(int);
extern void shot_bullet_H008(int);
extern void shot_bullet_H009(int);
extern void shot_bullet_H010(int);
extern void shot_bullet_H011(int);
extern void shot_bullet_H012(int);
extern void shot_bullet_H013(int);
extern void shot_bullet_H014(int);
extern void shot_bullet_H015(int);
extern void shot_bullet_H016(int);
extern void shot_bullet_H017(int);

void (*shot_bullet[SHOT_KND_MAX])(int) ={
	shot_bullet_H000,
	shot_bullet_H001,
	shot_bullet_H002,
	shot_bullet_H003,
	shot_bullet_H004,
	shot_bullet_H005,
	shot_bullet_H006,
	shot_bullet_H007,
	shot_bullet_H008,
	shot_bullet_H009,
	shot_bullet_H010,
	shot_bullet_H011,
	shot_bullet_H012,
	shot_bullet_H013,
	shot_bullet_H014,
	shot_bullet_H015,
	shot_bullet_H016,
	shot_bullet_H017,
};

//n番目のショットを登録した敵と自機との角度を返す
double shotatan2(int n){
	return atan2(ch.y-enemy[shot[n].num].y,ch.x-enemy[shot[n].num].x);
}

//空いている弾を探す
int shot_search(int n){
	int i;
	for(i=0;i<SHOT_BULLET_MAX;i++){
		if(shot[n].bullet[i].flag==0){
			return i;
		}
	}
	return -1;
}

void shot_calc(int n){
	int i,max=0;
	if(enemy[shot[n].num].flag!=1)//敵が倒されたら
		shot[n].flag=2;//それ以上ショットを登録しないフラグに変える
	for(i=0;i<SHOT_BULLET_MAX;i++){//n番目の弾幕データの弾を計算
		if(shot[n].bullet[i].flag>0){//その弾が登録されていたら
			shot[n].bullet[i].x+=cos(shot[n].bullet[i].angle)*shot[n].bullet[i].spd;
			shot[n].bullet[i].y+=sin(shot[n].bullet[i].angle)*shot[n].bullet[i].spd;
			shot[n].bullet[i].cnt++;
			if(shot[n].bullet[i].x<-50 || shot[n].bullet[i].x>FIELD_MAX_X+50 ||
				shot[n].bullet[i].y<-50 || shot[n].bullet[i].y>FIELD_MAX_Y+50){//画面外に外れたら
				if(shot[n].bullet[i].till<shot[n].bullet[i].cnt)//最低消えない時間より長ければ
					shot[n].bullet[i].flag=0;//消す
			}
		}
	}
	//現在表示中の弾が一つでもあるかどうか調べる
	for(i=0;i<SHOT_BULLET_MAX;i++)
		if(shot[n].bullet[i].flag>0)
			return;
	//現在表示中の弾が一つもなければ
	if(enemy[shot[n].num].flag!=1){
		shot[n].flag=0;//終了
		enemy[shot[n].num].flag=0;
	}
}

void shot_main(){
	int i;
	for(i=0;i<SHOT_MAX;i++){//弾幕データ計算
		//フラグが立っていて、設定した種類が間違っていなければ(オーバーフロー対策)
		if(shot[i].flag!=0 && 0<=shot[i].knd && shot[i].knd<SHOT_KND_MAX){
			shot_bullet[shot[i].knd](i);//.kndの弾幕計算関数を呼ぶ関数ポインタ
			shot_calc(i);//i番目の弾幕を計算
			shot[i].cnt++;
		}
	}
}

graph.cpp

コード:

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

void graph_enemy(){
	int i;
	for(i=0;i<ENEMY_MAX;i++){
		if(enemy[i].flag==1){
			DrawRotaGraphF(enemy[i].x+FIELD_X,enemy[i].y+FIELD_Y,1.0f,0.0f,img_enemy[0][enemy[i].img],TRUE);
		}
	}
}


void graph_ch(){//void型関数「graph」の定義して
	DrawRotaGraphF(ch.x+FIELD_X,ch.y+FIELD_Y,1.0f,0.0f,img_ch[0][ch.img],TRUE);
	//描画中心x,同じくy,拡大率,描画角度,GraphHandle,透過TF,反転TF
}

void graph_board(){//ボード書くための関数。img_board配列の中の画像ハンドルを呼ぶ
	DrawGraph(  0,  0, img_board[10],FALSE);
	DrawGraph(  0, 16, img_board[11],FALSE);
	DrawGraph(  0,464, img_board[12],FALSE);
	DrawGraph(416,  0, img_board[20],FALSE);
}


//弾丸の描画
void graph_bullet(){
	int i,j;
	SetDrawMode( DX_DRAWMODE_BILINEAR );//これが線形補完描画
	for(i=0;i<SHOT_MAX;i++){//敵弾幕数分ループ
		if(shot[i].flag>0){//弾幕フラグオンなら
			for(j=0;j<SHOT_BULLET_MAX;j++){//その弾幕の最大弾数分ループ
				if(shot[i].bullet[j].flag!=0){//弾フラグオンなら
					SetDrawBlendMode( DX_BLENDMODE_ADD,255);

				DrawRotaGraphF(
					shot[i].bullet[j].x+FIELD_X, shot[i].bullet[j].y+FIELD_Y,
					1.0,shot[i].bullet[j].angle+PI/2,
					img_bullet[shot[i].bullet[j].knd][shot[i].bullet[j].col],TRUE);
			if(shot[i].bullet[j].eff==1)
				SetDrawBlendMode(DX_BLENDMODE_NOBLEND,0);
				}
			}
		}
	}
	SetDrawMode(DX_DRAWMODE_NEAREST);//描画形式を戻す
}

void graph_cshot(){
	for(int i=0;i<CSHOT_MAX;i++){
		if(cshot[i].flag>0){
			DrawRotaGraphF(cshot[i].x+FIELD_X,cshot[i].y+FIELD_Y,1,0,img_cshot[cshot[i].knd],TRUE);
		}
	}
}

void graph_effect(){
	for(int i=0;i<EFFECT_MAX;i++){
		if(effect[i].flag>0){
			if(effect[i].eff==1)//1は光エフェクト
				SetDrawBlendMode( DX_BLENDMODE_ADD,effect[i].brt);
			DrawRotaGraphF(effect[i].x+FIELD_X,effect[i].y+FIELD_Y,effect[i].r,effect[i].ang,effect[i].img,TRUE);
			if(effect[i].eff==1)
				SetDrawBlendMode(DX_BLENDMODE_NOBLEND,0);
		}
	}
}

extern void graph_back_main();
	
void graph_main(){//ここで呼び出す
	graph_back_main();
	graph_effect();
	graph_enemy();
	graph_cshot();
	graph_ch();
	graph_bullet();
	graph_board();
}

その他必要なコードがございましたらお教えください。

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

Re: 龍神録で、画像がボードからはみ出し半透明に表示されてしまう。

#6

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

ぱっと目につくのはenemy.cppにあるenemy_pattern0と言う関数とenemy_act_pattern.cppにあるenemy_patturn0と言う関数です。
enemy_act_pattern.cppのenemy_patturn0は名前間違いですので、enemy.cppにあるenemy_pattern0を消すと見つからないエラーになると思いますよ。
「1>enemy.obj : error LNK2001: 外部シンボル ""void __cdecl enemy_pattern0(int)" (?enemy_pattern0@@YAXH@Z)" は未解決です。」 ← これ

VisualC++の場合は、名前を選んでおいて「すべての参照の検索」をすると参照先がない事で名前間違いをチェックできると思います。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

Itaru

Re: 龍神録で、画像がボードからはみ出し半透明に表示されてしまう。

#7

投稿記事 by Itaru » 14年前

ありがとうございます!ソフト屋さんのご指摘の点と、graph.cppをWinMergeで比較することにより見つかったコードの順番のミスを修正すると、元通りになりました!これで制作を続けられます、本当にありがとうございます!

閉鎖

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