【问题标题】:How to delete specific non-unique object in list without knowing its index如何在不知道其索引的情况下删除列表中的特定非唯一对象
【发布时间】:2015-09-21 17:20:01
【问题描述】:

我正在使用MonoGame 制作一个小游戏作为练习。你是一艘船,用子弹射击小行星。

我有一个可以射击的物体,然后它会爆炸成一堆子弹,除了移除原来的炸弹物体外,一切都有效。

我在 List 中处理我的对象,其中 entity 是列表中所有对象(例如船、小行星、子弹等)继承自的对象,我这样做是为了将它们放在 1 个列表中并将当它们碰撞时,清理列表上的索引,循环遍历并从原始列表中删除具有清理列表中索引的项目。

TL;DR 问题是,我不知道如何使用仅包含索引的列表来跟踪特定的炸弹对象,因为一直在删除和添加不同的对象。

如果我尝试在 Bomb 对象中使用某种计时器,我无法从对象本身中删除它,我什至尝试调用外部方法 Finalize 将对象设置为 NULL,但这也不起作用。 我用了这行代码:

game.objectController.Finalize(this);

还有这个方法:

public void Finalize(Entity obj)
{
    obj = null;
}

一个困难的解决方案是制定某种方法来跟踪实体列表中的所有索引,即使它们“四处移动”,但这不是处理它的正确方法吗?

我能想到的另一个解决方案是从炸弹对象中执行一些操作,该对象将返回它的列表条目,但我不知道该怎么做。

提前感谢您的帮助。

编辑:这是我尝试作为接口的代码

interface IDestructible
{
public bool Isdestroyed();
}

这是我在要在一定时间限制后销毁的可破坏对象中使用的实现方法:

public bool IDestructible.Isdestroyed(){
    if (timer == 25)
    {
        Explode();
        return true;
    } return false;
}`

【问题讨论】:

    标签: c# list oop monogame


    【解决方案1】:

    原来的子弹对象在某种程度上是特殊的,所以你可以让它实现一个特定的接口或者是一个派生类。例如,您可以创建这样的接口:

    public interface IDestroyable
    {
    }
    

    然后您可以遍历列表并在运行时检查哪个元素使用is 运算符实现了接口。并删除它。

    public class SourceBullet : Entity, IDestroyable
    {
        // whatever
    }
    

    现在:

    foreach (var item in myList)
    {
        if (item is IDestroyable) 
        {
            myList.Remove(item);
        }
    }
    

    这样您就不需要一直跟踪对象。通过从Entity 继承,原始项目符号仍然可以是列表的一部分,但您可以将其与其他项目符号区分开来。

    【讨论】:

    • 有趣,我想我什至可以放入一个虚拟方法来检查炸弹对象中的计时器,如果它返回 true,我将其删除,不是吗?
    • @stickypatrol 当然可以:-)
    • 我尝试了这个解决方案,但似乎无法让它发挥作用。问题是我遍历了一个实体对象列表(公共基类)并且实体对象并不都有一个检查时间的通用方法,我可以实现这样的接口:(IDestructible)entityList[p]. 但我可以'不要使用接口中的方法。
    • @stickypatrol 看起来你需要做if (item is IDestructable) { ((IDestructable)item).Destroy() }。按照您编写它的方式,您首先调用Entity 对象上的方法/属性并将此调用的结果转换为IDestructable。另请注意,实现和强制转换是完全不同的两件事。
    【解决方案2】:

    当我处于类似情况时,我没有使用游戏引擎,我最终做的是让每个对象跟踪它自己的状态,然后循环运行所有对象以在结束时清理它们主游戏循环。

    class gameobject
    {
        public bool isDestroyed {get;set;}
    }
    class bomb : gameobject
    {
    }
    
    main loop update:
    
    for(i = gameobjectcollection.Length; i--; i > -1 )
    {
       if(gameobjectcollection[i].isDestroyed ) gameobjectcollection[i] = null;//or whatever to remove by index
    }
    

    【讨论】:

    • 但是我必须为从 Entity 继承的每个对象添加该变量,即使只有 1 个对象类型使用它。这不被认为是不好的做法吗?
    • 在我的例子中,因为每个对象都是游戏对象,并且每个对象最终都可能被销毁(除了一些像记分板这样的对象),所以拥有它是有意义的。你可以有一个可销毁对象的子类,然后循环遍历这些对象,即 gameobjects.where(go=>typeof(go) is destroyable)(伪代码)
    猜你喜欢
    • 2021-01-05
    • 2013-08-06
    • 1970-01-01
    • 2016-07-21
    • 1970-01-01
    • 2015-03-22
    • 1970-01-01
    • 1970-01-01
    • 2021-05-12
    相关资源
    最近更新 更多