【问题标题】:Monogame multiple objects same animationMonogame多个对象相同的动画
【发布时间】:2017-10-23 17:15:56
【问题描述】:

正如标题所说,我正在尝试在 Monogame 中制作一款游戏,这是一个 Bomberman 克隆,但是当我尝试生成多个炸弹时,atm 动画只会移动到新位置。游戏对象停留在应有的位置,但没有动画。我认为问题在于它加载了已加载的相同动画,但我似乎无法弄清楚每次炸弹产生时如何让它产生一个新动画。 我使用 Content.Load 来获取 sorite 动画,并使用带有动画的 clone() 函数生成炸弹。

var bombAni = new Dictionary<string, Animation>() {
            {"Bomb", new Animation(Content.Load<Texture2D>("Obstacle/Bomb"), 3) },
        };

        _sprites = new List<Sprite>() {

            new Player(animations) {
                _bomb = new Bomb(bombAni),
                Position = new Vector2(32, 32),
                Input = new Input() {
                    Up = Keys.W,
                    Down = Keys.S,
                    Left = Keys.A,
                    Right = Keys.D,
                    Space = Keys.Space,
                }
            }

        };

public void Play(Animation animation) {
        if (animation == _animation) {
            return;
        }

        _animation = animation;

        _animation.CurFrame = 0;

        _timer = 0;
    }

private void AddBomb(List<Sprite> sprites) {

        var bomb = _bomb.Clone() as Bomb;
        switch (_direction) {
            case "Up":
                bomb.Position = _position + new Vector2(0, -32);
                break;
            case "Down":
                bomb.Position = _position + new Vector2(0, 32);
                break;
            case "Left":
                bomb.Position = _position + new Vector2(-32, 0);
                break;
            case "Right":
                bomb.Position = _position + new Vector2(32, 0);
                break;
        }
        bomb.lifeSpan = 3f;
        bomb.Parent = this;
        bombCount++;

        sprites.Add(bomb);
    }

public Sprite(Dictionary<string, Animation> animations) {

        _animations = animations;
        _animationManager = new AnimationManager(_animations.First().Value);

    }


namespace CompetenceWeek.scripts {
public class Bomb : Sprite {

    public float lifeSpan;
    private float _timer;

    public Bomb(Dictionary<string, Animation> animations) : base(animations) {

    }

    public Bomb(Texture2D texture) : base(texture) {

    }


    public override void Update(GameTime gameTime, List<Sprite> sprites) {
        _timer += (float)gameTime.ElapsedGameTime.TotalSeconds;

        SetAnimations();

        _animationManager.Update(gameTime);

        if (_timer > lifeSpan) {
            isDead = true;
        }

    }

}

}

namespace CompetenceWeek.scripts {
public class Sprite : ICloneable {

    protected AnimationManager _animationManager;

    protected Dictionary<string, Animation> _animations;

    protected Vector2 _position;

    protected Texture2D _texture;

    public bool Walkable { get; set; } = false;

    public bool isDead = false;


    public Player Parent { get; set; }

    public Input Input;

    public Vector2 Position {
        get { return _position; }
        set {
            _position = value;

            if(_animationManager != null) {
                _animationManager.Posistion = _position;
            }
        }
    }

    public float Speed = 2.5f;

    public Vector2 Velocity;

    public virtual void Draw(SpriteBatch spriteBatch) {

        if(_texture != null) {
            spriteBatch.Draw(_texture, Position, Color.White);
        } else if (_animationManager != null) {
            _animationManager.Draw(spriteBatch);
        } else {
            throw new Exception("somthings not right");
        }


    }



    public Sprite(Dictionary<string, Animation> animations) {

        _animations = animations;
        _animationManager = new AnimationManager(_animations.First().Value);

    }

    public Sprite(Texture2D texture) {
        _texture = texture;
    }

    public virtual void Update(GameTime gameTime, List<Sprite> sprites) {
        SetAnimations();

        _animationManager.Update(gameTime);

        Position += Velocity;
        Velocity = Vector2.Zero;


    }

    protected virtual void SetAnimations() {
        if (Velocity.X > 0) {
            _animationManager.Play(_animations["PlayerRight"]);
        } else if (Velocity.X < 0) {
            _animationManager.Play(_animations["PlayerLeft"]);
        } else if (Velocity.Y > 0) {
            _animationManager.Play(_animations["PlayerDown"]);
        } else if (Velocity.Y < 0) {
            _animationManager.Play(_animations["PlayerUp"]);
        }
    }

    public object Clone() {
        return this.MemberwiseClone();
    }
}

}

【问题讨论】:

  • 能把相关代码分享给我们吗?
  • 它现在在那里,对不起第一次在这里发帖^^;
  • 你能显示你的 Bomb 类的代码吗?看来,当您克隆炸弹时,您引用的动画实例与现有炸弹相同。这是浅克隆的问题之一。
  • 刚刚添加了 Bomb 类,但克隆来自 Sprite 类,但据我所知,这应该不会有所作为。

标签: c# animation sprite monogame


【解决方案1】:

问题出在这一段:

protected Dictionary<string, Animation> _animations;

public object Clone() {
    return this.MemberwiseClone();
}

当您执行按成员克隆时,它会创建一个浅拷贝,重用对引用类型对象的现有引用。这意味着 Clone 将与原始对象共享相同的动画状态。

解决这个问题的方法是,每次您想要克隆 Bomb 时都实例化所有动画的新副本。

类似这样的:

public object Clone() {
    var bomb = (Bomb)this.MemberwiseClone();
    bomb.InitAnimations(new Dictionary<string, Animation>() {
        {"Bomb", new Animation(Content.Load<Texture2D>("Obstacle/Bomb"), 3) },
    };
    return bomb;
}

【讨论】:

  • 是的,这也是我的想法,但我似乎无法从任何其他地方访问 Content.Load,然后在 game.cs 类中
  • 在广泛使用 MonoGame 进行开发时,我们发现让 Game 的实例可用于应用程序的其他部分非常有用。有很多方法可以做到这一点。天真的实现只是让它在全局空间中可用:github.com/EnigmaDragons/Astrocell/blob/master/MonoDragons.Core/… 你可以让你的 Game 实例调用在启动时初始化。
  • 好吧,我花了一些时间来弄清楚你对游戏实例的看法,但我通过这个公共覆盖对象 Clone() { var bomb = new Bomb(new Dictionary() { {"Bomb", new Animation(GameInstance.TheGame.Content.Load("Obstacle/Bomb"), 3) }, });回弹; } 非常感谢你的帮助! ^^
猜你喜欢
  • 2020-03-29
  • 1970-01-01
  • 1970-01-01
  • 2023-03-17
  • 2015-09-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多