MonoGameランタイム

概要

このドキュメントでは、MonoGameランタイムの使用方法について説明します。ランタイムの言語はC#です。書き出したJSONファイルを読み込んでシーンで再生する方法の例を説明します。

ランタイムを取得する

ランタイムをCreatureのGame Runtimesウィンドウから直接ダウンロードするか、リポジトリ(こちら)から取得することができます。

名前空間の使用

宣言されている名前空間は次のとおりです:

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Input.Touch;
using Microsoft.Xna.Framework.Storage;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Media;
using MeshBoneUtil;
using CreatureModule;
using CreatureRenderer;
using System.Collections.Generic;

読み込みと初期化

dragonTest.jsonと呼ばれるエクスポートされたドラゴンのアニメーションファイルがあるとしましょう。character-dragon.pngと呼ばれる対応するテクスチャアトラスもあると仮定します。 最初にファイルアセットを読み込むことから始めます:

Dictionary<string, object> load_data = 
    CreatureModule.Utils.LoadCreatureJSONData("dragonTest.json");
curCreature = new CreatureModule.Creature(ref load_data);

上のコードはJSONデータをディスクからメモリに読み込みます。次に、これらの読み込まれたアセットを利用できる実際のオブジェクトを作成しましょう:

curManager = new CreatureModule.CreatureManager (curCreature);

curManager.CreateAnimation (ref load_data, "default");
curManager.CreateAnimation (ref load_data, "pose2");

上記の例では、JSONファイルにはdefaultpose2の2つのアニメーションクリップがあります。従って、creature_managerオブジェクトから2つのアニメーションを作成して再生できるようにする必要があります。

読み込みが完了したら、再生用のアクティブなアニメーションを設定できます:

curManager.SetActiveAnimationName ("default");

これにより、現在アクティブなアニメーションとしてdefaultを設定します。 キャラクターアニメーションのレンダリングに必要なオブジェクトを作成します:

Texture2D curTexture;
curTexture = Content.Load<Texture2D> ("character-dragon");

curRenderer = new CreatureRenderer.Renderer (graphics.GraphicsDevice, curManager, ref curTexture);
curRenderer.world = Matrix.CreateScale (new Vector3(35.0f, 35.0f, 1.0f));

これにより、テクスチャアトラス画像ファイルを持つCreature Rendererが作成されます。完了したら、いくつかの再生プロパティを設定することができます:

curManager.SetIsPlaying (true);
curManager.should_loop = true;

キャラクターのアニメーションとレンダリングアップデート

キャラクターを読み込んだら、2つのコールバックで対応するアップデートコールバックを呼び出して、アニメーションの更新・キャラクターのレンダリングをする必要があります。 例えば、0.025といったタイム・デルタでアニメーションを更新するには、 Update() コールバックに次のコードを挿入します:

protected override void Update (GameTime gameTime)
{
        // TODO: Add your update logic here     
        curManager.Update (0.025f);
        ...
}

その後、 Draw() コールバックでキャラクターをレンダリングする次のコードを記述します:

protected override void Draw (GameTime gameTime)
{
    // Clear the backbuffer
    graphics.GraphicsDevice.Clear (Color.CornflowerBlue);

    //TODO: Add your drawing code here
    base.Draw (gameTime);

    // This renders the character
    curRenderer.DoUpdate (graphics.GraphicsDevice);
}

完全なコードサンプル

以下は完全なコードレイアウトです。ほとんどのコードは、デフォルトのMonoGameプロジェクトスターターテンプレートから生成されています。ほとんどの作業を行う LoadContent() メソッドに注意してください:

#region Using Statements
using System;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Input.Touch;
using Microsoft.Xna.Framework.Storage;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Media;
using MeshBoneUtil;
using CreatureModule;
using CreatureRenderer;
using System.Collections.Generic;


#endregion

namespace Sample
{
    /// <summary>
    /// Default Project Template
    /// </summary>
    public class Game1 : Game
    {

        CreatureModule.Creature curCreature;
        CreatureModule.CreatureManager curManager;
        CreatureRenderer.Renderer curRenderer;
        String curAnimationName;

        #region Fields

        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        Texture2D logoTexture;

        #endregion

        #region Initialization

        public Game1 ()
        {

            graphics = new GraphicsDeviceManager (this);

            Content.RootDirectory = "Assets";

            graphics.IsFullScreen = false;
        }

        /// <summary>
        /// Overridden from the base Game.Initialize. Once the GraphicsDevice is setup,
        /// we'll use the viewport to initialize some values.
        /// </summary>
        protected override void Initialize ()
        {
            base.Initialize ();
        }


        /// <summary>
        /// Load your graphics content.
        /// </summary>
        protected override void LoadContent ()
        {
            Dictionary<string, object> load_data = CreatureModule.Utils.LoadCreatureJSONData("dragonTest.json");
            curCreature = new CreatureModule.Creature(ref load_data);
            curManager = new CreatureModule.CreatureManager (curCreature);

            curManager.CreateAnimation (ref load_data, "default");
            curManager.CreateAnimation (ref load_data, "pose2");

            curAnimationName = "default";
            curManager.SetActiveAnimationName (curAnimationName);
            curManager.SetIsPlaying (true);
            curManager.should_loop = true;

            Texture2D curTexture;
            curTexture = Content.Load<Texture2D> ("character");

            curRenderer = new CreatureRenderer.Renderer (graphics.GraphicsDevice, curManager, ref curTexture);
            curRenderer.world = Matrix.CreateScale (new Vector3(35.0f, 35.0f, 1.0f));
        }

        #endregion

        #region Update and Draw

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update (GameTime gameTime)
        {
            // TODO: Add your update logic here     
            curManager.Update (0.025f);

            base.Update (gameTime);
        }

        /// <summary>
        /// This is called when the game should draw itself. 
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw (GameTime gameTime)
        {
            // Clear the backbuffer
            graphics.GraphicsDevice.Clear (Color.CornflowerBlue);

            //TODO: Add your drawing code here
            base.Draw (gameTime);

            curRenderer.DoUpdate (graphics.GraphicsDevice);
        }

        #endregion
    }
}

カスタム時間/フレーム範囲

現在アクティブなアニメーションのカスタム時間/フレーム範囲を設定できます。再生範囲を10〜20のフレーム範囲に制限したい場合、次の操作を行います:

curManager.use_custom_time_range = true;
curManager.custom_start_time = 10;
curManager.custom_end_time = 30;

アニメーションブレンディング

2つのアニメーションクリップをブレンドするには、次の手順を実行します:

curManager.SetBlending(true);   
curManager.SetBlendingAnimations("default", "pose2");
curManager.SetBlendingFactor(0.5);   // 0 to 1 blends between the 2 clips

ボーンの位置を変更する

場合によっては、キャラクターのボーンの位置を直接変更する必要があります。例えば、ボーンの位置をラグドール物理のスプリング/ジョイントに接続されたいくつかの剛体に従わせることができます。独自のカスタム要件に合わせてボーンの位置を設定する必要がある場合、次の操作を行う必要があります。まず、カスタムボーンオーバーライドメソッドを記述します。yのボーンをある量だけ置き換える例を次に示します:

// This demonstrates the ability to override/modify bone positions

void UpdateBonesToCustomPositions(Dictionary<string, MeshBoneUtil.MeshBone> bones_map)
{
    foreach(KeyValuePair<string, MeshBoneUtil.MeshBone> entry in bones_map)
    {
        var cur_bone = entry.Value;
        // displace each bone upwards by y as an example
        var cur_world_start_pos = cur_bone.getWorldStartPt();
        var cur_world_end_pos = cur_bone.getWorldEndPt();

        float displace_y = -20.0f;
        cur_world_start_pos.Y += displace_y;
        cur_world_end_pos.Y += displace_y;

        cur_bone.setWorldStartPt(cur_world_start_pos);
        cur_bone.setWorldEndPt(cur_world_end_pos);
    }

}

また、カスタムボーン修正コールバックを使用するためにCreatureManagerに次のように伝える必要があります:

    // The following code sets an optional bone override callback for modifying bone positions
    CreatureManager cur_manager = creature_renderer.creature_manager;
    cur_manager.bones_override_callback = UpdateBonesToCustomPositions;

キャラクターのインスタンス化とメモリ

キャラクターの複数コピー(例:2体のドラゴン)をインスタンス化する必要がある場合、以下のようにアニメーションを作成する必要があります:

var new_animation_1 = new CreatureModule.CreatureAnimation(ref load_data, "default");
var new_animation_2 = new CreatureModule.CreatureAnimation(ref load_data, "pose2");

その後、新しいCreatureオブジェクト、新しいCreatureManagerオブジェクト、および新しいCreatureRendererオブジェクトを作成する必要があります。作成したアニメーションを、新しく作成したCreatureManagerオブジェクトに次のように追加します:

new_creature_manager_2.AddAnimation(new_animation_1);
new_creature_manager_2.AddAnimation(new_animation_2);

この例と前の例との違いは、アニメーションが最初に作成され、それぞれのCreatureManagersに追加されることです。これは、アニメーションに割り当てられたメモリ(最もエクスペンシブなもの)が標準の場所に格納されていることを意味します。複数のCreatureManagerオブジェクトは、CreatureAnimationオブジェクトの共有プールからアニメーションを追加します。