ページ 11

C#とDXLibでLoadDivGraph関数を使用して分割読み込みできない

Posted: 2013年5月12日(日) 13:39
by ziko
C#とDXライブラリを使用して,ゲームを作成しているのですが,LoadDivGraphで画像を正しく分割読み込み出来ず困っています.

龍神録のプログラミングの館にて公開されている自機画像0.pngを描画する処理(http://dixq.net/rp/4.html)をC#で行おうと,LoadDivGraphを使用して自機画像0.pngを分割した結果,配列の0番目には正しく画像が格納されているのに対して,1番目~11番目には画像が格納されておらず,正しくアニメーションできませんでした.

確認のため,次のようなプログラムを作成して,自機画像のアニメーションをしてみた結果,やはり,配列GrHandleの0番目は正しく描画されており,1番目から11番目には画像が描画されていませんでした.

同じような問題を抱えている人がいたのですが,自分の場合,0番目には正しく画像の情報が格納されているのに次以降の配列に情報が格納されておらず,どうしてこのような現象になったのかわからなかったので質問させていただきました.

何かご存じでしたら,教えていただきたいです.
------------------------------------------------------------------------------------------------------------------------------
using DxLibDLL;
using System;
class Ryu
{
[STAThread]
static void Main()
{

int[] GrHandle=new int [12];
int GNum = 0;
int loopcnt = 0;

// ウインドウモードで起動
DX.ChangeWindowMode(DX.TRUE);

// 初期化
if (DX.DxLib_Init() == -1) return;

// 画像の読み込み
DX.LoadDivGraph("../dat/img/char/0.png", 12, 4, 3, 73, 73, out GrHandle[0]);

// 描画対象を裏画面に
DX.SetDrawScreen(DX.DX_SCREEN_BACK);

// 閉じられるか、何かキーが押されるまでループ
while (DX.ProcessMessage() == 0 && DX.CheckHitKeyAll() == 0 )
{
loopcnt++;

if (GNum < 11 & loopcnt % 40 == 39)
{
GNum++; //画像ナンバーを変更
}

// 画面の初期化
DX.ClearDrawScreen();

// 画像の描画
DX.DrawGraph(200, 200, GrHandle[GNum], DX.TRUE);

//文字の表示
DX.DrawString(100, 80, "loopcnt = " + loopcnt, DX.GetColor(255, 255, 255));
DX.DrawString(100, 100, "GNum = " + GNum, DX.GetColor(255, 255, 255));

// 裏画面の内容を表画面に反映
DX.ScreenFlip();
}

// 後始末
DX.DxLib_End();
}
}
------------------------------------------------------------------------------------------------------------------------------

使用言語:C#,DXライブラリ
開発環境:Visual Stdio 2008 express edition

Re: C#とDXLibでLoadDivGraph関数を使用して分割読み込みできない

Posted: 2013年5月13日(月) 09:51
by バグ
今、環境が手元にないので、ざっと見て気になった個所を・・・

コード:

if (GNum < 11 & loopcnt % 40 == 39)
{
	GNum++; //画像ナンバーを変更
}
ここの判定文あってますか?

コード:

if (GNum < 11 && loopcnt % 40 == 39)
{
	GNum++; //画像ナンバーを変更
}

Re: C#とDXLibでLoadDivGraph関数を使用して分割読み込みできない

Posted: 2013年5月13日(月) 10:56
by YuO
ざっと見out intなあたりがおかしいのでDxLibのダウンロードページ見て納得。
機械変換がおかしい。
int *がout intやref intに変わるのは,C++のint &の代わりに使っている場合のみで,配列を扱う場合はそのまま配列にする,
マーシャリングする場合はMarshalAs属性をつける形にする必要があります。
# 単体/配列両方ならば,オーバーロードで解決する。

というわけで,DxLibDotNet.dllを自分で(コードを修正した上で)ビルドする必要があります。

今回に関する場所について書くなら,DxDLL.csの7190行目からの,

コード:

        [DllImport("DxLib.dll", EntryPoint="dx_LoadDivGraph")]
        extern static int  dx_LoadDivGraph_x86( string  FileName, int  AllNum, int  XNum, int  YNum, int  XSize, int  YSize, out int  HandleBuf, int  NotUse3DFlag);
        [DllImport("DxLib_x64.dll", EntryPoint="dx_LoadDivGraph")]
        extern static int  dx_LoadDivGraph_x64( string  FileName, int  AllNum, int  XNum, int  YNum, int  XSize, int  YSize, out int  HandleBuf, int  NotUse3DFlag);
        public static int  LoadDivGraph( string  FileName, int  AllNum, int  XNum, int  YNum, int  XSize, int  YSize, out int  HandleBuf)
        {
            if( System.IntPtr.Size == 4 )
            {
                return dx_LoadDivGraph_x86( FileName , AllNum , XNum , YNum , XSize , YSize , out HandleBuf , FALSE );
            }
            else
            {
                return dx_LoadDivGraph_x64( FileName , AllNum , XNum , YNum , XSize , YSize , out HandleBuf , FALSE );
            }
        }
        public static int  LoadDivGraph( string  FileName, int  AllNum, int  XNum, int  YNum, int  XSize, int  YSize, out int  HandleBuf, int  NotUse3DFlag)
        {
            if( System.IntPtr.Size == 4 )
            {
                return dx_LoadDivGraph_x86( FileName , AllNum , XNum , YNum , XSize , YSize , out HandleBuf , NotUse3DFlag );
            }
            else
            {
                return dx_LoadDivGraph_x64( FileName , AllNum , XNum , YNum , XSize , YSize , out HandleBuf , NotUse3DFlag );
            }
        }
は,私がやるならせめて

コード:

        [DllImport("DxLib.dll", EntryPoint="dx_LoadDivGraph", CharSet=CharSet.Ansi)]
        extern static int  dx_LoadDivGraph_x86( string  FileName, int  AllNum, int  XNum, int  YNum, int  XSize, int  YSize, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1), Out] int[]  HandleBuf, [MarshalAs(UnmanagedType.Bool)] bool  NotUse3DFlag);
        [DllImport("DxLib_x64.dll", EntryPoint="dx_LoadDivGraph", CharSet=CharSet.Ansi)]
        extern static int  dx_LoadDivGraph_x64( string  FileName, int  AllNum, int  XNum, int  YNum, int  XSize, int  YSize, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1), Out] int[]  HandleBuf, [MarshalAs(UnmanagedType.Bool)] bool  NotUse3DFlag);
        public static int  LoadDivGraph( string  FileName, int  AllNum, int  XNum, int  YNum, int  XSize, int  YSize, int[]  HandleBuf)
        {
            return LoadDivGpaph(FileName, AllNum, XNum, YNum, XSize, YSize, HandleBuf, false);
        }
        public static int  LoadDivGraph( string  FileName, int  AllNum, int  XNum, int  YNum, int  XSize, int  YSize, int[]  HandleBuf, bool  NotUse3DFlag)
        {
            if( System.IntPtr.Size == 4 ) // .NET 4以降なら !Environment.Is64BitProcess を利用
            {
                return dx_LoadDivGraph_x86( FileName , AllNum , XNum , YNum , XSize , YSize , HandleBuf , NotUse3DFlag );
            }
            else
            {
                return dx_LoadDivGraph_x64( FileName , AllNum , XNum , YNum , XSize , YSize , HandleBuf , NotUse3DFlag );
            }
        }
とします。
DXクラス下にある大量の構造体とか,enum化されていないconst intとか,突っ込み所は満載ですが……。

Re: C#とDXLibでLoadDivGraph関数を使用して分割読み込みできない

Posted: 2013年5月19日(日) 14:27
by ziko
仕事の関係により,返信がおくれてしまって申し訳ございませんでした.

>バグさま
見落としていました.

コード:

if (GNum < 11 & loopcnt % 40 == 39)
{
    GNum++; //画像ナンバーを変更
}
 
ここの&は&&でした.
ただそのコードを直しても,問題は解決しませんでした.当たり前ですが….

>YuOさま

指定された個所のライブラリファイルを変更して,再ビルド行ったのですが,
次のようなエラーが発生しました.
エラー1:'DxLibDLL.DX.LoadDivGraph(string, int, int, int, int, int, int[])' に最も適しているオーバーロード メソッドには無効な引数がいくつか含まれています。
エラー2:引数 '7': 'out int' から 'int[]' に変換できません。
エラー3:名前 'LoadDivGpaph' は現在のコンテキスト内に存在しません。

エラー1とエラー2に関しては,関数に渡す引数をout GrHandle[0]からGrHandleに変更することで改善することができました.
改善前:DX.LoadDivGraph("../dat/img/char/0.png", 12, 4, 3, 73, 73, out GrHandle[0]);
改善後:DX.LoadDivGraph("../dat/img/char/0.png", 12, 4, 3, 73, 73, GrHandle);
しかしエラー3のエラーのみ,再ビルドを行っても解決できませんでした.

とよくよくソースコードを見ていたところ,LoadDivGraphのスペルが間違っていたようですね.
記載されていたコードの7行目:LoadDivGpaphは正しくはLoadDivGraphでした.

DxLibのライブラリファイルを変更した結果,サンプルコードで正しくアニメーションできていました.ありがとうございました.

後で解決したコードを記述しておきます.
C#で開発している人のためにも,管理人さんに報告しておいたほうがいいかもしれませんね…

Re: C#とDXLibでLoadDivGraph関数を使用して分割読み込みできない

Posted: 2013年5月19日(日) 14:40
by ziko
自分なりにまとめました
問題:C#とDXLibでLoadDivGraph関数を使用して分割読み込みできない.

現象:C#でDxLibのLoadDivGraph関数を使用すると,画像を正しく分割読み込み出来ない.具体的には,
LoadDivGraph関数を利用すると配列の0番目の画像しか読み込めない.

解決策:DxDLL.csファイルの7190行目に記述されているLoadDivGraphを次のように変更.プロジェクトを再ビルドする.

コード:

 
        [DllImport("DxLib.dll", EntryPoint="dx_LoadDivGraph", CharSet=CharSet.Ansi)]
        extern static int  dx_LoadDivGraph_x86( string  FileName, int  AllNum, int  XNum, int  YNum, int  XSize, int  YSize, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1), Out] int[]  HandleBuf, [MarshalAs(UnmanagedType.Bool)] bool  NotUse3DFlag);
        [DllImport("DxLib_x64.dll", EntryPoint="dx_LoadDivGraph", CharSet=CharSet.Ansi)]
        extern static int  dx_LoadDivGraph_x64( string  FileName, int  AllNum, int  XNum, int  YNum, int  XSize, int  YSize, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1), Out] int[]  HandleBuf, [MarshalAs(UnmanagedType.Bool)] bool  NotUse3DFlag);
        public static int  LoadDivGraph( string  FileName, int  AllNum, int  XNum, int  YNum, int  XSize, int  YSize, int[]  HandleBuf)
        {
            return LoadDivGpaph(FileName, AllNum, XNum, YNum, XSize, YSize, HandleBuf, false);
        }
        public static int  LoadDivGraph( string  FileName, int  AllNum, int  XNum, int  YNum, int  XSize, int  YSize, int[]  HandleBuf, bool  NotUse3DFlag)
        {
            if( System.IntPtr.Size == 4 ) 
            {
                return dx_LoadDivGraph_x86( FileName , AllNum , XNum , YNum , XSize , YSize , HandleBuf , NotUse3DFlag );
            }
            else
            {
                return dx_LoadDivGraph_x64( FileName , AllNum , XNum , YNum , XSize , YSize , HandleBuf , NotUse3DFlag );
            }
        }
以下正しく動いているかを判定するためのプログラム(C#)

コード:

 
using DxLibDLL;
using System;
class Ryu
{
[STAThread]
static void Main()
{

int[] GrHandle=new int [12];
int GNum = 0;
int loopcnt = 0;

// ウインドウモードで起動
DX.ChangeWindowMode(DX.TRUE);

// 初期化
if (DX.DxLib_Init() == -1) return;

// 画像の読み込み
DX.LoadDivGraph("../dat/img/char/0.png", 12, 4, 3, 73, 73, GrHandle);

// 描画対象を裏画面に
DX.SetDrawScreen(DX.DX_SCREEN_BACK);

// 閉じられるか、何かキーが押されるまでループ
while (DX.ProcessMessage() == 0 && DX.CheckHitKeyAll() == 0 )
{
loopcnt++;

if (GNum < 11 && loopcnt % 40 == 39)
{
GNum++; //画像ナンバーを変更
}

// 画面の初期化
DX.ClearDrawScreen();

// 画像の描画
DX.DrawGraph(200, 200, GrHandle[GNum], DX.TRUE);

//文字の表示
DX.DrawString(100, 80, "loopcnt = " + loopcnt, DX.GetColor(255, 255, 255));
DX.DrawString(100, 100, "GNum = " + GNum, DX.GetColor(255, 255, 255));

// 裏画面の内容を表画面に反映
DX.ScreenFlip();
}

// 後始末
DX.DxLib_End();
}
}