トップページ > 記事閲覧
インデックス画像から分割画像への仕方について
名前:まっつぁん 日時: 2019/07/27 10:47

いつもDXライブラリを使用させていただいております。 題名がうまく簡潔に書けなかったのですが、今回やりたいことは格闘ゲームのカラー変更のようなものです。 キャラクターはアニメーションしつつ、事前に決めているパレットを適用し、カラーを変更したいという旨です。 実は物自体はできているのですが、パレット変更時の処理が悪いため処理全体が一時的に止まってしまうので 何とか処理方法を変更したいというのが今回の状態です。 現在できていることはLoadSoftImageで読み込んだソフトウェアイメージにパレットを適用し、分割画像にして描画しています。 そしてパレットを変更した際に新たに分割画像を作成&削除をしています。 (CreateDivGraphFromSoftImageで作成した分割画像をDeleteGraph×作成枚数分削除しています。) パレット変更時に作成&削除をしているためこのときに一時的に処理が止まってしまうのですが(当たり前)、 SoftImageをDivGraphに転送する方法など何か良い案はございませんでしょうか? ご教授のほどよろしくお願いいたします。
メンテ

Page: 1 |

Re: インデックス画像から分割画像への仕方について ( No.1 )
名前:管理人 日時:2019/07/29 22:36

> パレット変更時に作成&削除をしているためこのときに一時的に処理が止まってしまうのですが(当たり前)、 > SoftImageをDivGraphに転送する方法など何か良い案はございませんでしょうか? 分割画像の元画像の大きさは縦横何pixelでしょうか? あと、『一時的』とはどのくらいの時間でしょうか?( 1秒くらいなのか、0.1秒くらいなのか、など ) ただ、画像からグラフィックハンドルを作成する処理は重い処理なので、どれほど頑張っても 一瞬も止まらないようにすることは難しいので、一番簡単な方法はあらかじめすべての カラーパターンのグラフィックハンドルを作成しておくことです ( ユーザーによるカスタマイズが可能で、バリエーションが無限にある場合は無理ですが… )
メンテ
Re: インデックス画像から分割画像への仕方について ( No.2 )
名前:まっつぁん 日時:2019/07/31 01:55

ご返信ありがとうございます。 こちら返答させていただきます。 >分割画像の元画像の大きさは縦横何pixelでしょうか? 分割画像は2つ読み込んでおり、 一つは2600px×1951、二つ目は2600px×2601pxです。 一つ目の内訳:650px×650pxが横4、縦3+縦1pxのドット情報 二つ目の内訳:650px×650pxが横4、縦4+縦1pxのドット情報 1pxドットは画像内パレットの統一のため追加しています。 >あと、『一時的』とはどのくらいの時間でしょうか?( 1秒くらいなのか、0.1秒くらいなのか、など ) 1カラーを変更するだけの場合は大体0.1〜0.2秒くらい(この場合は画面全体は影響していないように見える) それを連続で1カラー→2カラー→3カラーのようにとにかく早く連続でカラーを変更すると、画面全体のアニメーションが影響を受けてカクカクするようになります。 連続でカラー変更を行っても処理落ちをしないようにしたいと思っています。 >一番簡単な方法はあらかじめすべてのカラーパターンのグラフィックハンドルを作成しておくこと 一度、全パレット画像に対する分割グラフィックハンドルを読み込んでみたことがあるのですが、 そのときは想像以上にサクサクとカラー変更をすることができ、とても快適でした。 しかし、想定している数が100カラー分であり、上記の分割画像2種類×100の画像を作成したので 3.5GBほどメモリを食ってしまい、これはちょっと…と思いました。 >ユーザーによるカスタマイズが可能で、バリエーションが無限 カスタマイズがどのようなことをおっしゃっているのかわからないですが、 1つの画像に対するパレット数は現在60です。 それを100カラー、分割画像も大体上記の2600px×2600px前後です。
メンテ
Re: インデックス画像から分割画像への仕方について ( No.3 )
名前:管理人 日時:2019/08/01 00:21

> 一つは2600px×1951、二つ目は2600px×2601pxです。 > 1カラーを変更するだけの場合は大体0.1〜0.2秒くらい(この場合は画面全体は影響していないように見える) 面積が2600x1951pxですと、0.1〜0.2秒くらい時間が掛かるのは妥当かもしれません… 多少処理を高速化できるかもしれない方法としては、カラー変更の際に DeleteGraph でグラフィックハンドルの削除 ↓ CreateDivGraphFromSoftImage でグラフィックハンドルの作成 とされていると思いますが、こちらを ReCreateDivGraphFromSoftImage で既存のグラフィックハンドルの画像を変更 とすることです( ReCreateDivGraphFromSoftImage は ReloadDivGraph の SoftImage版です ) // ソフトウエアで扱うイメージから既存の分割グラフィックハンドルにデータを転送する int ReCreateDivGraphFromSoftImage( int SIHandle, int AllNum, int XNum, int YNum, int SizeX, int SizeY, const int *HandleArray ) ; …と、申し上げようとしたら、ReCreateDivGraphFromSoftImage がありませんでした… なので、ReCreateDivGraphFromSoftImage を追加したバージョンをアップしましたので、 よろしければこちらのバージョンで ReCreateDivGraphFromSoftImage を試してみてください m(_ _;m https://dxlib.xsrv.jp/temp/DxLibVCTest.zip // Windows版 VisualC++ 用 https://dxlib.xsrv.jp/temp/DxLibBCCTest.zip // Windows版 BorlandC++ 用 https://dxlib.xsrv.jp/temp/DxLibBCC2Test.zip // Windows版 C++ Builder 10.2 用 https://dxlib.xsrv.jp/temp/DxLibGCC_MinGWTest.zip // Windows版 MinGW 用 https://dxlib.xsrv.jp/temp/DxLibDotNet.zip // Windows版 .NET用 https://dxlib.xsrv.jp/temp/DxLibAndroidTest_ARM.zip // Android版 ARM用 https://dxlib.xsrv.jp/temp/DxLibAndroidTest_ARM64.zip // Android版 ARM64用 https://dxlib.xsrv.jp/temp/DxLibAndroidTest_x86.zip // Android版 x86用 https://dxlib.xsrv.jp/temp/DxLibAndroidTest_x64.zip // Android版 x64用 https://dxlib.xsrv.jp/temp/DxLibiOSTest.zip // iOS版 https://dxlib.xsrv.jp/temp/DxLibMakeTest.zip // ソース (中身を既存のライブラリのファイルに上書きして『リビルド』をして下さい) > 連続でカラー変更を行っても処理落ちをしないようにしたいと思っています。 DxLib_Init を実行する前に SetScreenMemToVramFlag( FALSE ); を実行することで 使用することができるソフトウェアレンダリングモードではパレット画像を パレット画像のまま保持するため、グラフィックハンドルのパレットの色を 変更するための SetGraphPalette という関数を使用することができます // グラフィックハンドルのパレットを変更する( ソフトウエアレンダリングモードで、且つパレット画像の場合のみ使用可能 ) int SetGraphPalette( int GrHandle, int ColorIndex, unsigned int Color ) ; グラフィックハンドルのパレットを変更する場合は、画像のピクセル情報はそのままで パレット情報のみ変更するので処理は一瞬で終わる為、処理落ち無くパレットの色を 変更して描画することができます この関数を使用してサンプル実行用フォルダにある test2.bmp の棒人間の色を1秒毎に変更するプログラムは以下のようになります ( 分割画像の場合は、分割されたグラフィックハンドルのどれか一つに対して色を変えると全てのグラフィックハンドルに反映されます ) #include "DxLib.h" int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { int GrHandle[ 10 ] ; int i ; int Counter ; int ColorIndex ; // ウィンドウモードで起動 ChangeWindowMode( TRUE ) ; // ソフトウェアレンダリングモードで起動 SetScreenMemToVramFlag( FALSE ) ; // DXライブラリを初期化 if( DxLib_Init() < 0 ) return -1 ; // BMP画像のメモリへの分割読み込み LoadDivGraph( "test2.bmp" , 10 , 4 , 3 , 48 , 56 , GrHandle ) ; // 描画先を裏画面に変更 SetDrawScreen( DX_SCREEN_BACK ) ; // 色番号を初期化 ColorIndex = 0 ; // カウンターを初期化 Counter = 0 ; // メインループ while( ProcessMessage() == 0 ) { // 画面を初期化 ClearDrawScreen() ; // カウンターをインクリメント Counter ++ ; // 60フレーム経過したら色を変える if( Counter == 60 ) { // カウンターを初期化 Counter = 0 ; // 色番号を変更 ColorIndex = ( ColorIndex + 1 ) % 6 ; // 色番号に沿ってパレット1番の色を設定 switch( ColorIndex ) { case 0 : SetGraphPalette( GrHandle[ 0 ], 1, GetColor( 0,255,0 ) ) ; break ; case 1 : SetGraphPalette( GrHandle[ 0 ], 1, GetColor( 0,0,255 ) ) ; break ; case 2 : SetGraphPalette( GrHandle[ 0 ], 1, GetColor( 255,0,0 ) ) ; break ; case 3 : SetGraphPalette( GrHandle[ 0 ], 1, GetColor( 255,255,0 ) ) ; break ; case 4 : SetGraphPalette( GrHandle[ 0 ], 1, GetColor( 0,255,255 ) ) ; break ; case 5 : SetGraphPalette( GrHandle[ 0 ], 1, GetColor( 255,0,255 ) ) ; break ; } } // 分割画像を描画 for( i = 0 ; i < 10 ; i ++ ) { DrawGraph( 48 * i, 0, GrHandle[ i ], TRUE ) ; } // 裏画面の内容を表画面に反映 ScreenFlip() ; } // DXライブラリの後始末 DxLib_End() ; // ソフトウェアの終了 return 0 ; } ただ、ソフトウェアレンダリングモードはGPUを一切使用せずに描画処理を行うため、描画処理の パフォーマンスが著しく低下しますので、贅沢な描画処理を行いたい場合はこの選択肢は使えません… 前述までの二つの方法以外には、SetASyncLoadFlag( TRUE ); を使用したバックグラウンド処理を使用する方法があります SetASyncLoadFlag( TRUE ) ; を実行した状態で CreateDivGraphFromSoftImage や ReCreateDivGraphFromSoftImage を実行すると、グラフィックハンドルの作成や再読み込みが バックグラウンドで行われるので、処理落ちしないようにできるかもしれません ただ、バックグラウンドで読み込み処理を開始すると、CheckHandleASyncLoad の戻り値が FALSE に なるまでグラフィックハンドルは使用できないので、グラフィックハンドルのセットは2つ用意する必要があります 〜〜〜〜〜 準備処理 int UseIndex = 0 ; int GrHandle[ 2 ][ 12 ]; int IsChangeColor = 0 ; int TargetColor = 0 ; // ←変更先の色番号 // 準備(最初の読み込み) CreateDivGraphFromSoftImage( SoftImage, 12, 4, 3, 650, 650, GrHandle[ 0 ] ) ; CreateDivGraphFromSoftImage( SoftImage, 12, 4, 3, 650, 650, GrHandle[ 1 ] ) ; 〜〜〜〜〜 〜〜〜〜〜 メインループ中 GrHandle[ UseIndex ][ 0〜11 ] を使用して描画 〜〜〜〜〜 〜〜〜〜〜 カラー変更処理開始 〜〜〜〜〜〜〜〜〜〜〜 TargetColor に従った SoftImage のパレットの色変更処理 〜〜〜〜〜〜〜〜〜〜〜 // UseIndex とは逆の番号( 0 だったら 1, 1 だったら 0 )に再読み込み ReCreateDivGraphFromSoftImage( SoftImage, 12, 4, 3, 650, 650, GrHandle[ UseIndex == 0 ? 1 : 0 ] ) ; // 色の変更処理中かどうかを示すフラグを立てる IsChangeColor = 1 ; 〜〜〜〜〜 〜〜〜〜〜 カラー変更処理中のメインループに追加する処理 // 色の変更処理の終了待ち中だった場合のみ処理 if( IsChangeColor == 1 ) { // 全ての非同期読み込み処理が終わったら UseIndex を逆にする // ( ハンドル単位では CheckHandleASyncLoad ですが、他に非同期読み込みをしていなければ //  GetASyncLoadNum で手抜きをすることもできます ) if( GetASyncLoadNum() == 0 ) { UseIndex = UseIndex == 0 ? 1 : 0 ; // 色の変更処理中かどうかを示すフラグを倒す IsChangeColor = 0 ; } } 〜〜〜〜〜 描画は常に UseIndex が示す側のグラフィックハンドルセットを使用するようにして、切り替える 際は UseIndex が示していない方にバックグラウンドで読み込み、読み込みが終わったら UseIndex が 示す番号を変える、という感じです ただ、読み込み処理に 0.1〜0.2秒くらい掛かることから、処理落ちが発生しなくはなるかもしれませんが、 カラーを変更する操作をしてから 0.1〜0.2秒経過しないとカラーが切り替わらない、という状態になります 加えて、バックグラウンドでの処理が終わる前に次のカラー変更を行ってしまった( 次のバックグラウンド 処理を始めようとしてしまった )場合は既に実行中のバックグラウンド処理が終わるまで待たされる( 通常の SetASyncLoad( TRUE ) ; を使用していない読み込みのように処理がブロックされる )ので、 それが発生しないようにするためには『GetASyncLoadNum が 0 になる前に次の色変更が発生した場合は、 GetASyncLoadNum が 0 になるまで次の ReCreateDivGraphFromSoftImage を待つ』という処理を行う必要があります 〜〜〜〜〜 準備処理 int UseIndex = 0; int GrHandle[ 2 ][ 12 ]; int IsChangeColor = 0 ; int TargetColor = 0 ; // ←変更先の色番号 int ColorChangeRequest = 0 ; // 準備(最初の読み込み) CreateDivGraphFromSoftImage( SoftImage, 12, 4, 3, 650, 650, GrHandle[ 0 ] ) ; CreateDivGraphFromSoftImage( SoftImage, 12, 4, 3, 650, 650, GrHandle[ 1 ] ) ; 〜〜〜〜〜 〜〜〜〜〜 メインループ中 GrHandle[ UseIndex ][ 0〜11 ] を使用して描画 〜〜〜〜〜 〜〜〜〜〜 カラー変更処理開始 // まだバックグラウンドで処理中だったら予約だけしておく if( GetASyncLoadNum() > 0 ) { ColorChangeRequest = 1 ; } else { 〜〜〜〜〜〜〜〜〜〜〜 TargetColor に従った SoftImage のパレットの色変更処理 〜〜〜〜〜〜〜〜〜〜〜 // UseIndex とは逆の番号( 0 だったら 1, 1 だったら 0 )に再読み込み ReCreateDivGraphFromSoftImage( SoftImage, 12, 4, 3, 650, 650, GrHandle[ UseIndex == 0 ? 1 : 0 ] ) ; // 色の変更処理中かどうかを示すフラグを立てる IsChangeColor = 1 ; } 〜〜〜〜〜 〜〜〜〜〜 カラー変更処理中のメインループに追加する処理 // 色の変更処理の終了待ち中だった場合のみ処理 if( IsChangeColor == 1 ) { // 全ての非同期読み込み処理が終わったら UseIndex を逆にする if( GetASyncLoadNum() == 0 ) { UseIndex = UseIndex == 0 ? 1 : 0 ; // 色の変更処理中かどうかを示すフラグを倒す IsChangeColor = 0 ; // 次の色変更の予約があった場合は、次の色に変更する処理を開始する if( ColorChangeRequest == 1 ) { // 色の変更の予約を解除 ColorChangeRequest = 0 ; 〜〜〜〜〜〜〜〜〜〜〜 TargetColor に従った SoftImage のパレットの色変更処理 〜〜〜〜〜〜〜〜〜〜〜 // UseIndex とは逆の番号( 0 だったら 1, 1 だったら 0 )に再読み込み ReCreateDivGraphFromSoftImage( SoftImage, 12, 4, 3, 650, 650, GrHandle[ UseIndex == 0 ? 1 : 0 ] ) ; // 色の変更処理中かどうかを示すフラグを立てる IsChangeColor = 1 ; } } } 〜〜〜〜〜 と、これ以外の二つの方法に比べてかなり処理が複雑です… > しかし、想定している数が100カラー分であり、上記の分割画像2種類×100の画像を作成したので > 3.5GBほどメモリを食ってしまい、これはちょっと…と思いました。 確かに…3.5GBは厳しいですね…
メンテ

Page: 1 |

題名
名前
コメント
パスワード (記事メンテ時に使用)

   クッキー保存