XNA: Основните функции за замяна на DrawableGameComponent (Update, Draw и т.н.) не се извикват

Опитвам се да капсулирам моите игрови обекти, като ги накарам да разширят 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();
    }
}

Animation.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