Ошибка анимации, вызванная параметрами C #, передаваемыми по ссылке, а не по значению, но где? - PullRequest
2 голосов
/ 16 июля 2010

У меня проблемы со спрайтовой анимацией в XNA, которая, кажется, вызвана структурой, переданной в качестве ссылочного значения.Но я нигде не использую ключевое слово ref .По общему признанию, я C # noob, так что здесь может быть небольшая мелкая ошибка, но я не вижу этого.

Я создаю 10 муравьев или пчел и оживляю их, когда они перемещаются поэкран.У меня есть массив структур анимации, и каждый раз, когда я создаю муравья или пчелу, я отправляю ему требуемое значение массива анимации (просто [0] или [1] в это время).Глубоко внутри структуры анимации находится таймер, который используется для смены кадров.Класс ant / bee хранит структуру анимации как частную переменную.

Что я вижу, так это то, что каждый муравей или пчела использует одну и ту же анимационную структуру, ту, которую, как я думал, я передавал и копировал по значению.Поэтому во время Update (), когда я перемещаю таймер анимации для каждого муравья / пчелы, у следующего муравья / пчелы свой таймер анимации увеличивается на эту небольшую величину.Если на экране есть 1 муравей, он оживляет должным образом.2 муравья, он работает в два раза быстрее и так далее.Очевидно, не то, что я хочу.

Вот сокращенная версия кода.Как BerryPicking's ActorAnimationGroupData [] распределяется между BerryCreatures?

class BerryPicking
{
    private ActorAnimationGroupData[] animations;
    private BerryCreature[] creatures;
    private Dictionary<string, Texture2D> creatureTextures;
    private const int maxCreatures = 5;

    public BerryPickingExample()
    {
        this.creatures = new BerryCreature[maxCreatures];
        this.creatureTextures = new Dictionary<string, Texture2D>();
    }

    public void LoadContent()
    {
        // Returns data from an XML file
        Reader reader = new Reader();
        animations = reader.LoadAnimations();

        CreateCreatures();
    }

    // This is called from another function I'm not including because it's not relevant to the problem.
    // In it, I remove any creature that passes outside the viewport by setting its creatures[] spot to null.
    // Hence the if(creatures[i] == null) test is used to recreate "dead" creatures. Inelegant, I know.
    private void CreateCreatures()
    {
        for (int i = 0; i < creatures.Length; i++)
        {
            if (creatures[i] == null)
            {
                // In reality, the name selection is randomized
                creatures[i] = new BerryCreature("ant");

                // Load content and texture (which I create elsewhere)
                creatures[i].LoadContent(
                    FindAnimation(creatures[i].Name),
                    creatureTextures[creatures[i].Name]);
            }
        }
    }

    private ActorAnimationGroupData FindAnimation(string animationName)
    {
        int yourAnimation = -1;

        for (int i = 0; i < animations.Length; i++)
        {
            if (animations[i].name == animationName)
            {
                yourAnimation = i;
                break;
            }
        }

        return animations[yourAnimation];
    }

    public void Update(GameTime gameTime)
    {
        for (int i = 0; i < creatures.Length; i++)
        {
            creatures[i].Update(gameTime);
        }
    }
}

class Reader
{
    public ActorAnimationGroupData[] LoadAnimations()
    {
        ActorAnimationGroupData[] animationGroup;
        XmlReader file = new XmlTextReader(filename);

        // Do loading...

        // Then later
        file.Close();
        return animationGroup;
    }
}

class BerryCreature
{
    private ActorAnimation animation;
    private string name;

    public BerryCreature(string name)
    {
        this.name = name;
    }

    public void LoadContent(ActorAnimationGroupData animationData, Texture2D sprite)
    {
        animation = new ActorAnimation(animationData);
        animation.LoadContent(sprite);
    }

    public void Update(GameTime gameTime)
    {
        animation.Update(gameTime);
    }
}

class ActorAnimation
{
    private ActorAnimationGroupData animation;

    public ActorAnimation(ActorAnimationGroupData animation)
    {
        this.animation = animation;
    }

    public void LoadContent(Texture2D sprite)
    {
        this.sprite = sprite;
    }

    public void Update(GameTime gameTime)
    {
        animation.Update(gameTime);
    }
}

struct ActorAnimationGroupData
{
    // There are lots of other members of this struct, but the timer is the only one I'm worried about.
    // TimerData is another struct
    private TimerData timer;

    public ActorAnimationGroupData()
    {
        timer = new TimerData(2);
    }

    public void Update(GameTime gameTime)
    {
        timer.Update(gameTime);
    }
}

struct TimerData
{
    public float currentTime;
    public float maxTime;

    public TimerData(float maxTime)
    {
        this.currentTime = 0;
        this.maxTime = maxTime;
    }

    public void Update(GameTime gameTime)
    {
        currentTime += (float)gameTime.ElapsedGameTime.TotalSeconds;
        if (currentTime >= maxTime)
        {
            currentTime = maxTime;
        }
    }
}

1 Ответ

0 голосов
/ 04 января 2011

Вы уверены, что используете новую ActorAnimation с каждым существом?Я хотел бы создать тест, в котором есть два существа, и установить часы для значений анимации каждого существа. Анимация и пройти через обновления, чтобы увидеть, когда они меняются.Возможно ли, чтобы ваши Updates () вызывались несколько раз?

...