单游戏多个对象相同的动画



正如花絮所说,我正在尝试在Monogame中制作一个游戏,一个炸弹人的克隆,但是当我尝试生成多个炸弹时,动画就会移动到新位置。游戏对象保留在应有的位置,但没有动画。我认为问题是它加载了已加载的相同动画,但我似乎无法弄清楚每次炸弹生成时如何让它生成一个新动画。我使用 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();
    }
}

}

问题出在这个段上:

protected Dictionary<string, Animation> _animations;
public object Clone() {
    return this.MemberwiseClone();
}

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

对此的解决方案是,每次要克隆炸弹时,实例化所有动画的新副本。

像这样:

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

最新更新