1

戻ってきました。また。:3 現在、私は自分の RPG プロジェクトに取り組んでおり (楽しみのために、簡単にできるという幻想はありません)、基礎となるフレームワークを書き終えたところまで来ました。スプライト マップからスプライトを描画するエレガントな方法を書きたいと思います。

現時点では、ポケモン ダイヤモンドのスプライト マップを使用しています (簡単に入手できたので、テストのためです。次の「ポケモン」ゲームは作成していません)。メイン ヒーローが 3 方向すべてを 1 行で 37 ピクセルで歩いています。 x 37px スプライト、画像内に 12 個のスプライト。

画像はこちら: http://spriters-resource.com/ds/pkmndiamondpearl/lucas.png (現在、「ウォーキング」サブセットを使用しています)。

SpriteSheet クラス (スプライトシートのコレクションの XML ファイルの表現である SpriteSheetData クラスと共に) と SpriteManager クラスを作成しました。これらはすべて以下にリストされています。

スプライトシート.cs

namespace RPG.Utils.Graphics
{
/// <summary>
/// Represents a Sprite Sheet. A Sprite Sheet is a graphic that contains a number of frames for animations.
/// These are laid out a set distance apart.
/// </summary>
public struct SpriteSheet
{
    /// <summary>
    /// The name for the texture. Used internally to reference the texture.
    /// </summary>
    [ContentSerializer]
    public string TextureName
    {
        get;
        private set;
    }
    /// <summary>
    /// The file name of the texture.
    /// </summary>
    [ContentSerializer]
    public string TextureFile
    {
        get;
        private set;
    }
    /// <summary>
    /// The width of each sprite in the sprite sheet.
    /// </summary>
    [ContentSerializer]
    public int SpriteWidth
    {
        get;
        private set;
    }
    /// <summary>
    /// The height of each sprite in the sprite sheet.
    /// </summary>
    [ContentSerializer]
    public int SpriteHeight
    {
        get;
        private set;
    }
    /// <summary>
    /// The interval between each frame of animation.
    /// This should be (by default) 100f or 100ms.
    /// </summary>
    [ContentSerializer]
    public float AnimationInterval
    {
        get;
        set;
    }

    /// <summary>
    /// The number of frames per each individual animation.
    /// </summary>
    [ContentSerializer]
    public int AnimationLength
    {
        get;
        set;
    }

    /// <summary>
    /// The texture for this sprite sheet.
    /// </summary>
    [ContentSerializerIgnore]
    public Texture2D Texture
    {
        get;
        set;
    }
}

SpriteManager.cs

/// <summary>
/// A sprite manager. Just loads sprites from a file and then stores them.
/// </summary>
public static class SpriteManager
{
    private static Dictionary<string, SpriteSheetData> m_spriteSheets;
    public static Dictionary<string, SpriteSheetData> SpriteSheets
    {
        get
        {
            if (m_spriteSheets == null)
                m_spriteSheets = new Dictionary<string, SpriteSheetData>();
            return m_spriteSheets;
        }
    }
    /// <summary>
    /// Loads all the sprites from the given directory using the content manager.
    /// Sprites are loaded by iterating SpriteSheetData (.xml) files inside the /Sprites/ directory.
    /// </summary>
    /// <param name="mgr">Content Manager.</param>
    /// <param name="subdir">Directory to load.</param>
    public static void LoadAllSprites(ContentManager mgr, string subdir)
    {
        // Get the files in the subdirectory.
        IEnumerable<string> files = Directory.EnumerateFiles(mgr.RootDirectory+"/"+subdir);
        foreach (string f in files)
        {
            // Microsoft, why do you insist on not letting us load stuff with file extensions?
            string fname = f.Replace("Content/", "").Replace(".xnb", "");
            SpriteSheetData data = mgr.Load<SpriteSheetData>(fname);

            string spriteSheetDir = subdir +"/" + data.SpriteSheetName + "/";

            int loaded = 0;
            for (int i = 0; i < data.SpriteSheets.Length; i++)
            {
                loaded++;
                SpriteSheet current = data.SpriteSheets[i];
                current.Texture = mgr.Load<Texture2D>(spriteSheetDir + current.TextureFile);
                data.SpriteSheetMap[current.TextureName] = current;
            }

            Console.WriteLine("Loaded SpriteSheetData file \"{0}\".xml ({1} sprite sheet(s) loaded).", data.SpriteSheetName, loaded);
            SpriteSheets[data.SpriteSheetName] = data;
        }
    }

    /// <summary>
    /// Query if a given Sprite definition file is loaded.
    /// </summary>
    /// <param name="spriteName">
    /// The sprite definition file name (ie, "Hero"). This should correspond with the XML file
    /// that contains the definition for the sprite sheets. It should NOT be the name OF a spritesheet.
    /// </param>
    /// <returns>True if the sprite definition file is loaded.</returns>
    public static bool IsLoaded(string spriteName)
    {
        return SpriteSheets.ContainsKey(spriteName);
    }
}

SpriteSheetData.cs

/// <summary>
/// Represents data for a SpriteSheet. These are stored in XML files.
/// </summary>
public struct SpriteSheetData
{
    /// <summary>
    /// The collective name for the sprite sheets.
    /// </summary>
    [ContentSerializer]
    public string SpriteSheetName
    {
        get;
        set;
    }
    /// <summary>
    /// The SpriteSheets in this data file.
    /// </summary>
    [ContentSerializer]
    internal SpriteSheet[] SpriteSheets
    {
        get;
        set;
    }


    [ContentSerializerIgnore]
    private Dictionary<string, SpriteSheet> m_map;
    /// <summary>
    /// The sprite sheet map.
    /// </summary>
    [ContentSerializerIgnore]
    public Dictionary<string, SpriteSheet> SpriteSheetMap
    {
        get
        {
            if (m_map == null)
                m_map = new Dictionary<string, SpriteSheet>();
            return m_map;
        }
    }
}

スプライトを「読み込む」ために使用しているファイルは、Sprites/Hero.xml です。

<?xml version="1.0" encoding="utf-8" ?>
<XnaContent>
  <Asset Type="RPG.Utils.Graphics.SpriteSheetData">
    <SpriteSheetName>Hero</SpriteSheetName>
    <SpriteSheets>
      <Item Type="RPG.Utils.Graphics.SpriteSheet">
        <TextureName>HeroWalking</TextureName>
        <TextureFile>hero_walk</TextureFile>
        <SpriteWidth>37</SpriteWidth>
        <SpriteHeight>37</SpriteHeight>
        <AnimationInterval>400</AnimationInterval>
        <AnimationLength>3</AnimationLength>
      </Item>
    </SpriteSheets>
  </Asset>
</XnaContent>

私が抱えている問題は、1) スプライトの読み込みと 2) スプライト シートのペアリングをエレガントに整理する方法がわからないことです (これはゲームの「一般的な」部分であり、再利用するつもりです。 、したがって、私が作成できるエンティティのインスタンスの数がわからない)エンティティ/ゲーム内オブジェクト-特にプレーヤー(それが私が今やろうとしていることだから)。続行する方法がわからないので、どんな助けでも大歓迎です。

さらにコードが必要な場合は (神は禁じます) 尋ねてください。それはあなたに与えられます:3

4

1 に答える 1

0

組織化に関しては、私はいつもそれを特定の方法で行うのが好きでした。あなたが使用した構造は、それにかなり適しています。

私は次のようにオブジェクトをロードするのが好きです:

  1. X タスク/レベルに何をロードする必要があるかを記述したレベル ファイル (XML または TXT) を用意します。
  2. これをループで繰り返します。ロードされる各オブジェクトには、それぞれ独自のファイルがあります (Hero.xml によく似ています)。
  3. これらはそれぞれ、すべてのデータのロードを処理するレベル マネージャーを介してロードされます。
  4. 描画し、レベル マネージャーを介してレベルを実行します。

次に、レベルマネージャーを呼び出して実装する方法は、主にあなた次第です。これらのレベル構成ファイルとレベル マネージャーを使用するのが好きです。これにより、レベル マネージャー全体でリソースを共有できるからです。したがって、ディクショナリを使用してレベル マネージャー内から参照されたテクスチャを使用し、それらをロードされたレベル内のゲーム オブジェクトに渡すことができます。

私が C# で知っていることから、「参照渡し」はこれが問題になるのを防ぐ傾向がありますが、私はレベルのこの種のコンテンツ管理が素晴らしいアイデアである C++ の分野から来ました。

プレーヤーに関しては、レベル マネージャーとのインターフェイスとなるプレーヤー マネージャー クラスを作成して、レベルとロードの間でプレーヤーを永続的に保つことができます。

これがとにかく整理する方法です。

乾杯!

于 2012-06-11T22:54:01.427 に答える