ページ「カテゴリ:MonoGame」と「MonoGameで外部のXNBファイルを読み込む」の間の差分

提供: MonoBook
(ページ間の差分)
ナビゲーションに移動 検索に移動
 
(ページの作成:「MonoGameで作っているゲームに起動時データ更新を実装し、プログラム以外の画像や音楽などだけであれば自動更新する...」)
 
1行目: 1行目:
'''MonoGame'''(読み:ものげーむ)とは、[[Mono]]プロジェクトが開発している[[XNA]]互換のゲーム開発用フレームワークである。
+
[[MonoGame]]で作っている[[ゲーム]]に起動時データ更新を実装し、[[プログラム]]以外の画像や音楽などだけであれば自動更新するようにしたいわけだ。
 +
むしろ[[プログラム]]の細かい部分も[[NLua]]に投げるようにしてしまいたい。
  
==概要==
+
そうなると外部から各種[[データ]]を読み込む必要が出てくる。
かつて「[[XNA]]」というゲーム開発用のフレームワークがあった。これは[[Windows]]と[[Xbox 360]]の[[ゲーム]]が簡単に作れるという代物であり、さらに開発したものは[[インディーズ]](=[[同人]])でも家庭用ゲーム機にゲームを出せるとあって大いに盛り上がった。
+
しかしMonoGameで扱う各種データの基本はプログラムに組み込まれた「Content」である。
  
しかし[[マイクロソフト]][[Xbox 360]]の終焉と[[Xbox One]]の誕生に際してXNAの廃止を決定した。いわゆる[[Unity]]などの[[マウス]]でポチポチ系の[[ゲームエンジン]]の普及により、従来型の[[プログラミング]]によるゲーム開発は急激に衰退していたためである。もう本屋に行っても[[DirectX]]の入門書すらない状況なので仕方がない。
+
==Xamarin.Android==
 +
[[MonoGame]]のContentManagerクラスの[[ソースコード]]をざっと見た感じ、[[Xamarin.Android]]ではアセット以外の[[ファイル]]へはアクセスできないようだ。
 +
ContentManagerクラスの[[ソースコード]]をみると幸いにもvirtualやらがチラホラ見受けられ継承してoverrideする前提の構造になっている。
 +
なので細かいことは考えずにoverrideしてしまえ。
  
ただプログラミングによるゲーム開発を好む人も少なからず存在した。そしてMonoGameが生まれた。本家[[XNA]][[Windows]][[Xbox 360]]が対象であったが、MonoGameでは[[Mac OS X]][[iOS]][[Android]]といった最新鋭の環境に対応している。
+
ついでに各種パラメータを保存した[[csv]][[json]]などのxnb以外の[[ファイル]]も同様の手順で読み込めるように、xnbパーサを経由しない裏口も用意すると捗った。
 +
個人的な主な用途としては、[[OpenGL ES]][[バーテックスシェーダー]]は書き込みだけで読み出せないため、[[モデル]]とは別に頂点データのcsvファイルを読み込み、それを当たり判定に用いている。
  
2017年3月、[[Microsoft]]が[[Xamarin]]を買収した絡みで、MonoGame 3.6から[[Xbox One]]と[[Windows 10]]を公式にサポートすることとなった([[UWP]]をサポートすることとなった)。
+
<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
[[iOS]]や[[Android]]はシミュレータや実機転送が遅すぎて一般的なアプリ開発でも[[デバッグ]]時にイライラ全開だが、MonoGameは[[Mac]]にも対応しており起動の速い[[Xamarin.Mac]]向けにスマホ風の解像度でサクッと開発し、最終的に[[iOS]]や[[Android]]向けに微調整という手法を用いることもできる。
+
{
 +
    public ExternalContentManager(IServiceProvider serviceProvider, string rootDirectory)
 +
        : base(serviceProvider, rootDirectory)
 +
    {
 +
    }
  
この場合はソリューションを以下のようなプロジェクト構成にして、各プラットフォームからCoreプロジェクトを呼ぶようにすると良い。
+
    public ExternalContentManager(IServiceProvider serviceProvider)
 +
        : base(serviceProvider)
 +
    {
 +
    }
  
*Core - MonoGame PCLプロジェクト(Gameクラスなどの実際のコード)
+
    protected override Stream OpenStream(string assetName)
*Mac - MonoGame MonoMacプロジェクト(エントリポイントとコンテンツだけ)
+
    {
*Android - MonoGame MonoMacプロジェクト(エントリポイントとコンテンツだけ)
+
        string assetPath;
 +
        if (Path.GetExtension(assetName) != "xnb")
 +
        {
 +
            assetPath = assetName + ".xnb";
 +
        }
 +
        else
 +
        {
 +
            assetPath = assetName;
 +
        }
 +
        return OpenRead(assetPath);
 +
    }
  
なお、[[Xamarin.Mac]]では実行速度が爆速であるため[[スマホ]]実機では[[フレームレート]]が出ない現象には注意が必要である。定期的にスマホ実機で動作検証することをオススメする。
+
    public Stream OpenRead(string fileName)
 +
    {
 +
        Stream stream = null;
 +
        string path;
  
==機種依存の吸収==
+
        try
その名の通り本来は[[ゲーム]]に使うものであるが、[[ゲーム]]以外の[[3D]]を扱う[[アプリ]]でも利用できなことはない。とくに機種依存の激しい[[Android]]、そのなかでも飛び抜けて機種依存の激しいパーツである[[GPU]]周りを整流する[[ミドルウェア]]としても非常に有望である。
+
        {
 +
            if (Path.IsPathRooted(fileName))
 +
            {
 +
                path = fileName;
 +
            }
 +
            else
 +
            {
 +
                path = Path.Combine(RootDirectory, fileName);
 +
            }
  
ただしMonoGameを使うとUI周りの開発が面倒になる。MonoGameにサクッとGUIを実装するライブラリは出ているが、どれもPC向けばかりで、現在の主流であるスマホ向けのUIフレームワークもほとんどない。
+
            // 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と大して変わらない。
MonoGame本体を公式サイトからダウンロードしてインストールする。
+
<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>
  
*http://www.monogame.net/downloads/
+
==関連項目==
 +
*[[MonoGame]]
  
開発環境が[[Mac]]や[[Linux]]の場合はMonoGame Pipeline Toolをダウンロードしてインストールする。
+
[[category:MonoGame]]
 
 
*http://teamcity.monogame.net/repository/download/MonoGame_PackageMacAndLinux/latest.lastSuccessful/Pipeline.MacOS.pkg?guest=1
 
 
 
3Dモデルをビルドするには別途[[Assimp]]が必要となる。以下のページを参照してインストールしよう。
 
 
 
*[[MacOS版のMonoGameのPipeline.appで3Dモデルをビルドできない]]
 
*
 
 
 
===Xamarin Studioの場合===
 
Xamarin Studio を使っている場合はMonoGame本体を入れた段階でプロジェクトテンプレートも追加されるので何もする必要はない。
 
新規ソリューション作成時(新規プロジェクト作成時)に「MonoGame」という項目が増えているはずである。
 
 
 
===Visual Studio for Macの場合===
 
2017年12月時点ではVisual Studio for Macの拡張機能の公式リポジトリのアルファチャンネルにプロジェクトテンプレートがある。
 
リポジトリをアルファチャンネルに切り替えて「最新の情報に更新」ボタンを押せば登場すると思う。
 
 
 
*リポジトリ:アルファチャンネル
 
*カテゴリ: IDE Extensions (UnityテンプレートなどがあるGame Developmentカテゴリではないので注意)
 
*名称: MonoDevelop.MonoGame.Templates
 
 
 
[[category:Mono]]
 
[[category:Xamarin.Mac]]
 
[[category:Xamarin.iOS]]
 
 
[[category:Xamarin.Android]]
 
[[category:Xamarin.Android]]

2016年1月14日 (木) 05:45時点における版

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

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

Xamarin.Android

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

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

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

使い方は普通の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");

関連項目

カテゴリ「MonoGame」にあるページ

このカテゴリには 54 ページが含まれており、そのうち以下の 54 ページを表示しています。

M