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

提供: MonoBook
ナビゲーションに移動 検索に移動
imported>Administrator
imported>Administrator
 
1行目: 1行目:
[[MonoGame]]で作っている[[ゲーム]]に起動時データ更新を実装し、[[プログラム]]以外の画像や音楽などだけであれば自動更新するようにしたいわけだ。[[スマホ]]の[[ゲーム]]によくあるアレである。むしろ[[プログラム]]の細かい部分も[[NLua]]に投げるようにしてしまいたい。
+
[[MonoGame]]で作っている[[ゲーム]]に起動時データ更新を実装し、[[プログラム]]以外の画像や音楽などだけであれば自動更新するようにしたいわけだ。[[スマホ]]の[[ゲーム]]によくあるアレである。むしろ[[プログラム]]の細かい部分も[[NeoLua]]に投げるようにしてしまいたい。
  
そうなると外部から各種[[データ]]を読み込む必要が出てくる。
+
そうなると外部から各種[[データ]]を読み込む必要が出てくる。しかし[[MonoGame]]で扱う各種[[データ]]の基本は[[プログラム]]に組み込まれた「Content」である。
しかし[[MonoGame]]で扱う各種[[データ]]の基本は[[プログラム]]に組み込まれた「Content」である。
 
  
 
== Xamarin.Android ==
 
== Xamarin.Android ==
85行目: 84行目:
  
 
使い方は普通のContentManagerと大して変わらない。
 
使い方は普通のContentManagerと大して変わらない。
<source>
+
<source lang="csharp">
 
// Androidであれば「/data/data/アプリID/files」あたりが返ってくるはず。
 
// Androidであれば「/data/data/アプリID/files」あたりが返ってくるはず。
var path = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
+
var rootdir = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
var cm = new ExternalContentManager(this.Content.ServiceProvider, path);
+
var cm = new ExternalContentManager(this.Content.ServiceProvider, rootdir);
 
var font = cm.Load<SpriteFont>("IPA-Gothic");
 
var font = cm.Load<SpriteFont>("IPA-Gothic");
 
</source>
 
</source>
97行目: 96行目:
 
* [[MonoGameのカメラを作る]]
 
* [[MonoGameのカメラを作る]]
  
== 参考文献 ==
 
{{reflist}}
 
 
{{stub}}
 
 
[[category:MonoGame]]
 
[[category:MonoGame]]
 
[[category:Xamarin.Android]]
 
[[category:Xamarin.Android]]

2018年10月26日 (金) 05:23時点における最新版

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

そうなると外部から各種データを読み込む必要が出てくる。しかし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 rootdir = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
var cm = new ExternalContentManager(this.Content.ServiceProvider, rootdir);
var font = cm.Load<SpriteFont>("IPA-Gothic");

関連項目[編集 | ソースを編集]