2012-05-24 4 views
1

전으로 돌아 왔습니다. 다시. : 3 지금 당장 RPG 프로젝트를 진행하고 있습니다. 재미있을 뿐이므로 쉽게 이해할 수 있습니다. 기본 프레임 워크를 작성한 지점으로 이동했습니다. 이제 스프라이트 맵에서 스프라이트를 그릴 우아한 방법을 쓰고 싶습니다.스프라이트, XNA, C# 및 우아함

포켓 몬스터 다이아몬드의 스프라이트 맵을 사용하고 있습니다 (쉽게 테스트 할 수 있기 때문에 테스트 할 수 있습니다. 다음 포켓몬 게임을 만들지는 않습니다). 메인 영웅이 세 방향으로 모두 걷고 있습니다. 하나의 행, 37px x 37px 스프라이트, 이미지의 12 스프라이트.

이미지는 여기에 있습니다 : http://spriters-resource.com/ds/pkmndiamondpearl/lucas.png (현재 "Walking"하위 세트로 작업 중입니다).

나는 아래에 나열되어 모두와 SpriteManager 클래스 (spritesheets의 수집에 대한 XML 파일의 표현 인 SpriteSheetData 클래스와 함께) SpriteSheet 클래스를 만들었습니다

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

그리고 나는 스프라이트를 "읽어"을 사용하고있는 파일은 다음과 같습니다 스프라이트/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

답변

0

현명 조직, 난 항상 그것을 하나의 특정 방법으로 일을 사랑했던, 그리고 구조는 당신이 빌려 사용했습니다 그 자체는 상당히 잘 그것.

나는과 같이 내 개체를로드하고자 :

  1. 는 X 작업/레벨로드되어야 하는지를 설명하는 수준의 파일 (XML 또는 TXT)가 있습니다.
  2. 루프를 통해이 과정을 반복하면로드 할 각 객체는 각각 Hero.xml과 같은 자체 파일을 갖습니다.
  3. 이들 각각은 모든 데이터로드를 처리하는 레벨 관리자를 통해로드됩니다.
  4. 그리기를 진행하고 수준 관리자를 통해 수준을 실행합니다.

다음은 레벨 관리자에게 전화를 걸고 구현하는 방법에 달려 있습니다. 저는 수준 관리자뿐만 아니라이 수준의 구성 파일을 사용하기를 원합니다. 그 이유는 수준 관리자 전체에서 리소스를 공유 할 수 있기 때문입니다. 따라서 레벨 관리자에서 참조 된 텍스처를 사전과 함께 사용하여로드 된 레벨의 게임 객체에 전달할 수 있습니다. 이렇게하면로드 된 텍스처가 배수가되지 않습니다.

"C#에서 알고있는 것부터"참조로 넘어가는 것이 문제가되지 않도록하는 경향이 있지만이 수준의 콘텐츠 관리가 좋은 아이디어 인 C++ 분야에서 왔습니다.

플레이어의 경우 수준 관리자와의 인터페이스를 통해 플레이어 관리자 클래스를 만들어 플레이어가 중간 레벨 및로드 상태를 유지할 수 있도록 할 수 있습니다.

어쨌든 이것을 구성하는 방법입니다.

건배!

+0

제쳐두고 제가 일반적으로 관리자와 같이하고 싶은 점은 그리기 방법을 사용할 수 있도록 허용 한 것입니다. 이 메서드는 SpriteBatch 또는 GraphicsDevice를 가져 와서 데이터를 렌더링 한 다음 렌더링합니다. 매우 우아하게 메인 로직 루프에서 업데이트 로직과 드로를 분리 할 수 ​​있습니다. 이렇게하면 클래스를 다른 게임 논리 및 관리자에 대해 너무 많이 알지 못하게 할 수 있습니다. 오류가 넘쳐나지 않도록 가능한 한 클래스를 독립적으로 유지하려고합니다. 도움이 되길 바랍니다! 건배! –