差分

ナビゲーションに移動 検索に移動

MonoGameで外部のXNBファイルを読み込む

4,224 バイト追加, 2016年1月14日 (木) 05:45
ページの作成:「MonoGameで作っているゲームに起動時データ更新を実装し、プログラム以外の画像や音楽などだけであれば自動更新する...」
[[MonoGame]]で作っている[[ゲーム]]に起動時データ更新を実装し、[[プログラム]]以外の画像や音楽などだけであれば自動更新するようにしたいわけだ。
むしろ[[プログラム]]の細かい部分も[[NLua]]に投げるようにしてしまいたい。

そうなると外部から各種[[データ]]を読み込む必要が出てくる。
しかしMonoGameで扱う各種データの基本はプログラムに組み込まれた「Content」である。

==Xamarin.Android==
[[MonoGame]]のContentManagerクラスの[[ソースコード]]をざっと見た感じ、[[Xamarin.Android]]ではアセット以外の[[ファイル]]へはアクセスできないようだ。
ContentManagerクラスの[[ソースコード]]をみると幸いにもvirtualやらがチラホラ見受けられ継承してoverrideする前提の構造になっている。
なので細かいことは考えずにoverrideしてしまえ。

ついでに各種パラメータを保存した[[csv]]や[[json]]などのxnb以外の[[ファイル]]も同様の手順で読み込めるように、xnbパーサを経由しない裏口も用意すると捗った。
個人的な主な用途としては、[[OpenGL ES]]の[[バーテックスシェーダー]]は書き込みだけで読み出せないため、[[モデル]]とは別に頂点データのcsvファイルを読み込み、それを当たり判定に用いている。

<source lang="csharp">
using System;
using System.IO;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;

public class ExternalContentManager : Microsoft.Xna.Framework.Content.ContentManager
{
public ExternalContentManager(IServiceProvider serviceProvider, string rootDirectory)
: base(serviceProvider, rootDirectory)
{
}

public ExternalContentManager(IServiceProvider serviceProvider)
: base(serviceProvider)
{
}

protected override Stream OpenStream(string assetName)
{
string assetPath;
if (Path.GetExtension(assetName) != "xnb")
{
assetPath = assetName + ".xnb";
}
else
{
assetPath = assetName;
}
return OpenRead(assetPath);
}

public Stream OpenRead(string fileName)
{
Stream stream = null;
string path;

try
{
if (Path.IsPathRooted(fileName))
{
path = fileName;
}
else
{
path = Path.Combine(RootDirectory, fileName);
}

// This is primarily for editor support.
// Setting the RootDirectory to an absolute path is useful in editor
// situations, but TitleContainer can ONLY be passed relative paths.
stream = File.OpenRead(path);

// Read the asset into memory in one go. This results in a ~50% reduction
// in load times on Android due to slow Android asset streams.
var memStream = new MemoryStream();
stream.CopyTo(memStream);
memStream.Seek(0, SeekOrigin.Begin);
stream.Close();
stream = memStream;
}
catch (FileNotFoundException fileNotFound)
{
throw new ContentLoadException("The content file was not found.", fileNotFound);
}
catch (DirectoryNotFoundException directoryNotFound)
{
throw new ContentLoadException("The directory was not found.", directoryNotFound);
}
catch (Exception exception)
{
throw new ContentLoadException("Opening stream error.", exception);
}
return stream;
}
}
</source>

使い方は普通のContentManagerと大して変わらない。
<source>
// Androidであれば「/data/data/アプリID/files」あたりが返ってくるはず。
var path = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
var cm = new ExternalContentManager(this.Content.ServiceProvider, path);
var font = cm.Load<SpriteFont>("IPA-Gothic");
</source>

==関連項目==
*[[MonoGame]]

[[category:MonoGame]]
[[category:Xamarin.Android]]
匿名利用者

案内メニュー