XNA: базовые функции переопределения DrawableGameComponent (обновление, рисование и т. д.) не вызываются

Я пытаюсь инкапсулировать свои игровые объекты, расширяя Mircosoft.Xna.Framework.GameCompenent, а затем просто создавая их и управляя ими в методе Update() Game1. У меня есть класс Game1, класс Player и класс Animation. Предполагается, что анимации управляют изменениями объекта Texture2D, в данном случае Player.

Моя проблема в том, что, несмотря на то, что я успешно расширил все, у меня не было синтаксических ошибок, исключений и я проверял и перепроверял тот небольшой код, который я написал, функции переопределения не вызываются, и я получаю черный экран.

Game1.cs: (обратите внимание, что изменены только две строки для объявления Player)

public class Game1 : Microsoft.Xna.Framework.Game
{
    GraphicsDeviceManager graphics;
    SpriteBatch spriteBatch;

    Player player;

    public Game1()
    {
        graphics = new GraphicsDeviceManager(this);
        Content.RootDirectory = "Content";
    }

    protected override void Initialize()
    {
        player = new Player(this);

        base.Initialize();
    }

    protected override void LoadContent()
    {
        spriteBatch = new SpriteBatch(GraphicsDevice);
    }

    protected override void UnloadContent()
    {

    }

    protected override void Update(GameTime gameTime)
    {
        if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
            this.Exit();

        // TODO: Add your update logic here

        base.Update(gameTime);
    }

    protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(Color.Black);
        base.Draw(gameTime);
    }
}

Player.cs:

class Player : Microsoft.Xna.Framework.DrawableGameComponent
{
    Rectangle bounds;
    Texture2D t;
    Animation[] animations = new Animation[4];
    String path = @"..\..\..\Content\player.png";

    #region Animation Constants
    private const int WALK_RIGHT = 0;
    #endregion

    SpriteBatch spriteBatch;

    public Player(Game game) : base(game)
    {
        //should only ever be one player, all value defaults set in Initialize()
    }

    public Texture2D T
    {
        get { return t; }
    }

    public Rectangle Bounds
    {
        get { return bounds; }
    }

    public override void Initialize()
    {
        base.Initialize();

        bounds = new Rectangle(0, 0,
            System.Drawing.Image.FromFile(path).Width,
            System.Drawing.Image.FromFile(path).Height
        );

        t = Game.Content.Load<Texture2D>("player");
        animations[0] = new Animation(this.Game, "player", "walking", 3);
    }

    protected override void LoadContent()
    {
        base.LoadContent();

        spriteBatch = new SpriteBatch(this.Game.GraphicsDevice);
    }

    public override void Update(GameTime gameTime)
    {
        base.Update(gameTime);

        KeyboardState k = Keyboard.GetState();

        if (k.IsKeyDown(Keys.Right)) //walk right
        {
            bounds.X += 3;
            if (animations[WALK_RIGHT].Playing)
            {
                t = animations[WALK_RIGHT].getTexture();
            }
            else
            {
                animations[WALK_RIGHT].Play();
            }
        }
        else if (animations[WALK_RIGHT].Playing)
            animations[WALK_RIGHT].Stop();

    }

    public override void Draw(GameTime gameTime)
    {
        base.Draw(gameTime);

        spriteBatch.Begin();
        spriteBatch.Draw(t, bounds, Color.White);
        spriteBatch.End();
    }
}

Анимация.cs:

class Animation : Microsoft.Xna.Framework.GameComponent
{
    Game game;
    String name; //name of default sprite; standing, unmoving, neutral, etc. The rest of the animation sprite names should derive from this
    String keyword;
    int frameCount;
    int delay; //frames between texture change


    String[] paths; //texture pathnames generated by the MakePaths() function
    int currentFrame = 0;
    int delayCount = 0;
    bool playing = false;

    public Animation(Game associatedGame, String nameVal, String keywordVal, int frameCountVal)
        : base(associatedGame)
    {
        name = nameVal;
        keyword = keywordVal;
        frameCount = frameCountVal;
        paths = MakePaths();
        delay = 10;
    }

    public Animation(Game associatedGame, String nameVal, String keywordVal, int frameCountVal, int delayVal)
        : base(associatedGame)
    {
        name = nameVal;
        keyword = keywordVal;
        frameCount = frameCountVal;
        paths = MakePaths();
        delay = delayVal;
    }

    private String[] MakePaths()
    {
        //format: name_keyword_anim[i]
        //format example: player_walking_anim1

        String[] temp = new String[frameCount];
        for (int i = 0; i < frameCount; i++)
        {
            temp[i] = name + "_" + keyword + "_" + "anim" + i.ToString();
        }

        return temp;
    }

    public Texture2D getTexture()
    {
        return Game.Content.Load<Texture2D>(paths[currentFrame]);
    }

    public void Play()
    {
        playing = true;
    }

    public void Stop()
    {
        currentFrame = 0;
        delayCount = 0;
        playing = false;
    }

    public bool Playing
    {
        get { return playing; }
    }

    public override void Update(GameTime gameTime)
    {
        if (playing)
        {
            if (delayCount == delay)
            {
                delayCount = 0;

                if ((currentFrame + 1) == frameCount) currentFrame = 0;
                else currentFrame++;
            }
            else delayCount++;
        }
        base.Update(gameTime);
    }

    public override string ToString()
    {
        return "params: " + name + "," + keyword + "," + frameCount.ToString() + "\nUsing paths: " + paths;
    }
}

Вызываются только те методы LoadContent, Initialize, Update и Draw, которые находятся в Game1. Что действительно сбивает меня с толку, так это то, что я мог использовать эту технику раньше без проблем. Эти функции будут вызываться естественным образом в процессе обновления Xna.

Итак... почему это?


person Matt Dennis    schedule 22.08.2010    source источник
comment
Слишком много кода, слишком трудоемко для чтения. Приведите небольшой изолированный пример вашей проблемы.   -  person Timwi    schedule 22.08.2010


Ответы (1)


Вам нужно добавить игровые компоненты в коллекцию компонентов, чтобы они вызывались автоматически.

protected override void Initialize()
{
    player = new Player(this);
    Components.Add(player);

    base.Initialize();
}

См. http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.game.components.aspx

person The ZMan    schedule 22.08.2010
comment
Извините за большое количество кода, я просто не был уверен, в чем может быть проблема. Я полагаю, что мог бы опубликовать только части Update, Draw и т. д., но это все равно было бы много кода... В любом случае, спасибо за ответ. Это работало без проблем. - person Matt Dennis; 22.08.2010