Justyさんが作成した炎サンプルを利用して

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

Justyさんが作成した炎サンプルを利用して

#1

投稿記事 by kai » 15年前

Justyさんがちょっと前に作成した炎サンプルを
改造している龍神録につないでみようと試みた(ボスの後ろに描画)のですが、
particleがなぜか5で固定されてしまい、
微妙な炎しか描画できなかったのですが、どうしたらうまくいくのでしょうか?
解決策がわかる方がいましたら教えてください><
以下、60章に追加、変更した部分↓

common_type.h、dxl_peripheral.h、vector2.h
はそのまんまヘッダーファイルに入れて
#include "common/common_type.h"は削除。

dxl_peripheral.cppは
#include "dxl_peripheral.h"
#include <DxLib.h>
を削除

effect_fire.cppの中身は
graph.cpp内の適当な場所に切り取り&貼り付け
そのときに変更した部分(コメントアウトや変更した部分)は添付参照

void graph_boss()内の適当な場所に
MainLoop();
を追加。

Justy

Re:Justyさんが作成した炎サンプルを利用して

#2

投稿記事 by Justy » 15年前

 書き直そう! といって忙しくてちっとも書き直せていないんですが、
添付のコードであからさまにおかしいのは 各種オブジェクトの生成位置が
元々メインループの外にあったものが中に入ってしまっているところです。

 具体体には fire、pauseCtrlです。
 MainLoop関数そのものがメインループの中に入ってしまっていると
するなら、fireオブジェクトはローカル変数なので MainLoop関数が呼ばれる度に
生成・破棄されることになり、その度に火の状態はリセットされてしまいます。

 なので fireが常に同じオブジェクトになるよう変更すれば直ると思うのですが、
まず(あまりいい方法ではないので)テストとして fireの宣言に staticをつけてみて下さい。

[color=#d0d0ff" face="monospace]
static Effect::Fire fire;
[/color]


 それでうまくいくようなら、fireオブジェクトを別のところで管理・保持するよう
変更してみて下さい。

kai

Re:Justyさんが作成した炎サンプルを利用して

#3

投稿記事 by kai » 15年前

staticを追加してみると一応上手く描画できました。ありがとうございます。

>fireオブジェクトを別のところで管理・保持するよう
>変更してみて下さい
すみません。これは具体的にはどうしたらよいのでしょうか?

Justy

Re:Justyさんが作成した炎サンプルを利用して

#4

投稿記事 by Justy » 15年前


> これは具体的にはどうしたらよいのでしょうか?

 結局のところ、同一のインスタンス(オブジェクト)を Updateし続けることで継続して
火として成り立つので、同じオブジェクトでさえあればいいのです。

 持たせるとしたら大抵はエフェクトを出すべきオブジェクト、例えば火が松明の火であれば
松明が、蝋燭の火なら蝋燭、プレイヤーが燃えてるならプレイヤーに持たせれば
いいのではないでしょうか。


 ただ、Fireクラスをグローバル変数にしたり、グローバル変数の別のオブジェクトに
持たせたりはしないで下さい。

 今の状態ですと、Fireクラスのコンストラクタでテクスチャのロードを
行っているので、グローバル変数などにすると読み込みに失敗します。
(テクスチャの読み込みは DxLib_Init後でないと成功しない)

 その場合は、Fireクラスのポインタにしておいて、後から必要に応じて newして
インスタンス化して下さい。


# うーん、これクラスになっているんで龍神録のプログラムとは
なじまないような気がします……。

kai

Re:Justyさんが作成した炎サンプルを利用して

#5

投稿記事 by kai » 15年前

Justyさんありがとうございます。
アドバイス通りにこれからやってみたいと思います。
もうひとつ聞きたいことがあるのですが、
一応現段階では
boss.back_knd[boss.knd]==1、スペルカード時に描画するようにしているのですが
この描画してるさいFPSが30くらいになり、もの凄く処理落ちして困ってるのですが
何が原因なのでしょうか?

Justy

Re:Justyさんが作成した炎サンプルを利用して

#6

投稿記事 by Justy » 15年前


> もの凄く処理落ちして困ってる

 まずはソートを止めてみて下さい。ソートを止めてもこのパラメータなら
見た目たいした違いはないはずです。

 それでも処理落ちが改善されないのであれば描画面積やパーティクルの枚数(発生頻度)を減らし、
それでもやっぱりダメなら別の方法を考えた方がいいのかもしれません。

kai

Re:Justyさんが作成した炎サンプルを利用して

#7

投稿記事 by kai » 15年前

すみません。言葉足らずでした。
通常の炎の場合は処理落ちしないのですが、
// 煙の ON/OFF
if(DXL::Peripheral::Mouse::Down(DXL::Peripheral::Mouse::ButtonType_Right))
の個所を
if(boss.hp<2000){ //ボスが死にそうなら
     fire.SetUseSmoke(!fire.GetUseSmoke());
}
に変えたとき、煙エフェクトが出たら処理落ちしました。

ついでに聞きたいのですが、
これって初期化はどうすればいいのでしょうか?
支館様より、ボス戦の途中、最初から戻るなどでリセットした場合、
もう一度ボスに出会うと、前の炎があった場所から炎が微妙に残って描画され、悩んでます。

Justy

Re:Justyさんが作成した炎サンプルを利用して

#8

投稿記事 by Justy » 15年前


> 煙エフェクトが出たら処理落ちしました

 なんかそのコードですと毎フレーム煙を ONにしたり OFFにしたりしそうに
見えますが、その処理落ちはソートをコメントアウトしてもそうなりますか?

 あと、releaseビルドだとどうなりますか?



> これって初期化はどうすればいいのでしょうか?
> 前の炎があった場所から炎が微妙に残って描画され

 それは同じオブジェクトを使い回していませんか?
 同じオブジェクトを別のところで使えば、前の状態を覚えているので、それを
引きずっていまうのは自然です。

 なので、使わなくなったオブジェクトは破棄して、新規にオブジェクトを生成すれば
初期化されます。
(そうなるとコンストラクタでの LoadGraphは少し考えないといけませんが)


 どうしても同じオブジェクトを使い回したいのであれば……そうですね、こんな感じでしょうか。

 Fireクラスに Endメンバ関数を追加して、それが呼ばれた以降は新規のパーティクルの
生成を停止(AddFiresを呼ばない)するようにして下さい。

 Startメンバ関数を追加してそれが呼ばれた以降は新規のパーティクルの
生成を行う(AddFiresを呼ぶ)ようにして下さい。

 それから Resetメンバ関数も追加して、その中で m_Firesコンテナを空にして下さい。
 ついでに、その他のパラメータ(位置とかスケールとか)も初期化しておくといいかと思います。


 で、炎が必要なくなったら End関数を、必要になったら Start関数を呼べば自然な形で
炎が消えたり(数十フレームかけて炎が収束する)、炎が出現したりします。

 但し、消えている途中で再度出現させようとするとやはり、同じ現象がおきるので、
炎を再出現させようとする段階で、パーティクルの数が0になっていなかったら Reset関数を呼んで
強制的に前の情報を消し、改めて位置などの情報を設定してから Start関数を呼べば
一応望み通り動くかと思います。


 まぁでもどっちの戦略をとるにしても、明示的に Startしないと出現しない方が
なにかと便利なはずですし、消すのにいちいちオブジェクトを破棄していたら一瞬で
消えてしまうことになるんで、ゲームで使うなら Start/End/Reset関数は
追加しておいた方がいいでしょうね。

kai

Re:Justyさんが作成した炎サンプルを利用して

#9

投稿記事 by kai » 15年前

>Justyさん
返信遅れてすみません。

>処理落ちはソートをコメントアウトしてもそうなりますか?
コメントアウトしたら処理落ちはしませんでした。
>あと、releaseビルドだとどうなりますか?
debugと同じでした。

>使わなくなったオブジェクトは破棄して、新規にオブジェクトを生成すれば
>初期化されます。
特に同じオブジェクトを使い回しはしなくてもよさそうなので
使わなくなったオブジェクトは破棄して
新規にオブジェクトを生成して初期化したいと思うのですが、
沢山オブジェクトがあって、どれのことか分からない&破棄する方法が分からないのですが
どうしたらいいのでしょうか?

Justy

Re:Justyさんが作成した炎サンプルを利用して

#10

投稿記事 by Justy » 15年前


> コメントアウトしたら処理落ちはしませんでした
> debugと同じでした

 この中の処理の中ではソートか描画が重いだろうと思っていたので、
ソートをコメントアウトして処理落ちがなくなったのはある意味予想通りですが、
Releaseビルドにしても Debugと同じと言うことは、ソートを入れると
Releaseでも処理落ちするということですかね。

 うーん、描画にも負荷がかかっているんでしょうか。



> 沢山オブジェクトがあって、どれのことか分からない&破棄する方法が分からないのですが

 C++は大丈夫ですか?

 C++のクラスを理解していないと難しい話になってしまうのですが、ボスで使うのなら
ボスのメンバに Effect::Fireクラスのポインタ pFireEffect(名前はお好みで決めて下さい)を
定義します。

 次にボスの初期化(或いは使い始める時)のところで、そのポインタに対し、
newを行い火のクラスをインスタンス化します。
[color=#d0d0ff" face="monospace]
boss.pFireEffect = new Effect::Fire;
[/color]

 これが生成になります。
 今のコードですと、コンストラクタでテクスチャを読み込んでいますので、
このあたりは事前に読み込んでおいて使い回すようにしておくのがいいかと思います。

 使う時は、
[color=#d0d0ff" face="monospace]
boss.pFireEffect->Update();
boss.pFireEffect->Draw();
[/color]

のように使います。

 次にボスの終了(或いは火が必要なくなった時)のところでそのポインタに対し
deleteを行います。
[color=#d0d0ff" face="monospace]
delete boss.pFireEffect;
boss.pFireEffect = NULL;
[/color]

 これが破棄になります。
 その際、bossオブジェクトはグローバル変数になっているので念のため
使わなくなった pFireEffectを 上のようにNULLで初期化しておくといいでしょう。

kai

Re:Justyさんが作成した炎サンプルを利用して

#11

投稿記事 by kai » 15年前

あの、
>ボスのメンバに Effect::Fireクラスのポインタ pFireEffect(名前はお好みで決めて下さい)を
>定義します。
というのは、どう定義すればいいのでしょうか?

Justy

Re:Justyさんが作成した炎サンプルを利用して

#12

投稿記事 by Justy » 15年前


> どう定義すればいいのでしょうか?

 あー、そこからですか。
 
 本来ならきちんと Effect::Fireクラスを h, cppファイルに分けて書くべきでしょうが、
この状況だともっと簡単な方がいいですよね。

 んーと、struct.hのボス構造体より上(「//ボスの情報」のコメントの上あたりがいいでしょう)に
[color=#d0d0ff" face="monospace]
namespace Effect { class Fire; }
[/color]

と書き、ボスの構造体のメンバ変数として
[color=#d0d0ff" face="monospace]
Effect::Fire * pFireEffect;
[/color]

というのを定義して下さい。

 後は必要に応じて生成・破棄(或いは開始・停止)をすればOKです。

kai

Re:Justyさんが作成した炎サンプルを利用して

#13

投稿記事 by kai » 15年前

すみません。
Justyさんのいうとおりに行ったのですが、
今度はエラーが出て、描画すらできなくなってしまいました。
自分が改造してるゲームではないですが、
ほとんど同じの50章にJustyさんが作成した炎プログラムをドッキングしたのをアップロードしたので、
どこを修正すれば描画出来るようになるか教えていただけないでしょうか?
描画は
graph.cpp内、
void graph_boss()内のMainLoop();で描画しようとしてます

http://www.dotup.org/uploda/www.dotup.o ... 6.zip.html
パス:1q2w3e

Justy

Re:Justyさんが作成した炎サンプルを利用して

#14

投稿記事 by Justy » 15年前


> 今度はエラーが出て、描画すらできなくなってしまいました

 生成する前に使おうとしているからです。
 つまり、boss.pFireEffectが NULLの状態で、Update等を行おうとしたのが原因です。

 一応動くよう直してみましたが、1回しかテストしていなので、
全く問題ないかどうかはわかりません。

kai

Re:Justyさんが作成した炎サンプルを利用して

#15

投稿記事 by kai » 15年前

Justyありがとうございます。
一応エラーもなく描画できましたが、
これだと、次の弾幕移行時に
particleが5に戻って、薄く描画されてしまうのですが、
これはどうしたらいいのでしょうか?

Justy

Re:Justyさんが作成した炎サンプルを利用して

#16

投稿記事 by Justy » 15年前

 なるほど。
 多分、stage_countがボス戦中カウントが進んでいないので、
消したはずの火がすぐに際復活(生成)してしまうのでしょう。

 なんか、生成と破棄の条件はもう少し見直す必要がありそうですね。
(というか、ボスの開始と終了の条件判定をしている boss_shot_mainとか enter_bossの中で
やった方がいいような)

kai

Re:Justyさんが作成した炎サンプルを利用して

#17

投稿記事 by kai » 15年前

Justyさん、ありがとうございます。一応
// メインループ
void effect_fire_main(){
	//開始時間なら
	if((stage_count==boss.appear_count[0] || stage_count==boss.appear_count[1]) && !boss.pFireEffect){
		boss.pFireEffect = new Effect::Fire;				//生成
	}
	//ボスがいる、かつサウンドノベル処理でないならば
	if(boss.flag==1 && boss.boss_wait_flag==0 && boss.pFireEffect){
		//火エフェクト移動
		boss.pFireEffect->SetPosition(vector2(static_cast<float>(boss.dx+FX), static_cast<float>(boss.dy+23+FY)));
		boss.pFireEffect->SetScale((float)boss.fire_cnt);	//火エフェクト拡縮
		boss.pFireEffect->Update();							//火エフェクト更新
		boss.pFireEffect->Draw();							//火エフェクト表示
		
		//if(boss.hp<2000){				//ボスが死にそうなら
		//	boss.pFireEffect->SetUseSmoke(1);				//煙エフェクト表示
		//}
	}

	#define BOSS_POS2_Y (-150)			//中ボスが逃げるY座標の位置
	//中ボス逃走中で指定の位置に移動、かつ中ボスの出すべき弾幕をだしきったら
	if(boss.state==3 && boss.y <= BOSS_POS2_Y+1 && boss.knd==boss.danmaku_num[0]){
		delete boss.pFireEffect;		//破棄
		boss.pFireEffect = NULL;
	}
	//弾幕中で体力が無くなる、または時間切れ、かつボスの出すべき弾幕をだしきったら【つまりボスが死亡したら】
	if(boss.state==2 && (boss.hp<=0 || boss.endtime<=0) && boss.knd==boss.danmaku_num[1]){
		delete boss.pFireEffect;		//破棄
		boss.pFireEffect = NULL;
	}
}
とすることで、なんとか初期化に成功しました。
これで炎は完璧に結合することができました。
Justyさんのおかげです。本当にありがとうございました><
スルーしてましたが、html?みたいなもので
修正箇所が簡単に分かる、あれも凄いですね。初めてみましたw

あとは、煙なんですが、どうしても処理落ちしてしまうのが現在の問題ですが
なんとか、これは自力で解決してみたいです。
最後に、炎の絵についてお聞きしたいのですが、
Justyさんのサンプルについてたfire64.ddsとfire64.png
これはどう違う画像なんでしょうか?
ddsなんて拡張子は初めてみたのですが、
使うとしたら、どちらのほうが良いのでしょうか?

Justy

Re:Justyさんが作成した炎サンプルを利用して

#18

投稿記事 by Justy » 15年前


> これで炎は完璧に結合することができました

 元々は出ればいいだけのサンプルでしたので、あまりゲーム内にそのままの形で
組み込まれることは想定していませんでした。

 そういう面で前のスレでも書きましたが、実行効率とか最適化とかは
されていないので、そのあたりを追々自分好みに直してみて下さい。



> 修正箇所が簡単に分かる

 そういうツールがあります。

WinMerge 日本語版
http://www.geocities.co.jp/SiliconValle ... creenshots

差分表示ソフト Rekisa
http://frozenlib.net/rekisa/



> なんとか、これは自力で解決してみたいです。

 わかりました。
 がんばって下さい。



> fire64.ddsとfire64.png
> これはどう違う画像なんでしょうか?

 LoadGraphで読み込んで表示させてみるとわかりますが、中身は同じです。
(厳密には DDSの方は非可逆圧縮がかかってるので、全く同じではないです)

 DirectXでよく使われるフォーマットです。

DirectDraw Surface - Wikipedia
http://ja.wikipedia.org/wiki/DirectDraw_Surface



> 使うとしたら、どちらのほうが良いのでしょうか

 DXライブラリ上では大差ないのでお好みで、ってところなのですが、
まぁ扱い易い PNGでいいのでないでしょうか。

kai

Re:Justyさんが作成した炎サンプルを利用して

#19

投稿記事 by kai » 15年前

なるほど。わかりました。
色々と教えていただきありがとうございました!

SIT

画像の平均化

#20

投稿記事 by SIT » 15年前

画像の10×10のピクセルの平均化をしたいのですが、どのようにプログラミングしたらよろしいでしょうか??

考えているのは、1ピクセル毎に(r+g+b)/3=グレーをして

そのあとに10×10の中のグレーを全て足して100で割ろうかという方法を考えています。


// データをコピーする
    // x, y はコピー先の座標
        for ( y = 0; y < bi1.biHeight; y++ ) {
            for ( x = 0; x < bi1.biWidth; x++ ) {
                data1[ y ][ x ].rgbtBlue =
                    (int)data[ y * 10+1 ][ x * 10 ].rgbtBlue / 10;  
                data1[ y ][ x ].rgbtGreen =
                    (int)data[ y * 10+1 ][ x * 10 ].rgbtGreen / 10;
                data1[ y ][ x ].rgbtRed =
                    (int)data[ y * 10+1 ][ x * 10 ].rgbtRed /10;
                
        }
    }
    // 出力ファイルを開く
        
        printf( "%s というファイルを作成します\n", filename1 );
        fp1 = fopen( filename1, "wb" );
        if ( !fp1 ) {
            printf("ファイルの作成に失敗しました\n");
            return 0;
        }

    // ファイルにデータを書き込む
        fwrite( &bf, sizeof(BITMAPFILEHEADER), 1, fp1 );
        fwrite( &bi1, sizeof(BITMAPINFOHEADER), 1, fp1 );
        fwrite( buf1, BufferSize1, 1, fp1 );
    // ファイルを閉じる
        fclose(fp1);
        return 0;
        }

kazuoni

Re:画像の平均化

#21

投稿記事 by kazuoni » 15年前

まだ駆け出しなので、意に合わない回答になるかもしれませんが・・・

> 画像の10×10のピクセルの平均化をしたいのですが、

平均化フィルタの作成っということでしょうか?
それならば、線形フィルタの計算をすればよいのではないでしょうか。
(10*10となると、かなりボヤボヤになってしまいそうな気がしますが。。)

> 1ピクセル毎に(r+g+b)/3=グレーをして
> そのあとに10×10の中のグレーを全て足して100で割ろうかという方法

これを求めるのであれば、おっしゃる通りにすればよいかと思いますが・・・
これってピクセルの平均化っていうのかなってのが正直な意見です。。
(重ねて言いますが、まだ駆け出しですので、的外れでしたらごめんなさい。。)

閉鎖

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