「MonoGameで外部のXNBファイルを読み込む」の版間の差分

提供: MonoBook
ナビゲーションに移動 検索に移動
1行目: 1行目:
[[MonoGame]]で作っている[[ゲーム]]に起動時データ更新を実装し、[[プログラム]]以外の画像や音楽などだけであれば自動更新するようにしたいわけだ。
+
[[MonoGame]]で作っている[[ゲーム]]に起動時データ更新を実装し、[[プログラム]]以外の画像や音楽などだけであれば自動更新するようにしたいわけだ。[[スマホ]]の[[ゲーム]]によくあるアレである。むしろ[[プログラム]]の細かい部分も[[NLua]]に投げるようにしてしまいたい。
むしろ[[プログラム]]の細かい部分も[[NLua]]に投げるようにしてしまいたい。
 
  
 
そうなると外部から各種[[データ]]を読み込む必要が出てくる。
 
そうなると外部から各種[[データ]]を読み込む必要が出てくる。
しかしMonoGameで扱う各種データの基本はプログラムに組み込まれた「Content」である。
+
しかし[[MonoGame]]で扱う各種[[データ]]の基本は[[プログラム]]に組み込まれた「Content」である。
  
==Xamarin.Android==
+
== Xamarin.Android ==
[[MonoGame]]のContentManagerクラスの[[ソースコード]]をざっと見た感じ、[[Xamarin.Android]]ではアセット以外の[[ファイル]]へはアクセスできないようだ。
+
[[MonoGame]][[ソースコード]]をざっと見た感じ、[[Xamarin.Android]]ではContentManagerクラスでアセット以外の[[ファイル]]へはアクセスできないようだ。ContentManagerクラスの[[ソースコード]]をみると幸いにもvirtualやらがチラホラ見受けられ継承してoverrideする前提の構造になっている。なので細かいことは考えずにoverrideしてしまえと考えた。
ContentManagerクラスの[[ソースコード]]をみると幸いにもvirtualやらがチラホラ見受けられ継承してoverrideする前提の構造になっている。
 
なので細かいことは考えずにoverrideしてしまえ。
 
  
 
ついでに各種パラメータを保存した[[csv]]や[[json]]などのxnb以外の[[ファイル]]も同様の手順で読み込めるように、xnbパーサを経由しない裏口も用意すると捗った。
 
ついでに各種パラメータを保存した[[csv]]や[[json]]などのxnb以外の[[ファイル]]も同様の手順で読み込めるように、xnbパーサを経由しない裏口も用意すると捗った。
個人的な主な用途としては、[[OpenGL ES]]の[[バーテックスシェーダー]]は書き込みだけで読み出せないため、[[モデル]]とは別に頂点データのcsvファイルを読み込み、それを当たり判定に用いている。
 
  
 
<source lang="csharp">
 
<source lang="csharp">
96行目: 92行目:
 
</source>
 
</source>
  
==関連項目==
+
== 関連項目 ==
*[[MonoGame]]
+
* [[:Category:MonoGame|MonoGameカテゴリ]]
  
 +
== 参考文献 ==
 +
{{reflist}}
 +
 +
{{stub}}
 
[[category:MonoGame]]
 
[[category:MonoGame]]
 
[[category:Xamarin.Android]]
 
[[category:Xamarin.Android]]

2017年3月9日 (木) 10:33時点における版

MonoGameで作っているゲームに起動時データ更新を実装し、プログラム以外の画像や音楽などだけであれば自動更新するようにしたいわけだ。スマホゲームによくあるアレである。むしろプログラムの細かい部分もNLuaに投げるようにしてしまいたい。

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

Xamarin.Android

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

ついでに各種パラメータを保存したcsvjsonなどのxnb以外のファイルも同様の手順で読み込めるように、xnbパーサを経由しない裏口も用意すると捗った。

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);
            }

            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;
    }
}

使い方は普通のContentManagerと大して変わらない。

// 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");

関連項目

参考文献